juicedata/juicefs · error

new sm4 cipher

Error message

new sm4 cipher: %s

What it means

newCipher wraps a failure from sm4.NewCipher when constructing the SM4 block cipher for format secret encryption/decryption. The SM4 key (derived via SM3 KDF from the configured key string) was rejected by the implementation, typically because the derived key length is invalid.

Solutions

  1. Check the wrapped error (%s); regenerate the encryption key (e.g. openssl rand -hex 32) and retry
  2. Confirm --cipher is really SM4-GCM and the key file is intact and non-empty
  3. If using SM4 was unintentional, reconfigure with the default AES cipher and a valid key

Example fix

// before
--encrypt-key "" --cipher sm4
// after
openssl rand -hex 32 > /etc/juicefs.key
--encrypt-key /etc/juicefs.key --cipher sm4
Defensive patterns

Strategy: validation

Validate before calling

key, err := os.ReadFile(keyFile)
if err != nil || len(bytes.TrimSpace(key)) == 0 {
    return errors.New("empty encryption key for SM4")
}
// verify cipher round-trips before use:
aead, err := newCipher("sm4-gcm", string(key))
if err != nil { return err }

Try / catch

aead, err := newCipher(algo, key)
if err != nil {
    if strings.HasPrefix(err.Error(), "new sm4 cipher") {
        // regenerate key or switch cipher
    }
    return err
}

Prevention

When it happens

Trigger: Format.Encrypt()/Decrypt() call newCipher(object.SM4GCM, key) and sm4.NewCipher(sm3.Kdf([]byte(key), 16)) returns an error — malformed key material or an SM4 implementation/build constraint issue.

Common situations: Volume configured with cipher SM4-GCM but an empty or exotic-character encrypt key; key file corrupted; building with a toolchain/tags where the SM4 package misbehaves.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/ad5c46e0601bed18. Report an issue: GitHub.

Appendix: source

Thrown at pkg/meta/config.go:212

	if f.MaxClientVersion != "" {
		maxClientVer := version.Parse(f.MaxClientVersion)
		r, err := version.CompareVersions(ver, maxClientVer)
		if err == nil && r > 0 {
			err = fmt.Errorf("allowed maximum version: %s; please use an older client", f.MaxClientVersion)
		}
		if err != nil {
			return err
		}
	}
	return nil
}

func newCipher(algo string, key string) (cipher.AEAD, error) {
	switch algo {
	case object.SM4GCM:
		block, err := sm4.NewCipher(sm3.Kdf([]byte(key), 16))
		if err != nil {
			return nil, fmt.Errorf("new sm4 cipher: %s", err)
		}
		aead, err := cipher.NewGCM(block)
		if err != nil {
			return nil, fmt.Errorf("new sm4 GCM: %s", err)
		}
		return aead, nil
	default:
		hashKey := md5.Sum([]byte(key))
		block, err := aes.NewCipher(hashKey[:])
		if err != nil {
			return nil, fmt.Errorf("new cipher: %s", err)
		}
		aead, err := cipher.NewGCM(block)
		if err != nil {
			return nil, fmt.Errorf("new GCM: %s", err)
		}
		return aead, nil
	}

View on GitHub (pinned to c9a67b23e8)