siyuan-note/siyuan · error
Conf.Language(317)
Error message
Conf.Language(317)
What it means
ImportNotebookCryptoBackup() first json.Unmarshals the submitted bytes into a conf.NotebookCrypto; if that fails it returns Conf.Language(317): 'Invalid key backup file'. This branch means the payload is not valid JSON of the expected shape at all - structural, before any cryptographic validation happens.
Source
Thrown at kernel/model/crypto.go:325
// 安全:备份文件不含主密码(salt 不保密、verifier 是密文),导入只恢复配置,解锁仍需主密码。
// 防呆:本机已有完整且已启用的加密配置时拒绝导入,避免覆盖现有 salt/verifier 孤立现有 WrappedDEK。
// ImportNotebookCryptoBackup 接收用户导入的密钥备份文件内容(JSON 字节)+ 主密码,
// 校验主密码能解开备份里的 verifier 后才写回配置。防止 crafted 备份设置弱 KDFParams 等攻击。
// RecoveryRequired 状态允许导入,但候选 KEK 必须能解开所有现存笔记本和已删除笔记本历史。
func ImportNotebookCryptoBackup(data []byte, password string) error {
notebookCryptoMu.Lock()
defer notebookCryptoMu.Unlock()
Conf.m.RLock()
current := *Conf.NotebookCrypto
Conf.m.RUnlock()
if current.Enabled && notebookCryptoConfigurationComplete(¤t) {
return errors.New(Conf.Language(324))
}
nc := &conf.NotebookCrypto{}
if err := json.Unmarshal(data, nc); err != nil {
return errors.New(Conf.Language(317))
}
if !notebookCryptoConfigurationComplete(nc) {
return errors.New(Conf.Language(317))
}
// 用导入的 salt + 用户输入的主密码派生 KEK,校验能否解开备份里的 verifier
params, validErr := util.ValidateArgon2Params(nc.KDFParams)
if validErr != nil {
return errors.New(Conf.Language(317))
}
kek := util.DeriveKey(password, nc.MasterSalt, params)
defer zeroAndClear(kek)
if nc.Checksum != computeBackupChecksum(nc) {
return errors.New(Conf.Language(317))
}
if !verifyKEKMAC(nc, kek) {
return errors.New(Conf.Language(317))
}View on GitHub (pinned to afa823b6b4)
Solutions
- Re-export the backup on the source machine and transfer it as-is (no re-saving through editors)
- Open the file in a text editor - it must be plain JSON starting with '{' and contain masterSalt/kekVerifier-style fields
- Check the file is not truncated (compare size with the source)
- For API callers, run json.Valid(data) before submitting
Defensive patterns
Strategy: validation
Validate before calling
if !json.Valid(data) {
return errors.New("file is not valid JSON - not a key backup")
}
var probe map[string]any
if err := json.Unmarshal(data, &probe); err != nil {
return errors.New("file is not a JSON object - not a key backup")
} Prevention
- Transfer backups as raw files - never through editors or re-serializers
- Sanity-check the file starts with '{' and mentions masterSalt/kek fields before submitting
- Keep the .json extension and UTF-8 encoding intact
When it happens
Trigger: Uploading a file that is not the exported notebook-crypto-backup JSON: truncated download, an HTML error page saved as .json, a renamed unrelated file, or encoding damage (BOM/garbled bytes).
Common situations: User picks the wrong attachment; backup emailed/downloaded through a pipeline that mangles it; double-extension files hiding true format.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Conf.Language(324)
- Conf.Language(315)
- invalid import token
- no file found
- import path is not sub path of import dir
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/8f0c26816b4c0c6a.
Report an issue: GitHub.