{"record":{"id":"336ce7e953f0e6f7","repo":"siyuan-note/siyuan","slug":"encrypted-envelope-too-short","errorCode":null,"errorMessage":"encrypted envelope too short","messagePattern":"encrypted envelope too short","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/kdf.go","lineNumber":107,"sourceCode":"\n// Encrypt 用 AES-256-GCM 加密。每次调用生成随机 nonce，因此同一明文多次加密结果不同。\n// 返回格式：magic(4B) || spec(1B) || algorithm(1B) || nonceLength(1B) || nonce || ciphertext || GCM tag(16B)。\nfunc Encrypt(key, plaintext []byte) ([]byte, error) {\n\treturn encryptGCM(key, plaintext, nil, \"Encrypt\")\n}\n\n// Decrypt 对应 Encrypt 的解密。密钥错误、格式无效或密文被篡改时返回错误。\nfunc Decrypt(key, ciphertext []byte) ([]byte, error) {\n\treturn decryptGCM(key, ciphertext, nil, \"Decrypt\")\n}\n\n// EncryptionNonce 从 AES-GCM 密文信封中提取 nonce。\nfunc EncryptionNonce(ciphertext []byte) ([]byte, error) {\n\tif !hasEncryptionMagic(ciphertext) {\n\t\treturn nil, errors.New(\"invalid encrypted envelope magic\")\n\t}\n\tif len(ciphertext) < encryptionEnvelopeHeaderSize {\n\t\treturn nil, errors.New(\"encrypted envelope too short\")\n\t}\n\tif ciphertext[len(encryptionMagic)] != EncryptionSpec {\n\t\treturn nil, errors.New(\"unsupported encrypted envelope spec\")\n\t}\n\tif ciphertext[len(encryptionMagic)+1] != encryptionAlgorithmAES256GCM {\n\t\treturn nil, errors.New(\"unsupported encrypted envelope algorithm\")\n\t}\n\tnonceLength := int(ciphertext[len(encryptionMagic)+2])\n\tif nonceLength == 0 || len(ciphertext) < encryptionEnvelopeHeaderSize+nonceLength {\n\t\treturn nil, errors.New(\"invalid encrypted envelope nonce length\")\n\t}\n\treturn append([]byte(nil), ciphertext[encryptionEnvelopeHeaderSize:encryptionEnvelopeHeaderSize+nonceLength]...), nil\n}\n\n// DeriveSubKey 用 HKDF-SHA256 从主 DEK 派生用途隔离的子密钥。\n// 同一 (dek, purpose) 多次调用结果一致；不同 purpose 派生出相互独立的子密钥，\n// 实现用途分离——.sy/assets/AV 各用独立子密钥，互不可替代，限制单点密钥泄漏的影响面。\nfunc DeriveSubKey(dek []byte, purpose string) []byte {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/kdf.go#L89-L125","documentation":"EncryptionNonce found the 'SENC' magic but the buffer is shorter than the 7-byte envelope header (magic 4B + spec 1B + algorithm 1B + nonceLength 1B), so the spec/algorithm/nonce-length fields cannot be read. The input is a truncated envelope.","triggerScenarios":"Calling EncryptionNonce with a byte slice of length 4-6 that starts with 'SENC' — a header that was cut off mid-read, a manually sliced envelope, or corrupted storage.","commonSituations":"Partial file reads, copying only part of the ciphertext, slicing the envelope into header + body and passing the wrong part, or disk corruption of stored encrypted blobs.","solutions":["Pass the complete envelope bytes as returned by Encrypt/EncryptWithAAD (never a manual slice)","Check the read path that produced the bytes for truncation (compare against expected envelope length)","Restore the original file from backup/sync if stored data is corrupted"],"exampleFix":"// before\nnonce, err := util.EncryptionNonce(envelope[:5]) // truncated header\n\n// after\nnonce, err := util.EncryptionNonce(envelope) // full envelope bytes","handlingStrategy":"validation","validationCode":"if len(data) < 7 {\n    return errors.New(\"ciphertext shorter than envelope header\")\n}","typeGuard":"func isCompleteHeader(b []byte) bool { return len(b) >= 7 }","tryCatchPattern":"nonce, err := util.EncryptionNonce(ciphertext)\nif err != nil {\n    return fmt.Errorf(\"envelope truncated or malformed: %w\", err)\n}","preventionTips":["Read the whole file/blob; avoid partial reads for encrypted data","Never slice envelopes manually; keep header and body together","Verify byte counts after IO against expected envelope size"],"tags":["encryption","aes-gcm","envelope-format","truncated-data"],"backgroundTag":"invalid-argument-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}