Skip to content

fix: zero sensitive crypto key material after use#81

Merged
LiranCohen merged 1 commit into
mainfrom
fix/crypto-zeroize
Feb 26, 2026
Merged

fix: zero sensitive crypto key material after use#81
LiranCohen merged 1 commit into
mainfrom
fix/crypto-zeroize

Conversation

@LiranCohen

Copy link
Copy Markdown
Contributor

Summary

Closes #78.

Zero ephemeral private keys, ECDH shared secrets, KEKs, CEKs, and intermediate HKDF derivation keys immediately after use to reduce the window where sensitive material remains in process memory.

Changes

  • ecdh.go: defer clear() for ephemeral private key, shared secret, and KEK in ECDHESWrapKey; shared secret and KEK in ECDHESUnwrapKey
  • jwe.go: defer clear(cek) in EncryptData, DecryptData, DecryptDataWithScheme
  • hkdf.go: clear(currentKey) before reassignment and on error path in DeriveKeyBytes
  • protocol.go: defer clear(protocolLevelKey) in InjectEncryptionDirectives, clear(childPrivateKey) after recursive call in injectEncryptionRecursive
  • protocol.go: New Close() method on EncryptionKeyManager for graceful shutdown — zeros RootPrivateKey and all contextKeys

Design notes

  • Go's GC can relocate heap objects, so zeroization is not a perfect guarantee, but it significantly reduces the attack surface by clearing keys as soon as they're no longer needed.
  • Immutable Go strings (e.g., base64-encoded JWK D fields) cannot be zeroed; this is a known language limitation.
  • EncryptionKeyManager.RootPrivateKey is needed for the process lifetime, so it gets a Close() method for graceful shutdown rather than immediate zeroization.
  • Uses Go's built-in clear() (available since Go 1.21) for byte slices.

Verification

  • go build ./... — zero errors
  • go vet ./... — zero warnings
  • go test ./... -count=1 -race — all tests pass, no data races

Zero ephemeral private keys, ECDH shared secrets, KEKs, CEKs, and
intermediate HKDF derivation keys immediately after use to reduce the
window where sensitive material remains in process memory.

Changes:
- ecdh.go: defer clear() for ephPriv, sharedSecret, kek in ECDHESWrapKey
  and sharedSecret, kek in ECDHESUnwrapKey
- jwe.go: defer clear(cek) in EncryptData, DecryptData, DecryptDataWithScheme
- hkdf.go: clear(currentKey) before reassignment and on error in DeriveKeyBytes
- protocol.go: defer clear(protocolLevelKey) in InjectEncryptionDirectives,
  clear(childPrivateKey) after recursive call in injectEncryptionRecursive
- protocol.go: add Close() method to EncryptionKeyManager for graceful
  shutdown zeroization of RootPrivateKey and all contextKeys

Build, vet, and tests (with -race) all pass.
@LiranCohen LiranCohen merged commit 20f5bd0 into main Feb 26, 2026
2 checks passed
@LiranCohen LiranCohen deleted the fix/crypto-zeroize branch February 26, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: crypto key material not zeroed after use

1 participant