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

  1. Regenerate keys with `nhp-serverd keygen --sm2` (or the matching keygen) so SM4-compatible key material is used.
  2. Ensure the key passed corresponds to CIPHER_SCHEME_GMSM, not a curve25519/AES key.
  3. Verify the first 16 bytes of the key slice are the intended SM4 key and the slice was filled correctly.
  4. 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

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


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)