From eef23328230449591c448381aa72c683997bf2da Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 15 Jul 2025 08:42:46 +0200 Subject: [PATCH] Fix EncryptWithPassphrase to accept LockedBuffer for data parameter - Changed EncryptWithPassphrase to accept *memguard.LockedBuffer instead of []byte - Updated all callers to pass LockedBuffer: - CreatePassphraseUnlocker in vault/unlockers.go - Keychain unlocker in keychainunlocker.go - Tests in passphrase_test.go - Removed intermediate dataBuffer creation since data is now already protected - This ensures sensitive data is protected in memory throughout encryption --- internal/secret/crypto.go | 13 ++++++------- internal/secret/keychainunlocker.go | 2 +- internal/secret/passphrase_test.go | 5 +++-- internal/secret/secret.go | 1 - internal/vault/unlockers.go | 4 +++- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/internal/secret/crypto.go b/internal/secret/crypto.go index 2233a51..710ed86 100644 --- a/internal/secret/crypto.go +++ b/internal/secret/crypto.go @@ -69,8 +69,11 @@ func DecryptWithIdentity(data []byte, identity age.Identity) ([]byte, error) { } // EncryptWithPassphrase encrypts data using a passphrase with age's scrypt-based encryption -// The passphrase parameter should be a LockedBuffer for secure memory handling -func EncryptWithPassphrase(data []byte, passphrase *memguard.LockedBuffer) ([]byte, error) { +// Both data and passphrase parameters should be LockedBuffers for secure memory handling +func EncryptWithPassphrase(data *memguard.LockedBuffer, passphrase *memguard.LockedBuffer) ([]byte, error) { + if data == nil { + return nil, fmt.Errorf("data buffer is nil") + } if passphrase == nil { return nil, fmt.Errorf("passphrase buffer is nil") } @@ -82,11 +85,7 @@ func EncryptWithPassphrase(data []byte, passphrase *memguard.LockedBuffer) ([]by return nil, fmt.Errorf("failed to create scrypt recipient: %w", err) } - // Create a secure buffer for the data - dataBuffer := memguard.NewBufferFromBytes(data) - defer dataBuffer.Destroy() - - return EncryptToRecipient(dataBuffer, recipient) + return EncryptToRecipient(data, recipient) } // DecryptWithPassphrase decrypts data using a passphrase with age's scrypt-based decryption diff --git a/internal/secret/keychainunlocker.go b/internal/secret/keychainunlocker.go index d6c9eb9..8979455 100644 --- a/internal/secret/keychainunlocker.go +++ b/internal/secret/keychainunlocker.go @@ -368,7 +368,7 @@ func CreateKeychainUnlocker(fs afero.Fs, stateDir string) (*KeychainUnlocker, er passphraseBuffer := memguard.NewBufferFromBytes([]byte(agePrivKeyPassphrase)) defer passphraseBuffer.Destroy() - encryptedAgePrivKey, err := EncryptWithPassphrase(agePrivKeyBuffer.Bytes(), passphraseBuffer) + encryptedAgePrivKey, err := EncryptWithPassphrase(agePrivKeyBuffer, passphraseBuffer) if err != nil { return nil, fmt.Errorf("failed to encrypt age private key with passphrase: %w", err) } diff --git a/internal/secret/passphrase_test.go b/internal/secret/passphrase_test.go index 36e56d3..c00ab14 100644 --- a/internal/secret/passphrase_test.go +++ b/internal/secret/passphrase_test.go @@ -76,10 +76,11 @@ func TestPassphraseUnlockerWithRealFS(t *testing.T) { // Test encrypting private key with passphrase t.Run("EncryptPrivateKey", func(t *testing.T) { - privKeyData := []byte(agePrivateKey) + privKeyBuffer := memguard.NewBufferFromBytes([]byte(agePrivateKey)) + defer privKeyBuffer.Destroy() passphraseBuffer := memguard.NewBufferFromBytes([]byte(testPassphrase)) defer passphraseBuffer.Destroy() - encryptedPrivKey, err := secret.EncryptWithPassphrase(privKeyData, passphraseBuffer) + encryptedPrivKey, err := secret.EncryptWithPassphrase(privKeyBuffer, passphraseBuffer) if err != nil { t.Fatalf("Failed to encrypt private key: %v", err) } diff --git a/internal/secret/secret.go b/internal/secret/secret.go index 0c8e8e8..c706af4 100644 --- a/internal/secret/secret.go +++ b/internal/secret/secret.go @@ -62,7 +62,6 @@ func NewSecret(vault VaultInterface, name string) *Secret { } } - // GetValue retrieves and decrypts the current version's value using the provided unlocker func (s *Secret) GetValue(unlocker Unlocker) ([]byte, error) { DebugWith("Getting secret value", diff --git a/internal/vault/unlockers.go b/internal/vault/unlockers.go index 11e6e4e..f4e008a 100644 --- a/internal/vault/unlockers.go +++ b/internal/vault/unlockers.go @@ -346,7 +346,9 @@ func (v *Vault) CreatePassphraseUnlocker(passphrase *memguard.LockedBuffer) (*se // Encrypt private key with passphrase privKeyStr := unlockerIdentity.String() - encryptedPrivKey, err := secret.EncryptWithPassphrase([]byte(privKeyStr), passphrase) + privKeyBuffer := memguard.NewBufferFromBytes([]byte(privKeyStr)) + defer privKeyBuffer.Destroy() + encryptedPrivKey, err := secret.EncryptWithPassphrase(privKeyBuffer, passphrase) if err != nil { return nil, fmt.Errorf("failed to encrypt unlocker private key: %w", err) }