mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
M-1: compose.yml commented section now enforces JWT_SECRET required syntax
M-3: TLS client config uses TOFU certificate pinning instead of blind
InsecureSkipVerify — SHA-256 fingerprint pinned on first connect,
mismatches rejected on subsequent connections
M-4: TLSOnlyListener plaintext escape hatch gated behind both
ALLOW_PLAINTEXT=true AND ENVIRONMENT=development
M-5: KMS fallback to unencrypted storage is now log.Fatal in production
(ENVIRONMENT != "development"), including Put-time failures
M-6: isKeyShare() now checks org: prefix, key-type prefixes (frost:,
bls:, sr25519:, tfhe:), and hex wallet IDs instead of returning true
M-9: AES-GCM Encrypt/Decrypt accept optional AAD variadic parameter
for context-binding; existing callers remain backward compatible
M-12: Internal /keygen endpoint requires org_id in request body (400 if
missing); orgID propagated to GenerateKeyMessage and audit log
71 lines
2.0 KiB
Go
71 lines
2.0 KiB
Go
package encryption
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"fmt"
|
|
)
|
|
|
|
// EncryptAESGCM encrypts plaintext using AES-GCM with optional context-binding AAD.
|
|
// Key must be 16, 24, or 32 bytes for AES-128, AES-192, or AES-256.
|
|
// The aad parameter binds the ciphertext to a context (e.g. wallet_id or key path),
|
|
// preventing cross-context ciphertext transplant attacks. Pass nil for no AAD
|
|
// (backward compatible, but not recommended for new callers).
|
|
func EncryptAESGCM(plain, key []byte, aad ...[]byte) (ciphertext, nonce []byte, err error) {
|
|
// Validate key length for AES
|
|
switch len(key) {
|
|
case 16, 24, 32:
|
|
// Valid AES key sizes
|
|
default:
|
|
return nil, nil, fmt.Errorf("invalid AES key length: %d (must be 16, 24, or 32 bytes)", len(key))
|
|
}
|
|
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
aead, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
nonce = make([]byte, aead.NonceSize())
|
|
if _, err = rand.Read(nonce); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
var additionalData []byte
|
|
if len(aad) > 0 {
|
|
additionalData = aad[0]
|
|
}
|
|
ciphertext = aead.Seal(nil, nonce, plain, additionalData)
|
|
return ciphertext, nonce, nil
|
|
}
|
|
|
|
// DecryptAESGCM decrypts ciphertext using AES-GCM with optional context-binding AAD.
|
|
// Key must be 16, 24, or 32 bytes for AES-128, AES-192, or AES-256.
|
|
// The aad parameter must match the AAD used during encryption; mismatched AAD
|
|
// causes authentication failure, preventing cross-context transplant attacks.
|
|
func DecryptAESGCM(ciphertext, key, nonce []byte, aad ...[]byte) ([]byte, error) {
|
|
// Validate key length for AES
|
|
switch len(key) {
|
|
case 16, 24, 32:
|
|
// Valid AES key sizes
|
|
default:
|
|
return nil, fmt.Errorf("invalid AES key length: %d (must be 16, 24, or 32 bytes)", len(key))
|
|
}
|
|
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
aead, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var additionalData []byte
|
|
if len(aad) > 0 {
|
|
additionalData = aad[0]
|
|
}
|
|
return aead.Open(nil, nonce, ciphertext, additionalData)
|
|
}
|