@blamejs/pki 0.4.13 → 0.4.15

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/lib/key.js CHANGED
@@ -120,11 +120,23 @@ async function encrypt(privateKey, password, opts) {
120
120
  var iterations = pbes2.assertIterations(opts.iterations == null ? 600000 : opts.iterations, _err, "key");
121
121
  var salt = opts.salt != null ? pbes2.assertSalt(guard.bytes.view(opts.salt, KeyError, "key/bad-input", "salt"), _err, "key") : nodeCrypto.randomBytes(16);
122
122
  var iv = nodeCrypto.randomBytes(16);
123
- var dk = nodeCrypto.pbkdf2Sync(pbes2.passwordBytes(password, _err, "key"), salt, iterations, keyBits / 8, prfNode);
124
- var ciphertext = pbes2.cbcEncrypt(dk, iv, der, keyBits);
125
- var epki = b.sequence([pbes2.pbes2AlgId(salt, iterations, prf, cipherName, iv), b.octetString(ciphertext)]);
126
- pkcs8.parseEncrypted(epki); // self-check: the produced EncryptedPrivateKeyInfo re-parses
127
- return opts.pem ? pkcs8.pemEncode(epki, "ENCRYPTED PRIVATE KEY") : epki;
123
+ // The derived key protects a PRIVATE KEY, so it is cleared as soon as the encryption is done. The
124
+ // caller's password is untouched -- passwordBytes returns a supplied Buffer as-is.
125
+ // A string / Uint8Array password is encoded into a buffer THIS toolkit allocated -- a credential
126
+ // copy -- so it is cleared once the derivation has consumed it. A caller-supplied Buffer is
127
+ // borrowed and left intact.
128
+ var pwK = pbes2.passwordBytesOwned(password, _err, "key");
129
+ var dk;
130
+ try { dk = nodeCrypto.pbkdf2Sync(pwK.bytes, salt, iterations, keyBits / 8, prfNode); }
131
+ finally { if (pwK.owned) guard.secret.zeroize(pwK.bytes, KeyError, "key/bad-input", "the password encoding"); }
132
+ try {
133
+ var ciphertext = pbes2.cbcEncrypt(dk, iv, der, keyBits);
134
+ var epki = b.sequence([pbes2.pbes2AlgId(salt, iterations, prf, cipherName, iv), b.octetString(ciphertext)]);
135
+ pkcs8.parseEncrypted(epki); // self-check: the produced EncryptedPrivateKeyInfo re-parses
136
+ return opts.pem ? pkcs8.pemEncode(epki, "ENCRYPTED PRIVATE KEY") : epki;
137
+ } finally {
138
+ guard.secret.zeroize(dk, KeyError, "key/bad-input", "the password-derived encryption key");
139
+ }
128
140
  }
129
141
 
130
142
  /**
@@ -176,7 +188,13 @@ function _decryptPbes2(encAlg, ciphertext, password, opts) {
176
188
  // The shared PBES2 decrypt home (strict params + the uniform decrypt-failed on a wrong key / bad pad). The
177
189
  // plaintext re-parse below is the MAC-less PBES2-CBC integrity check (RFC 8018 sec. 8): a bad pad and a
178
190
  // valid pad whose plaintext is not a PrivateKeyInfo are indistinguishable, and it MUST run (never skipped).
179
- var plaintext = pbes2.pbes2Decrypt(pbes2.passwordBytes(password, _err, "key"), encAlg.parameters, ciphertext, opts, _err, "key");
191
+ // A string / Uint8Array password is encoded into a buffer THIS toolkit allocated -- a credential
192
+ // copy -- so it is cleared once the derivation has consumed it. A caller-supplied Buffer is
193
+ // borrowed and left intact.
194
+ var pwD = pbes2.passwordBytesOwned(password, _err, "key");
195
+ var plaintext;
196
+ try { plaintext = pbes2.pbes2Decrypt(pwD.bytes, encAlg.parameters, ciphertext, opts, _err, "key"); }
197
+ finally { if (pwD.owned) guard.secret.zeroize(pwD.bytes, KeyError, "key/bad-input", "the password encoding"); }
180
198
  try { pkcs8.parse(plaintext); }
181
199
  catch (_e) { throw _err("key/decrypt-failed", "decryption failed"); }
182
200
  return plaintext;