siyuan-note/siyuan · warning

Conf.Language(324)

Error message

Conf.Language(324)

What it means

ImportNotebookCryptoBackup() refuses to import when the local NotebookCrypto config is enabled AND complete (notebookCryptoConfigurationComplete), returning Conf.Language(324): 'Cannot import a key backup while encrypted notebooks are enabled. Disable it first'. This is a deliberate guard: importing would overwrite the existing salt/verifier and orphan every existing WrappedDEK, making current encrypted notebooks permanently undecryptable.

Source

Thrown at kernel/model/crypto.go:320

}

// 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(&current) {
		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 afa823b6b4)

Solutions

  1. Disable notebook encryption first (Settings flow with the current master password), then import the backup
  2. Or import into a fresh workspace where encryption was never enabled
  3. If encryption cannot be disabled because the password is lost, import is not the remedy - restore via conf.json/backup files instead
  4. After importing, re-enable encryption and verify all notebooks unlock before adding data
Defensive patterns

Strategy: validation

Validate before calling

// kernel-side guard mirrors the check: only import into a disabled or incomplete config
state := model.GetNotebookCryptoState() // conceptually: Enabled && complete must be false
if state == NotebookCryptoStateEnabled {
    return errors.New("disable notebook encryption before importing a key backup")
}

Prevention

When it happens

Trigger: Calling the import API/flow on a machine that already has working notebook encryption configured, e.g. when attempting to migrate keys from another device into an already-encrypted setup.

Common situations: Trying to restore keys onto a reinstalled machine where encryption was re-enabled first; copying keys between devices in the wrong order; misunderstanding the flow as additive rather than destructive.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/d7373ee56986d80a. Report an issue: GitHub.