siyuan-note/siyuan · error
invalid encrypted envelope nonce length
Error message
invalid encrypted envelope nonce length
What it means
EncryptionNonce reads the nonce length byte (offset 6) and checks it is non-zero and that the envelope actually contains that many bytes after the 7-byte header. A zero length or a length exceeding the remaining buffer means the envelope is malformed or truncated.
Solutions
- Verify the full envelope was written/read — compare file size against the expected envelope length
- Restore the encrypted blob from backup or re-sync it; a truncated GCM envelope is unrecoverable in place
- Check the write path for missing error handling on file writes that could leave partial envelopes
- If only extracting the nonce for diagnostics, treat this envelope as corrupt and skip it
Example fix
// before
nonce, err := util.EncryptionNonce(envelope[:len(envelope)-8]) // chopped tail
// after
nonce, err := util.EncryptionNonce(envelope)
if err != nil { return fmt.Errorf("envelope corrupt: %w", err) } Defensive patterns
Strategy: validation
Validate before calling
if len(data) >= 7 {
nl := int(data[6])
if nl == 0 || len(data) < 7+nl {
return errors.New("envelope nonce length invalid or body truncated")
}
} Type guard
func envelopeComplete(b []byte) bool {
if len(b) < 7 { return false }
nl := int(b[6])
return nl > 0 && len(b) >= 7+nl
} Try / catch
nonce, err := util.EncryptionNonce(ciphertext)
if err != nil {
return fmt.Errorf("envelope corrupt/truncated, restore from backup: %w", err)
} Prevention
- Ensure file writes of envelopes are atomic or error-checked (no partial writes)
- Verify sync completed fully before reading encrypted blobs
- Keep backups; truncated GCM envelopes cannot be repaired in place
When it happens
Trigger: Calling EncryptionNonce on an envelope where byte 6 is 0x00 (corrupt header) or where len(ciphertext) < 7 + nonceLength (body truncated), e.g. a partially written or partially synced encrypted file.
Common situations: Interrupted writes (crash/power loss mid-write), incomplete sync of encrypted blobs, manual truncation of ciphertext, or corruption flipping the length byte.
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
- invalid encrypted asset chunk count
- invalid encrypted asset content metadata
- invalid encrypted asset format
- invalid encrypted asset metadata size
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/b9d006d7b0dbcc3f.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/kdf.go:117
}
// 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
if _, err := io.ReadFull(r, out); err != nil {
// hkdf.Read 不应出错(除非 dek 为空);防御性 panic 避免静默返回弱密钥
panic("hkdf derive failed: " + err.Error())
}
return out
}
View on GitHub (pinned to 9f775e8a12)