siyuan-note/siyuan · error

Decryption failed: incorrect key or corrupted data

Error message

Decryption failed: incorrect key or corrupted data

What it means

ImportNotebookCryptoBackup returns Conf.Language(316) ('key mismatch') at line 350 when the imported backup's KEK passes its own verifier but cannot decrypt the WrappedDEK of any existing encrypted notebook (verifyKEKAgainstExistingBoxes) or any deleted-notebook history WrappedDEK (verifyKEKAgainstEncryptedHistory). The backup belongs to a different key domain than the notebooks present on this device; importing it would orphan all existing encrypted data. The comment marks this as 密钥不匹配 (key mismatch), distinct from a wrong password (311).

Source

Thrown at kernel/model/crypto.go:350

	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))
	}
	decrypted, dErr := util.DecryptWithAAD(kek, nc.KEKVerifier, []byte("siyuan:kek-verifier"))
	if dErr != nil || string(decrypted) != string(kekVerifierMagic) {
		return errors.New(Conf.Language(311)) // 主密码错误
	}

	// 校验 KEK 能解密现存笔记本和已删除笔记本历史中的 WrappedDEK,避免导入不匹配的备份。
	if !verifyKEKAgainstExistingBoxes(kek) || !verifyKEKAgainstEncryptedHistory(kek) {
		return errors.New(Conf.Language(316)) // 密钥不匹配
	}

	nc.KDFParams = params // 确保写回 Conf 的参数已经通过完整校验。
	nc.Enabled = true

	// 先写 backup,再提交 conf;backup 失败时 conf 尚未改变,可重试
	if err := writeNotebookCryptoBackupData(nc, kek); err != nil {
		return fmt.Errorf("failed to persist key backup: %w", err)
	}
	Conf.m.Lock()
	*Conf.NotebookCrypto = *nc
	Conf.m.Unlock()
	Conf.Save()
	IncSync()
	return nil
}

// saveNotebookCryptoBackup 把当前 NotebookCrypto(含 MasterSalt/KEKVerifier/KDFParams)备份到 DataDir。

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Import the backup that matches this device's existing encrypted notebooks — the one created on a device sharing the same key domain.
  2. If the existing notebooks are no longer needed, remove them (and their history) before importing, so the mismatch check has nothing to contradict.
  3. Confirm the backup source device and master-password lineage before importing.
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the backup matches this device's notebooks before importing.
// If existing encrypted notebooks are unwanted, remove them and their history first.

Prevention

When it happens

Trigger: The backup decrypts its own verifier with the supplied password, but verifyKEKAgainstExistingBoxes or verifyKEKAgainstEncryptedHistory returns false: a WrappedDEK from a current or historical encrypted notebook does not decrypt under this KEK. Happens when importing a backup from an unrelated key domain (different device that never shared this notebook's keys).

Common situations: User imports a backup from device B that used a different master password/key lineage than device A's notebooks; backup taken before a master-password change while notebooks were re-keyed under the new password; mixing backups across separate workspaces.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/9ffd4e881c045d8f. Report an issue: GitHub.