OpenNHP/opennhp · error
failed to create AES cipher for CBC decryption
Error message
failed to create AES cipher for CBC decryption: %w
What it means
In CBCDecryption's GCM_AES256 branch, aes.NewCipher(key[:]) failed. Go's AES implementation only accepts 16/24/32-byte keys, so this wraps the underlying key-length error. With SymmetricKeySize keys this should never occur, meaning the caller effectively passed a wrong-sized or corrupted key buffer.
Solutions
- Generate keys with the daemon's `keygen --curve` output or the library's key derivation so the AES key is exactly 32 bytes.
- Check that the key was fully decoded (base64/hex) and not truncated before wrapping it in the [SymmetricKeySize]byte array.
- Confirm the config.toml private key matches the curve/scheme expected (curve25519/AES vs SM2/SM4).
- Log/inspect the wrapped %w error; it names the exact key-length violation.
Example fix
// before
keyBytes, _ := hex.DecodeString(cfg.Key) // may be 24 or 40 bytes
var key [core.SymmetricKeySize]byte
copy(key[:], keyBytes)
// after
if len(keyBytes) != core.SymmetricKeySize {
return fmt.Errorf("key must be %d bytes, got %d", core.SymmetricKeySize, len(keyBytes))
}
copy(key[:], keyBytes) Defensive patterns
Strategy: validation
Validate before calling
if len(keyBytes) != core.SymmetricKeySize {
return fmt.Errorf("AES key must be %d bytes, got %d", core.SymmetricKeySize, len(keyBytes))
} Try / catch
plain, err := core.CBCDecryption(core.GCM_AES256, key, ct, false)
if err != nil {
return fmt.Errorf("CBC decrypt failed (check key material): %w", err)
} Prevention
- Generate keys with the daemon keygen command instead of hand-built byte arrays.
- Assert key length immediately after decoding from config or network.
- Keep AES and SM4 key material in separate, clearly named config fields.
When it happens
Trigger: Calling CBCDecryption with GCM_AES256 and a *[SymmetricKeySize]byte whose backing bytes were constructed from a key of invalid AES length (not 16/24/32 bytes), typically a truncated, mis-decoded, or wrong-format key.
Common situations: Key loaded from a hex/base64 string decoded to a non-standard length; key material from an older config version with a different key size; hand-built byte arrays instead of the library's keygen output.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- failed to create AES cipher
- failed to create AES-GCM
- failed to create AES cipher for CBC
- failed to create SM4 cipher for CBC decryption
- cipherText too short: need at least
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/e4f17620bfac8a62.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/crypto.go:244
ciphertext = make([]byte, 0, len(plaintext))
}
mode := cipher.NewCBCEncrypter(block, iv)
// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(ciphertext, paddedPlainText)
return ciphertext, nil
}
func CBCDecryption(t GcmTypeEnum, key *[SymmetricKeySize]byte, ciphertext []byte, inPlace bool) ([]byte, error) {
var block cipher.Block
var iv []byte
var err error
switch t {
case GCM_AES256:
block, err = aes.NewCipher(key[:])
if err != nil {
return nil, fmt.Errorf("failed to create AES cipher for CBC decryption: %w", err)
}
iv = key[8:24]
case GCM_SM4:
block, err = sm4.NewCipher(key[:16])
if err != nil {
return nil, fmt.Errorf("failed to create SM4 cipher for CBC decryption: %w", err)
}
iv = key[16:]
case GCM_CHACHA20POLY1305:
return nil, ErrNotApplicable
default:
return nil, fmt.Errorf("unsupported cipher type for CBC decryption: %d", t)
}
// Validate ciphertext: must be at least one block and a multiple of block sizeView on GitHub (pinned to 6e04ca5ff0)