Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ go.work.sum
# env file
.env
wallet.db
uploads/
377 changes: 256 additions & 121 deletions README.md

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions aesutils/aes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package aesutils

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/hex"
"fmt"
)

// Encrypt the private key using AES-GCM
func EncryptPrivateKey(privateKey, secretKey string) (string, error) {
// Create an AES cipher
block, err := aes.NewCipher([]byte(secretKey)[:32])
if err != nil {
fmt.Println("failed to create an aes cipher")
return "", err
}

// Use AES-GCM for encryption
aesGCM, err := cipher.NewGCM(block)
if err != nil {
fmt.Println("failed to create aes gcm")
return "", err
}

// Generate a random nonce
nonce := make([]byte, aesGCM.NonceSize())
if _, err := rand.Read(nonce); err != nil {
fmt.Println("failed to create a random nonce")
return "", err
}

// Encrypt the private key
ciphertext := aesGCM.Seal(nonce, nonce, []byte(privateKey), nil)

// Return encrypted data as base64
return hex.EncodeToString(ciphertext), nil
}

// Decrypt the private key
func DecryptPrivateKey(encryptedKey, secretKey string) (string, error) {
ciphertext, err := hex.DecodeString(encryptedKey)
if err != nil {
return "", nil
}

// Create an AES cipher
block, err := aes.NewCipher([]byte(secretKey)[:32])
if err != nil {
return "", err
}

// Use AES-GCM for decryption
aesGCM, err := cipher.NewGCM(block)
if err != nil {
return "", err
}

// Since we know the ciphertext is actually nonce+ciphertext
// And len(nonce) == NonceSize(). We can separate the two.
nonceSize := aesGCM.NonceSize()
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]

// Decrypt the private key
plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
if err != nil {
return "", err
}

return string(plaintext), nil
}
33 changes: 33 additions & 0 deletions aesutils/aes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package aesutils

import (
"testing"

"golang.org/x/crypto/bcrypt"
)

func AESTest(t *testing.T, privateKey string, secretKey string) {
hashedSecretKey, err := bcrypt.GenerateFromPassword([]byte(secretKey), bcrypt.DefaultCost)
if err != nil {
t.Fatal("could not hash secret key, err", err)
}

key := string(hashedSecretKey[:32])

encryptedPrivateKey, err := EncryptPrivateKey(privateKey, key)
if err != nil {
t.Fatal("failed to encrypt private key, err:", err)
}
decryptedPrivateKey, err := DecryptPrivateKey(encryptedPrivateKey, key)
if err != nil {
t.Fatal("failed to decrypt private key, err:", err)
}
if decryptedPrivateKey != privateKey {
t.Fatal("mismatched decrypted private key")
}
}

func TestAES(t *testing.T) {
AESTest(t, "04b82f061b69471dc877ffc828687970da99fd2d65c6da7f08b9d9a793bf7262", "N1PCdw3M2B1TfJhoaY2mL736p2vCUc47")
AESTest(t, "randomstring", "abc123")
}
Loading