From e4ae5b4a9dce0de9357cdceaadc78399018de0f8 Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Sat, 3 May 2025 19:34:26 -0400 Subject: [PATCH] Add high-level Decrypt() and Encrypt() functions for use by importing applications --- example.go | 14 ++------------ wrappers/aes.go | 14 +++++++------- wrappers/chacha.go | 5 ++--- wrappers/highLevel.go | 20 ++++++++++++++++++++ 4 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 wrappers/highLevel.go diff --git a/example.go b/example.go index fdabec7..54b90b6 100644 --- a/example.go +++ b/example.go @@ -24,10 +24,6 @@ import ( // RPC password sharing // TODO Enhancements: -// Keyfile: -// Store: -// Hash of passphrase (prevent user from losing data by accidentally providing incorrect passphrase during encryption) -// Order of algorithms (determined randomly at keyfile generation) // Security: // Play with nonce sizes and Argon2 parameters to find the best speed-security balance // Standalone cmd: @@ -41,12 +37,7 @@ func main() { case 3: // decrypt file encBytes, _ := os.ReadFile("encrypted-example.txt") - decBytes, err := wrappers.DecryptCha(encBytes, []byte(os.Args[2])) - if err != nil { - fmt.Println(err) - return - } - decBytes, err = wrappers.DecryptAES(decBytes, []byte(os.Args[2])) + decBytes, err := wrappers.Decrypt(encBytes, []byte(os.Args[2])) if err != nil { fmt.Println(err) return @@ -54,8 +45,7 @@ func main() { fmt.Println(string(decBytes)) case 4: // encrypt data (from cli args) - encBytes := wrappers.EncryptAES([]byte(os.Args[2]), []byte(os.Args[3])) - encBytes = wrappers.EncryptCha(encBytes, []byte(os.Args[3])) + encBytes := wrappers.Encrypt([]byte(os.Args[2]), []byte(os.Args[3])) os.WriteFile("encrypted-example.txt", encBytes, 0644) default: // request served data diff --git a/wrappers/aes.go b/wrappers/aes.go index c91d6d4..45f5922 100644 --- a/wrappers/aes.go +++ b/wrappers/aes.go @@ -13,7 +13,7 @@ const ( ) // EncryptAES encrypts data using AES-256-GCM. -func EncryptAES(data []byte, passphrase []byte) []byte { +func encryptAES(decBytes []byte, passphrase []byte) []byte { // generate a random salt salt := make([]byte, saltSize) io.ReadFull(rand.Reader, salt) @@ -32,7 +32,7 @@ func EncryptAES(data []byte, passphrase []byte) []byte { io.ReadFull(rand.Reader, nonce) // encrypt the data - ciphertext := aesGCM.Seal(nil, nonce, data, nil) + ciphertext := aesGCM.Seal(nil, nonce, decBytes, nil) // format: salt + nonce + ciphertext result := make([]byte, 0, saltSize+nonceSizeAES+len(ciphertext)) @@ -44,15 +44,15 @@ func EncryptAES(data []byte, passphrase []byte) []byte { } // DecryptAES decrypts data using AES256-GCM. -func DecryptAES(encryptedData []byte, passphrase []byte) ([]byte, error) { - if len(encryptedData) < saltSize+nonceSizeAES { +func decryptAES(encBytes []byte, passphrase []byte) ([]byte, error) { + if len(encBytes) < saltSize+nonceSizeAES { return nil, errors.New("AES256-GCM: Encrypted data is too short") } // extract salt, nonce, and ciphertext - salt := encryptedData[:saltSize] - nonce := encryptedData[saltSize : saltSize+nonceSizeAES] - ciphertext := encryptedData[saltSize+nonceSizeAES:] + salt := encBytes[:saltSize] + nonce := encBytes[saltSize : saltSize+nonceSizeAES] + ciphertext := encBytes[saltSize+nonceSizeAES:] // derive key from passphrase using the salt key := deriveKey(passphrase, salt) diff --git a/wrappers/chacha.go b/wrappers/chacha.go index d6cd4ad..270a277 100644 --- a/wrappers/chacha.go +++ b/wrappers/chacha.go @@ -13,13 +13,12 @@ const ( ) // EncryptCha encrypts data using ChaCha20-Poly1305. -func EncryptCha(data []byte, passphrase []byte) []byte { +func encryptCha(data []byte, passphrase []byte) []byte { // generate a random salt salt := make([]byte, saltSize) io.ReadFull(rand.Reader, salt) // derive key from passphrase using the salt - // TODO ensure the passphrase is consistent (store a hashed version to compare against) key := deriveKey(passphrase, salt) // create ChaCha20-Poly1305 cipher @@ -42,7 +41,7 @@ func EncryptCha(data []byte, passphrase []byte) []byte { } // DecryptCha decrypts data using ChaCha20-Poly1305. -func DecryptCha(encryptedData []byte, passphrase []byte) ([]byte, error) { +func decryptCha(encryptedData []byte, passphrase []byte) ([]byte, error) { if len(encryptedData) < saltSize+nonceSizeCha { return nil, errors.New("ChaCha20-Poly1305: Encrypted data is too short") } diff --git a/wrappers/highLevel.go b/wrappers/highLevel.go new file mode 100644 index 0000000..f4c3ae7 --- /dev/null +++ b/wrappers/highLevel.go @@ -0,0 +1,20 @@ +package wrappers + +func Decrypt(encBytes []byte, passphrase []byte) ([]byte, error) { + var err error = nil + encBytes, err = decryptCha(encBytes, passphrase) + if err != nil { + return nil, err + } + encBytes, err = decryptAES(encBytes, passphrase) + if err != nil { + return nil, err + } + return encBytes, err +} + +func Encrypt(decBytes []byte, passphrase []byte) []byte { + decBytes = encryptAES(decBytes, passphrase) + decBytes = encryptCha(decBytes, passphrase) + return decBytes +}