{"record":{"id":"c20ede1590dc6f21","repo":"siyuan-note/siyuan","slug":"conf-language-311","errorCode":null,"errorMessage":"Conf.Language(311)","messagePattern":"Conf\\.Language\\(311\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/crypto.go","lineNumber":352,"sourceCode":"\t\treturn errors.New(Conf.Language(317))\n\t}\n\n\t// 用导入的 salt + 用户输入的主密码派生 KEK，校验能否解开备份里的 verifier\n\tparams, validErr := util.ValidateArgon2Params(nc.KDFParams)\n\tif validErr != nil {\n\t\treturn errors.New(Conf.Language(317))\n\t}\n\tkek := util.DeriveKey(password, nc.MasterSalt, params)\n\tdefer zeroAndClear(kek)\n\tif nc.Checksum != computeBackupChecksum(nc) {\n\t\treturn errors.New(Conf.Language(317))\n\t}\n\tif !verifyKEKMAC(nc, kek) {\n\t\treturn errors.New(Conf.Language(317))\n\t}\n\tdecrypted, dErr := util.DecryptWithAAD(kek, nc.KEKVerifier, []byte(\"siyuan:kek-verifier\"))\n\tif dErr != nil || string(decrypted) != string(kekVerifierMagic) {\n\t\treturn errors.New(Conf.Language(311)) // 主密码错误\n\t}\n\n\t// 校验 KEK 能解密现存笔记本和已删除笔记本历史中的 WrappedDEK，避免导入不匹配的备份。\n\tif !verifyKEKAgainstExistingBoxes(kek, nc) || !verifyKEKAgainstEncryptedHistory(kek, nc) {\n\t\treturn errors.New(Conf.Language(316)) // 密钥不匹配\n\t}\n\n\tnc.KDFParams = params // 确保写回 Conf 的参数已经通过完整校验。\n\tnc.Enabled = true\n\n\t// 先写 backup，再提交 conf；backup 失败时 conf 尚未改变，可重试\n\tif err := writeNotebookCryptoBackupData(nc, kek); err != nil {\n\t\treturn fmt.Errorf(\"failed to persist key backup: %w\", err)\n\t}\n\tConf.m.Lock()\n\t*Conf.NotebookCrypto = *nc\n\tConf.m.Unlock()\n\tConf.Save()","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/crypto.go#L334-L370","documentation":"ImportNotebookCryptoBackup verification failure surfaced as localized message Conf.Language(311) (wrong main password): the KEK derived from the user-entered password plus the backup's MasterSalt failed to decrypt the KEKVerifier to the expected magic. The password does not match the backup, so import is refused without touching existing data.","triggerScenarios":"Thrown at kernel/model/crypto.go:352 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Re-enter the exact main password used when the backup was created","Confirm the backup file is the intended one and uncorrupted","Never regenerate MasterSalt or delete keys to work around the mismatch"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}