siyuan-note/siyuan · error

unsupported encrypted envelope spec

Error message

unsupported encrypted envelope spec

What it means

Raised by EncryptionNonce when the spec byte at offset len(encryptionMagic) (4) does not equal EncryptionSpec (currently 1). The spec byte identifies the envelope format version; a mismatch means the blob is either a future/incompatible version or corrupted at that byte.

Source

Thrown at kernel/util/kdf.go:110

func Encrypt(key, plaintext []byte) ([]byte, error) {
	return encryptGCM(key, plaintext, nil, "Encrypt")
}

// Decrypt 对应 Encrypt 的解密。密钥错误、格式无效或密文被篡改时返回错误。
func Decrypt(key, ciphertext []byte) ([]byte, error) {
	return decryptGCM(key, ciphertext, nil, "Decrypt")
}

// EncryptionNonce 从 AES-GCM 密文信封中提取 nonce。
func EncryptionNonce(ciphertext []byte) ([]byte, error) {
	if !hasEncryptionMagic(ciphertext) {
		return nil, errors.New("invalid encrypted envelope magic")
	}
	if len(ciphertext) < encryptionEnvelopeHeaderSize {
		return nil, errors.New("encrypted envelope too short")
	}
	if ciphertext[len(encryptionMagic)] != EncryptionSpec {
		return nil, errors.New("unsupported encrypted envelope spec")
	}
	if ciphertext[len(encryptionMagic)+1] != encryptionAlgorithmAES256GCM {
		return nil, errors.New("unsupported encrypted envelope algorithm")
	}
	nonceLength := int(ciphertext[len(encryptionMagic)+2])
	if nonceLength == 0 || len(ciphertext) < encryptionEnvelopeHeaderSize+nonceLength {
		return nil, errors.New("invalid encrypted envelope nonce length")
	}
	return append([]byte(nil), ciphertext[encryptionEnvelopeHeaderSize:encryptionEnvelopeHeaderSize+nonceLength]...), nil
}

// DeriveSubKey 用 HKDF-SHA256 从主 DEK 派生用途隔离的子密钥。
// 同一 (dek, purpose) 多次调用结果一致;不同 purpose 派生出相互独立的子密钥,
// 实现用途分离——.sy/assets/AV 各用独立子密钥,互不可替代,限制单点密钥泄漏的影响面。
func DeriveSubKey(dek []byte, purpose string) []byte {
	// HKDF info 用 purpose 字节;salt 为 nil(DEK 本身已是高熵随机密钥,无需额外 salt)
	r := hkdf.New(sha256.New, dek, nil, []byte(purpose))
	out := make([]byte, 32) // AES-256

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Upgrade the kernel to a version that understands the spec byte in the blob.
  2. If the spec byte is unexpected due to corruption, restore from backup.
  3. Do not hand-edit envelope bytes; regenerate via the official crypto flow.
Defensive patterns

Strategy: validation

Validate before calling

if util.IsCiphertext(blob) && len(blob) > 4 && blob[4] != byte(util.EncryptionSpec) {
    return fmt.Errorf("envelope spec %d is unsupported by this kernel", blob[4])
}

Prevention

When it happens

Trigger: EncryptionNonce reads a blob whose 5th byte is not 1. Happens if the blob was produced by a newer SiYuan using a higher spec, or if the byte was flipped by corruption.

Common situations: Opening a notebook created by a newer kernel version that bumped EncryptionSpec; bit-rot in the conf; an older kernel reading a newer-format envelope.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/a05ded3c8101af52. Report an issue: GitHub.