{"record":{"id":"ad1373379b3cb251","repo":"siyuan-note/siyuan","slug":"decryption-failed-incorrect-key-or-corrupted-data-ad1373","errorCode":null,"errorMessage":"Decryption failed: incorrect key or corrupted data [box=%s]","messagePattern":"Decryption failed: incorrect key or corrupted data \\[box=(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/crypto.go","lineNumber":1730,"sourceCode":"\t}\n\tnewKEK := util.DeriveKey(newPassword, nc.MasterSalt, params)\n\tdefer zeroAndClear(newKEK)\n\tnewVerifier, err := util.EncryptWithAAD(newKEK, kekVerifierMagic, []byte(\"siyuan:kek-verifier\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Phase 0: 遍历所有加密笔记本（含 conf 损坏但存在备份的），预计算新 WrappedDEK（内存操作）\n\t// 允许 entries 为空：用户可能已启用加密功能但尚未创建加密笔记本，此时仍需更新全局 verifier 和 backup。\n\tencBoxIDs, listErr := listAllEncryptedBoxIDs()\n\tif listErr != nil {\n\t\treturn fmt.Errorf(\"list encrypted notebooks failed: %w\", listErr)\n\t}\n\tvar entries []migrationBoxEntry\n\tfor _, id := range encBoxIDs {\n\t\tdek, boxCrypt, dErr := decryptBoxCrypt(id, oldKEK)\n\t\tif dErr != nil {\n\t\t\treturn errors.New(Conf.Language(316) + \" [box=\" + id + \"]\")\n\t\t}\n\t\tnewWrapped, nErr := util.EncryptWithAAD(newKEK, dek, wrappedDEKAAD(id))\n\t\tif nErr != nil {\n\t\t\treturn nErr\n\t\t}\n\t\tentries = append(entries, migrationBoxEntry{\n\t\t\tBoxID:         id,\n\t\t\tNewSpec:       boxEncryptionSpec,\n\t\t\tNewWrappedDEK: newWrapped,\n\t\t\tNewWrapNonce:  mustEncryptionNonce(newWrapped),\n\t\t\tMetadata:      append([]byte(nil), boxCrypt.Metadata...),\n\t\t})\n\t}\n\n\t// Phase 1: 持久化 migration manifest（崩溃后 recovery 的依据）\n\tnewParamsJSON, _ := gulu.JSON.MarshalJSON(params)\n\tmig := &masterPasswordMigration{\n\t\tOldVerifier:      nc.KEKVerifier,","sourceCodeStart":1712,"sourceCodeEnd":1748,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/crypto.go#L1712-L1748","documentation":"Thrown by ChangeMasterPassword Phase 0 when decryptBoxCrypt(id, oldKEK) fails for a specific encrypted notebook. decryptBoxCrypt tries both the conf.json BoxCrypt and the per-notebook backup; failure means the old password's KEK could not unwrap any WrappedDEK for that notebook. The message includes the box ID for diagnosis (Language(316) + ' [box=<id>]').","triggerScenarios":"Fires during ChangeMasterPassword when the old password is wrong (same KEK can't decrypt any WrappedDEK), or when a specific notebook's WrappedDEK is corrupted/belongs to a different KEK than the others. The error is returned immediately, aborting the migration before any changes are written.","commonSituations":"User enters the wrong old password. A notebook was encrypted under a different master password (e.g., imported from another workspace). A partial migration on another device left one notebook's WrappedDEK on the old key while the global verifier was already switched. Sync brought an inconsistent WrappedDEK for one notebook.","solutions":["Verify the old password is correct — try unlocking one of the listed encrypted notebooks with it first.","Identify the problematic box from the [box=<id>] suffix and check if its WrappedDEK matches the current global verifier.","If one notebook has an inconsistent WrappedDEK, restore its conf.json or backup from a device where it's consistent, let sync propagate, then retry the password change.","If a master-password migration is pending from a previous attempt, restart SiYuan to complete recovery first."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Verify the old password works before starting the migration by\n// attempting to derive the KEK (or unlock a test notebook):\n// deriveKEK is internal, but you can call UnlockBox on one notebook\n// to validate the password, then LockBox before ChangeMasterPassword.","typeGuard":null,"tryCatchPattern":"if err := model.ChangeMasterPassword(oldPassword, newPassword); err != nil {\n    if strings.Contains(err.Error(), \"[box=\") {\n        // specific notebook failed to decrypt with old KEK\n        // extract box ID, check its WrappedDEK consistency\n    }\n}","preventionTips":["Verify the old password by unlocking one encrypted notebook before starting the password change.","Ensure all notebooks are synced and have consistent WrappedDEKs before changing the password.","Complete any pending migration (restart SiYuan) before starting a new password change."],"tags":["encryption","password-change","decryption-failure","go"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}