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