OpenNHP/opennhp · error
unsupported cipher type for CBC
Error message
unsupported cipher type for CBC: %d
What it means
CBCEncryption only supports block ciphers (AES-256 and SM4) for CBC mode. When the GcmTypeEnum passed is not GCM_AES256 or GCM_SM4 — e.g. GCM_CHACHA20POLY1305 handled earlier via ErrNotApplicable, or any unknown numeric value — the default branch rejects it because CBC mode cannot be applied to a stream cipher or an unregistered type.
Solutions
- Pass only GCM_AES256 or GCM_SM4 to CBCEncryption; verify the enum value at the call site.
- If the caller wants ChaCha20Poly1305, use AeadFromKey/AEAD encryption instead — CBC is ErrNotApplicable for stream ciphers.
- Validate the cipher-type config field (e.g. in config.toml) maps to a supported GcmTypeEnum before calling.
- Add the missing case to CBCEncryption if a new block cipher was introduced to the enum.
Example fix
// before data, err := core.CBCEncryption(core.GCM_CHACHA20POLY1305, key, plaintext, false) // after data, err := core.CBCEncryption(core.GCM_AES256, key, plaintext, false) // or for ChaCha20Poly1305 use AEAD: aead, err := core.AeadFromKey(core.GCM_CHACHA20POLY1305, key)
Defensive patterns
Strategy: validation
Validate before calling
func cbcSupported(t core.GcmTypeEnum) bool { return t == core.GCM_AES256 || t == core.GCM_SM4 }
if !cbcSupported(scheme) { return fmt.Errorf("scheme %v cannot use CBC", scheme) } Type guard
func isBlockCipherCBC(t core.GcmTypeEnum) bool { return t == core.GCM_AES256 || t == core.GCM_SM4 } Try / catch
data, err := core.CBCEncryption(t, key, pt, false)
if errors.Is(err, core.ErrNotApplicable) {
// stream cipher: fall back to AEAD path
} else if err != nil {
return fmt.Errorf("CBC encrypt: %w", err)
} Prevention
- Centralize cipher-scheme selection in one config constant; never pass raw ints.
- Use AEAD (AeadFromKey) for ChaCha20Poly1305; reserve CBC helpers for block ciphers only.
- Validate cipher-type config fields against the enum at startup.
When it happens
Trigger: Calling CBCEncryption(t, key, plaintext, inPlace) with a GcmTypeEnum value other than GCM_AES256 or GCM_SM4, such as GCM_CHACHA20POLY1305 misuse reaching the default branch, a zero-value enum, or a cipher type loaded from config that doesn't match any case.
Common situations: Cipher scheme read from TOML config or wire data as an arbitrary integer; code refactors that map a Noise cipher suite (e.g. ChaCha20Poly1305) to CBC helpers; new enum added to GcmTypeEnum without updating CBCEncryption.
Related errors
- failed to create device
- failed to create device from new key
- keystore: generate otp
- failed to create blake2s hash
- failed to create AES-GCM
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/95f12ed7cf299616.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/crypto.go:210
case GCM_AES256:
block, err = aes.NewCipher(key[:])
if err != nil {
return nil, fmt.Errorf("failed to create AES cipher for CBC: %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: %w", err)
}
iv = key[16:]
case GCM_CHACHA20POLY1305:
return nil, ErrNotApplicable
default:
return nil, fmt.Errorf("unsupported cipher type for CBC: %d", t)
}
var paddedPlainText []byte
if len(plaintext)%block.BlockSize() == 0 {
// skip padding
paddedPlainText = plaintext
} else {
pkcs7 := padding.NewPKCS7Padding(uint(block.BlockSize()))
paddedPlainText = pkcs7.Pad(plaintext)
}
var ciphertext []byte
if inPlace {
ciphertext = paddedPlainText
} else {
ciphertext = make([]byte, 0, len(plaintext))
}
View on GitHub (pinned to 6e04ca5ff0)