2019-03-08 17:42:50 +01:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2019-03-08 17:42:50 +01:00
package secret
import (
2020-10-05 07:49:33 +02:00
"crypto/aes"
"crypto/cipher"
2019-03-08 17:42:50 +01:00
"crypto/rand"
2024-02-25 14:32:13 +01:00
"crypto/sha256"
2019-03-08 17:42:50 +01:00
"encoding/base64"
2020-10-05 07:49:33 +02:00
"encoding/hex"
"errors"
2023-05-07 19:29:43 +08:00
"fmt"
2020-10-05 07:49:33 +02:00
"io"
2019-03-08 17:42:50 +01:00
)
2020-10-05 07:49:33 +02:00
// AesEncrypt encrypts text and given key with AES.
func AesEncrypt ( key , text [ ] byte ) ( [ ] byte , error ) {
block , err := aes . NewCipher ( key )
if err != nil {
2023-05-07 19:29:43 +08:00
return nil , fmt . Errorf ( "AesEncrypt invalid key: %v" , err )
2020-10-05 07:49:33 +02:00
}
b := base64 . StdEncoding . EncodeToString ( text )
ciphertext := make ( [ ] byte , aes . BlockSize + len ( b ) )
iv := ciphertext [ : aes . BlockSize ]
2023-05-07 19:29:43 +08:00
if _ , err = io . ReadFull ( rand . Reader , iv ) ; err != nil {
return nil , fmt . Errorf ( "AesEncrypt unable to read IV: %w" , err )
2020-10-05 07:49:33 +02:00
}
cfb := cipher . NewCFBEncrypter ( block , iv )
cfb . XORKeyStream ( ciphertext [ aes . BlockSize : ] , [ ] byte ( b ) )
return ciphertext , nil
}
// AesDecrypt decrypts text and given key with AES.
func AesDecrypt ( key , text [ ] byte ) ( [ ] byte , error ) {
block , err := aes . NewCipher ( key )
if err != nil {
return nil , err
}
if len ( text ) < aes . BlockSize {
2023-05-07 19:29:43 +08:00
return nil , errors . New ( "AesDecrypt ciphertext too short" )
2020-10-05 07:49:33 +02:00
}
iv := text [ : aes . BlockSize ]
text = text [ aes . BlockSize : ]
cfb := cipher . NewCFBDecrypter ( block , iv )
cfb . XORKeyStream ( text , text )
data , err := base64 . StdEncoding . DecodeString ( string ( text ) )
if err != nil {
2023-05-07 19:29:43 +08:00
return nil , fmt . Errorf ( "AesDecrypt invalid decrypted base64 string: %w" , err )
2020-10-05 07:49:33 +02:00
}
return data , nil
}
// EncryptSecret encrypts a string with given key into a hex string
2021-12-20 05:41:31 +01:00
func EncryptSecret ( key , str string ) ( string , error ) {
2020-10-05 07:49:33 +02:00
keyHash := sha256 . Sum256 ( [ ] byte ( key ) )
plaintext := [ ] byte ( str )
ciphertext , err := AesEncrypt ( keyHash [ : ] , plaintext )
if err != nil {
2023-05-07 19:29:43 +08:00
return "" , fmt . Errorf ( "failed to encrypt by secret: %w" , err )
2020-10-05 07:49:33 +02:00
}
return hex . EncodeToString ( ciphertext ) , nil
}
// DecryptSecret decrypts a previously encrypted hex string
2023-05-07 19:29:43 +08:00
func DecryptSecret ( key , cipherHex string ) ( string , error ) {
2020-10-05 07:49:33 +02:00
keyHash := sha256 . Sum256 ( [ ] byte ( key ) )
2023-05-07 19:29:43 +08:00
ciphertext , err := hex . DecodeString ( cipherHex )
2020-10-05 07:49:33 +02:00
if err != nil {
2023-05-07 19:29:43 +08:00
return "" , fmt . Errorf ( "failed to decrypt by secret, invalid hex string: %w" , err )
2020-10-05 07:49:33 +02:00
}
plaintext , err := AesDecrypt ( keyHash [ : ] , ciphertext )
if err != nil {
2023-05-07 19:29:43 +08:00
return "" , fmt . Errorf ( "failed to decrypt by secret, the key (maybe SECRET_KEY?) might be incorrect: %w" , err )
2020-10-05 07:49:33 +02:00
}
return string ( plaintext ) , nil
}