node icon indicating copy to clipboard operation
node copied to clipboard

Customize password-based KDF in `KeyObject#export`

Open Phoenix35 opened this issue 1 year ago • 2 comments

What is the problem this feature will solve?

At the moment, node.js uses OpenSSL defaults when exporting a key object

const { privateKey } = generateKeyPairSync("ec", {
  namedCurve: "P-384",
  privateKeyEncoding: {
    type: "pkcs8",
    format: "pem",
    cipher: "aes-256-cbc",
    passphrase: "something secret",
  },
});

generates a PEM-encoded encrypted private key with 2048 iterations of PBKDF2-HMAC-SHA256. OWASP recommends way more (600k).

What is the feature you are proposing to solve the problem?

In OpenSSL CLI openssl pkcs8 -topk8, the iterations are customizable with the -iter option. Alternatively, one can choose -scrypt (and relevant -scrypt_N/r/p params) as the KDF in OpenSSL but not in node.js. The PRF can also be a different HMAC-SHAxxx but that's less relevant in my opinion

I open the discussion for extending KeyObject#export and related interfaces with one of the following

  1. A derivedKey parameter that excludes passphrase. In this case, no KDF is performed, and it is strongly emphasised to pass a key derived with scrypt, pbkdf2, or argon2id (node.js support one day :crossed_fingers:) (EDIT: support for argon2id introduced in OpenSSL 3.2.0)
privateKeyEncoding: {
  ...
  cipher: "aes-256-cbc",
  derivedKey: await promisifiedScrypt(weakUserPassphrase, salt, 32, { p: 5 }) // {@link <https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt>}
}
  1. Extend cipher to be an object
cipher: {
  alg: "aes-256-cbc",
  kdf: "pbkdf2",
  iter: 600_000,
  /* prf: "hmacWithSHA256" */
  
  // mutually exclusive
  alg: "aes-256-cbc",
  kdf: "scrypt",
  cost: ...,
  // same options as with crypto.scrypt
}
  1. Change the default iterations count to follow OWASP guidelines. This loses parity with OpenSSL defaults, which can be confusing for users, and there is no extensibility in case OWASP removes pbkdf2 from its recommandation. I am strongly against it, but its implementation would seem the less painful of all

What alternatives have you considered?

Install OpenSSL on operating systems that don't provide it (hello Windows) and encrypt with its CLI (via child_process or a terminal)

Phoenix35 avatar Jun 05 '24 22:06 Phoenix35

There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the https://github.com/nodejs/node/labels/never-stale label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment. For more information on how the project manages feature requests, please consult the feature request management document.

github-actions[bot] avatar Dec 05 '24 01:12 github-actions[bot]

Can we consider putting the never-stale label on this issue, or try to solve it?

Phoenix35 avatar Dec 05 '24 10:12 Phoenix35

There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the https://github.com/nodejs/node/labels/never-stale label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment. For more information on how the project manages feature requests, please consult the feature request management document.

github-actions[bot] avatar Jun 04 '25 01:06 github-actions[bot]

There has been no activity on this feature request and it is being closed. If you feel closing this issue is not the right thing to do, please leave a comment.

For more information on how the project manages feature requests, please consult the feature request management document.

github-actions[bot] avatar Jul 04 '25 01:07 github-actions[bot]

I don't consider this an unreasonable request. Any chance there will be a never-stale tag to it?

Phoenix35 avatar Jul 07 '25 10:07 Phoenix35