OpenNHP/opennhp · error
failed to create SM4 cipher for CBC decryption
Error message
failed to create SM4 cipher for CBC decryption: %w
What it means
In CBCDecryption's GCM_SM4 branch, sm4.NewCipher(key[:16]) failed. SM4 requires a 16-byte key; the first 16 bytes of the supplied key buffer were invalid for SM4 key construction. Like the AES variant, this indicates malformed key material rather than a transient fault.
Solutions
- Regenerate keys with `nhp-serverd keygen --sm2` (or the matching keygen) so SM4-compatible key material is used.
- Ensure the key passed corresponds to CIPHER_SCHEME_GMSM, not a curve25519/AES key.
- Verify the first 16 bytes of the key slice are the intended SM4 key and the slice was filled correctly.
- Inspect the wrapped %w error for the exact sm4.NewCipher failure reason.
Example fix
// before
sharedKey := core.DeriveCurveKey(...) // 32-byte curve key used with SM4
plain, err := core.CBCDecryption(core.GCM_SM4, sharedKey, ct, false)
// after
if cfg.CipherScheme == core.CIPHER_SCHEME_GMSM {
sharedKey = core.DeriveSMKey(...) // SM-compatible key
} Defensive patterns
Strategy: validation
Validate before calling
if scheme == core.GCM_SM4 && isCurveKey(keyMaterial) {
return errors.New("SM4 requires SM2-scheme key material, not curve25519 key")
} Try / catch
plain, err := core.CBCDecryption(core.GCM_SM4, key, ct, false)
if err != nil {
return fmt.Errorf("SM4 CBC decrypt (verify --sm2 keygen keys): %w", err)
} Prevention
- Use `keygen --sm2` for GMSM deployments and `--curve` otherwise; never mix.
- Tag key material with its scheme and check scheme matches the cipher before use.
- Test decrypt with a known vector at startup to fail fast on bad keys.
When it happens
Trigger: Calling CBCDecryption with GCM_SM4 where the key buffer's first 16 bytes are invalid for the SM4 implementation — e.g. an all-zero, wrong-length, or mis-derived key array passed in.
Common situations: SM2/SM4 (CIPHER_SCHEME_GMSM) deployments where curve keys were generated with --curve instead of --sm2; key bytes copied from a base64 string that decoded to the wrong length; mixing AES and SM4 keys across peers.
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
- invalid key length for SM4-GCM
- failed to create AES cipher for CBC decryption
- invalid key length for AES-256-GCM
- failed to create device
- failed to create device from new key
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/fe8d6d225856eeab.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/crypto.go:251
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 size
if len(ciphertext) < block.BlockSize() {
return nil, fmt.Errorf("ciphertext too short: need at least %d bytes", block.BlockSize())
}
if len(ciphertext)%block.BlockSize() != 0 {
return nil, fmt.Errorf("ciphertext length %d is not a multiple of block size %d", len(ciphertext), block.BlockSize())
}
View on GitHub (pinned to 6e04ca5ff0)