siyuan-note/siyuan · warning
Cannot import a key backup while encrypted notebooks are ena
Error message
Cannot import a key backup while encrypted notebooks are enabled. Disable it first
What it means
ImportNotebookCryptoBackup refuses to import a backup when the local NotebookCrypto configuration is already Enabled and complete (notebookCryptoConfigurationComplete). This is a deliberate guard: importing would overwrite the existing MasterSalt/KEKVerifier and orphan the existing WrappedDEKs, making current encrypted notebooks permanently undecryptable. The error is Conf.Language(324).
Source
Thrown at kernel/model/crypto.go:319
}
// ImportNotebookCryptoBackup 接收用户导入的密钥备份文件内容(JSON 字节),
// 校验为合法 NotebookCrypto 后写回 <DataDir>/.siyuan/data-crypto-backup.json 并装回本机 Conf。
// 用于新设备/重装后不依赖同步、手动恢复加密配置(详见设计文档 §4.1)。
// 安全:备份文件不含主密码(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) {View on GitHub (pinned to 251596fc0d)
Solutions
- Disable encryption on the current device first (DecryptEncryptedNotebook / disable flow), then import the backup.
- If the goal is to adopt another device's key domain, use the sync-based recovery path instead of manual import.
- Confirm whether the import is actually needed — an already-enabled complete config does not require restoration.
Defensive patterns
Strategy: validation
Validate before calling
// Only offer import when encryption is not already enabled and complete.
if model.NotebookCryptoEnabled() {
// hide / disable import; prompt to disable encryption first if needed
} Prevention
- Gate the import action on encryption being disabled or incomplete.
- Prefer the sync-based recovery path to adopt another device's key domain rather than manual import.
- Never import a backup onto an already-enabled complete configuration — it would orphan existing WrappedDEKs.
When it happens
Trigger: Calling ImportNotebookCryptoBackup while Conf.NotebookCrypto.Enabled is true and the configuration has all required fields. Happens when a user has encryption active on this device and attempts to import a backup from another device or a previously exported file.
Common situations: User enabled encryption on device A and tries to import device B's backup on device A; user re-imports an old backup after changing the master password; scripted restore run against an already-configured workspace.
Related errors
- Decryption failed: incorrect key or corrupted data
- Encrypted notebooks already exist but the master key backup
- Invalid key backup file
- Incorrect master password
- 312
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/3425823e80631e40.
Report an issue: GitHub.