creditdaddy 1.2.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/transfer.js CHANGED
@@ -37,6 +37,28 @@ function deriveKey(password, salt, kdf = KDF) {
37
37
  });
38
38
  }
39
39
 
40
+ /**
41
+ * 导入文件里的 kdf 参数不可信:文件自报 {N:2,r:1,p:1} 会让 scrypt 瞬间算完(0ms vs 42ms),
42
+ * 密钥强度被文件作者单方面降级,而且没有任何地方会提示。KDF 是本格式的固定契约(见文件头),
43
+ * 不一致就拒收。注意 kdf 整个对象缺失时要报「参数不对」而不是「口令错误」——后者会把
44
+ * 用户的排查方向带偏。
45
+ */
46
+ function checkKdf(blob) {
47
+ const k = blob?.kdf;
48
+ if (!k || typeof k !== 'object') {
49
+ throw new TransferError('BAD_KDF', '迁移文件缺少 KDF 参数,可能不是本工具导出的文件');
50
+ }
51
+ if (k.alg !== KDF.alg) {
52
+ throw new TransferError('BAD_KDF', `不支持的 KDF 算法:${k.alg}`);
53
+ }
54
+ for (const f of ['N', 'r', 'p', 'keyLen']) {
55
+ if (k[f] !== KDF[f]) {
56
+ throw new TransferError('BAD_KDF', `KDF 参数 ${f} 与本工具不一致(文件 ${k[f]},期望 ${KDF[f]}):为避免密钥强度被文件单方面降级,已拒绝导入`);
57
+ }
58
+ }
59
+ return k;
60
+ }
61
+
40
62
  export function sealTransfer(payload, password) {
41
63
  if (typeof password !== 'string' || password.length < 4) {
42
64
  throw new TransferError('PASSPHRASE_TOO_SHORT', '加密口令至少 4 个字符');
@@ -58,8 +80,9 @@ export function sealTransfer(payload, password) {
58
80
  export function openTransfer(blob, password) {
59
81
  if (blob?.format !== TRANSFER_FORMAT) throw new TransferError('UNSUPPORTED_FORMAT', '不是加密迁移文件');
60
82
  if (!password) throw new TransferError('NEED_PASSWORD', '该文件已加密,请输入导出时设置的口令');
83
+ const kdf = checkKdf(blob);
61
84
  try {
62
- const decipher = crypto.createDecipheriv('aes-256-gcm', deriveKey(password, unb64(blob.kdf?.salt), blob.kdf), unb64(blob.iv));
85
+ const decipher = crypto.createDecipheriv('aes-256-gcm', deriveKey(password, unb64(kdf.salt), kdf), unb64(blob.iv));
63
86
  decipher.setAuthTag(unb64(blob.tag));
64
87
  const plain = Buffer.concat([decipher.update(unb64(blob.payload)), decipher.final()]);
65
88
  return JSON.parse(plain.toString('utf8'));