siyuan-note/siyuan · error

Argon2id Iterations too low (minimum 3)

Error message

Argon2id Iterations too low (minimum 3)

What it means

ValidateArgon2Params requires at least 3 Argon2id iterations (passes over memory). Fewer passes make key derivation too cheap and weaken the KDF against brute force, so the library rejects them before deriving any key.

Solutions

  1. Set Argon2Params.Iterations to >= 3; use util.DefaultArgon2Params() (3 iterations) as the baseline
  2. If unlock is too slow, reduce Memory within the allowed 64-256 MB range instead of dropping iterations below 3
  3. Fix the source config JSON of the imported backup before importing

Example fix

// before
p := util.Argon2Params{Memory: 64 * 1024, Iterations: 2, Parallelism: 4, KeyLength: 32}

// after
p := util.Argon2Params{Memory: 64 * 1024, Iterations: 3, Parallelism: 4, KeyLength: 32}
Defensive patterns

Strategy: validation

Validate before calling

if p.Iterations < 3 || p.Iterations > 10 {
    return fmt.Errorf("iterations must be 3-10, got %d", p.Iterations)
}

Try / catch

if _, err := util.ValidateArgon2Params(p); err != nil {
    return fmt.Errorf("invalid KDF params: %w", err)
}

Prevention

When it happens

Trigger: Calling ValidateArgon2Params (directly or via EnableEncryptedNotebook, ImportNotebookCryptoBackup, deriveKEK, or backup-restore paths) with Argon2Params.Iterations < 3, e.g. a config saved with Iterations 1 or 2.

Common situations: Hand-editing notebook crypto settings to speed up unlock, importing a backup whose params were downgraded, or constructing Argon2Params partially so Iterations zero-values to 0.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/fa4869daa872d71f. Report an issue: GitHub.

Appendix: source

Thrown at kernel/util/kdf.go:74

		Parallelism: 4,
		KeyLength:   32,
	}
}

// ValidateArgon2Params 校验 Argon2id 参数是否在合理范围内,防止恶意备份设置极大内存导致 OOM,
// 或过弱参数降低安全性。
func ValidateArgon2Params(p Argon2Params) (Argon2Params, error) {
	if p.KeyLength != 32 {
		return p, errors.New("Argon2id KeyLength must be 32")
	}
	if p.Memory < 64*1024 {
		return p, errors.New("Argon2id Memory too low (minimum 64 MB)")
	}
	if p.Memory > 256*1024 {
		return p, errors.New("Argon2id Memory too high (maximum 256 MB)")
	}
	if p.Iterations < 3 {
		return p, errors.New("Argon2id Iterations too low (minimum 3)")
	}
	if p.Iterations > 10 {
		return p, errors.New("Argon2id Iterations too high (maximum 10)")
	}
	if p.Parallelism == 0 || p.Parallelism > 16 {
		return p, errors.New("Argon2id Parallelism must be between 1 and 16")
	}
	return p, nil
}

// DeriveKey 用 Argon2id 从密码派生密钥。同一 password+salt+params 多次调用结果一致。
func DeriveKey(password string, salt []byte, p Argon2Params) []byte {
	return argon2.IDKey([]byte(password), salt, p.Iterations, p.Memory, p.Parallelism, p.KeyLength)
}

// Encrypt 用 AES-256-GCM 加密。每次调用生成随机 nonce,因此同一明文多次加密结果不同。
// 返回格式:magic(4B) || spec(1B) || algorithm(1B) || nonceLength(1B) || nonce || ciphertext || GCM tag(16B)。
func Encrypt(key, plaintext []byte) ([]byte, error) {

View on GitHub (pinned to 9f775e8a12)