github.com/hungdoo/bot@v0.0.0-20240325145135-dd1f386f7b81/src/packages/command/tomb/secret.go (about)

     1  package tomb
     2  
     3  import (
     4  	"crypto/aes"
     5  	"crypto/cipher"
     6  	"crypto/ecdsa"
     7  	"crypto/rand"
     8  	"encoding/base64"
     9  	"fmt"
    10  	"io"
    11  	"os"
    12  	"strings"
    13  
    14  	"github.com/ethereum/go-ethereum/crypto"
    15  	"github.com/hungdoo/bot/src/packages/dotenv"
    16  )
    17  
    18  // Encrypt encrypts the plaintext using AES-GCM encryption.
    19  func Encrypt(plaintext []byte, key []byte) (string, error) {
    20  	block, err := aes.NewCipher(key)
    21  	if err != nil {
    22  		return "", err
    23  	}
    24  
    25  	gcm, err := cipher.NewGCM(block)
    26  	if err != nil {
    27  		return "", err
    28  	}
    29  
    30  	nonce := make([]byte, gcm.NonceSize())
    31  	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
    32  		return "", err
    33  	}
    34  
    35  	ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
    36  	return base64.StdEncoding.EncodeToString(ciphertext), nil
    37  }
    38  
    39  // Decrypt decrypts the ciphertext using AES-GCM decryption.
    40  func Decrypt(ciphertext string, key []byte) ([]byte, error) {
    41  	block, err := aes.NewCipher(key)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	gcm, err := cipher.NewGCM(block)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	decodedCiphertext, err := base64.StdEncoding.DecodeString(ciphertext)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	nonceSize := gcm.NonceSize()
    57  	if len(decodedCiphertext) < nonceSize {
    58  		return nil, fmt.Errorf("ciphertext is too short")
    59  	}
    60  
    61  	nonce, cipher := decodedCiphertext[:nonceSize], decodedCiphertext[nonceSize:]
    62  	plaintext, err := gcm.Open(nil, nonce, cipher, nil)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	return plaintext, nil
    68  }
    69  
    70  func LoadSecrets(idx int, key string) (*ecdsa.PrivateKey, error) {
    71  	encryptedContent, err := os.ReadFile(dotenv.GetEnv("SECRET_FILE"))
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	encryptedSecrets := strings.Split(string(encryptedContent), ",")
    77  	if len(encryptedSecrets) <= idx {
    78  		return nil, fmt.Errorf("encryptedSecrets out-of-bound: length[%v], idx[%v]", len(encryptedSecrets), idx)
    79  	}
    80  
    81  	// Convert the byte slice to a string (assuming the secret is text-based)
    82  	decrypted, err := Decrypt(string(encryptedSecrets[idx]), []byte(key))
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	pk, err := crypto.HexToECDSA(string(decrypted))
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	return pk, nil
    92  }