siyuan-note/siyuan · error
invalid encrypted envelope magic
Error message
invalid encrypted envelope magic
What it means
EncryptionNonce parses SiYuan's SENC envelope format (magic 'SENC' + spec + algorithm + nonce length + nonce). The input does not start with the 4-byte 'SENC' magic, meaning it is not an encrypted envelope produced by Encrypt/EncryptWithAAD. The function refuses to parse arbitrary or foreign bytes.
Solutions
- Verify the input is a complete envelope returned by util.Encrypt/EncryptWithAAD, not raw ciphertext or plaintext
- Check that the data source actually wrote an encrypted envelope (notebook encryption was enabled when the data was written)
- If the data came from another tool, decrypt it with that tool's method instead of SiYuan's EncryptionNonce
- If bytes were truncated/reordered in transit, re-fetch or restore the original file
Example fix
// before
nonce, err := util.EncryptionNonce(rawAESCiphertext) // no SENC header
// after
envelope, err := util.Encrypt(key, plaintext)
if err != nil { return err }
nonce, err := util.EncryptionNonce(envelope) Defensive patterns
Strategy: validation
Validate before calling
func isSENCEnvelope(b []byte) bool {
return len(b) >= 7 && b[0]=='S' && b[1]=='E' && b[2]=='N' && b[3]=='C'
}
if !isSENCEnvelope(data) { return errors.New("not a SENC envelope") } Type guard
func hasEncHeader(b []byte) bool {
return len(b) >= 4 && string(b[:4]) == "SENC"
} Try / catch
nonce, err := util.EncryptionNonce(ciphertext)
if err != nil {
return fmt.Errorf("not a SiYuan encrypted envelope: %w", err)
} Prevention
- Only pass output of util.Encrypt/EncryptWithAAD to EncryptionNonce
- Never strip or re-encode the envelope header before parsing
- Check for the 'SENC' prefix before parsing third-party data
When it happens
Trigger: Calling EncryptionNonce with ciphertext that was not produced by util.Encrypt/EncryptWithAAD — e.g. raw AES-GCM output from another tool, plaintext bytes, a base64 string decoded incorrectly, or data encrypted by a different format version.
Common situations: Inspecting legacy (pre-encryption-feature) notebook data, decrypting data encrypted by an external tool, passing the wrong slice (e.g. header-stripped ciphertext), or corruption/truncation overwrote the header.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- encrypted envelope too short
- unsupported encrypted envelope algorithm
- Argon2id KeyLength must be 32
- Argon2id Memory too low (minimum 64 MB)
- cannot save incomplete notebook crypto configuration
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/6fe9c7495c5bda53.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/kdf.go:104
func DeriveKey(password string, salt []byte, p Argon2Params) []byte {
return argon2.IDKey([]byte(password), salt, p.Iterations, p.Memory, p.Parallelism, p.KeyLength)
}
// Encrypt 用 AES-256-GCM 加密。每次调用生成随机 nonce,因此同一明文多次加密结果不同。
// 返回格式:magic(4B) || spec(1B) || algorithm(1B) || nonceLength(1B) || nonce || ciphertext || GCM tag(16B)。
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 派生用途隔离的子密钥。View on GitHub (pinned to 9f775e8a12)