-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
crypto: introduce crypto/promises #37218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2551,8 +2551,8 @@ added: | |
* Returns: {Buffer} | ||
|
||
Computes the Diffie-Hellman secret based on a `privateKey` and a `publicKey`. | ||
Both keys must have the same `asymmetricKeyType`, which must be one of `'dh'` | ||
(for Diffie-Hellman), `'ec'` (for ECDH), `'x448'`, or `'x25519'` (for ECDH-ES). | ||
Both keys must have the same `asymmetricKeyType`, which must be one of `'dh'`, | ||
`'ec'`, `'x448'`, or `'x25519'`. | ||
|
||
### `crypto.generateKey(type, options, callback)` | ||
<!-- YAML | ||
|
@@ -3895,6 +3895,130 @@ Type: {Crypto} An implementation of the Web Crypto API standard. | |
|
||
See the [Web Crypto API documentation][] for details. | ||
|
||
## `crypto` Promises API | ||
<!-- YAML | ||
added: REPLACEME | ||
--> | ||
|
||
> Stability: 1 - Experimental | ||
|
||
The `crypto.promises` API provides an alternative set of asynchronous crypto | ||
methods that return `Promise` objects and execute operations in libuv's | ||
threadpool. | ||
The API is accessible via `require('crypto').promises` or `require('crypto/promises')`. | ||
|
||
### `cryptoPromises.diffieHellman(options)` | ||
<!-- YAML | ||
added: REPLACEME | ||
--> | ||
|
||
* `options`: {Object} | ||
* `privateKey`: {KeyObject|CryptoKey} | ||
* `publicKey`: {KeyObject|CryptoKey} | ||
* Returns: {Promise} containing {Buffer} | ||
|
||
Computes the Diffie-Hellman secret based on a `privateKey` and a `publicKey`. | ||
Both keys must have the same `asymmetricKeyType`, which must be one of `'dh'`, | ||
`'ec'`, `'x448'`, or `'x25519'`. | ||
|
||
### `cryptoPromises.digest(algorithm, data[, options])` | ||
<!-- YAML | ||
added: REPLACEME | ||
--> | ||
|
||
* `algorithm` {string} | ||
* `data` {ArrayBuffer|TypedArray|DataView|Buffer} | ||
* `options` {Object} | ||
* `outputLength` {number} Used to specify the desired output length in bytes | ||
for XOF hash functions such as `'shake256'`. | ||
* Returns: {Promise} containing {Buffer} | ||
|
||
Calculates the digest for the `data` using the given `algorithm`. | ||
|
||
The `algorithm` is dependent on the available algorithms supported by the | ||
version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc. | ||
On recent releases of OpenSSL, `openssl list -digest-algorithms` | ||
(`openssl list-message-digest-algorithms` for older versions of OpenSSL) will | ||
display the available digest algorithms. | ||
|
||
### `cryptoPromises.hmac(algorithm, data, key)` | ||
<!-- YAML | ||
added: REPLACEME | ||
--> | ||
|
||
* `algorithm` {string} | ||
* `data` {ArrayBuffer|TypedArray|DataView|Buffer} | ||
* `key` {KeyObject|CryptoKey} | ||
* Returns: {Promise} containing {Buffer} | ||
|
||
Calculates the HMAC digest for the `data` using the given `algorithm`. | ||
|
||
The `algorithm` is dependent on the available algorithms supported by the | ||
version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc. | ||
On recent releases of OpenSSL, `openssl list -digest-algorithms` | ||
(`openssl list-message-digest-algorithms` for older versions of OpenSSL) will | ||
display the available digest algorithms. | ||
|
||
### `cryptoPromises.sign(algorithm, data, key[, options])` | ||
<!-- YAML | ||
added: REPLACEME | ||
--> | ||
|
||
* `algorithm` {string|null|undefined} | ||
* `data` {ArrayBuffer|TypedArray|DataView|Buffer} | ||
* `key` {KeyObject|CryptoKey} | ||
* `options` {Object} | ||
* `dsaEncoding` {string} For DSA and ECDSA, this option specifies the | ||
format of the generated signature. It can be one of the following: | ||
* `'der'` (default): DER-encoded ASN.1 signature structure encoding `(r, s)`. | ||
* `'ieee-p1363'`: Signature format `r || s` as proposed in IEEE-P1363. | ||
* `padding` {integer} Optional padding value for RSA, one of the following: | ||
* `crypto.constants.RSA_PKCS1_PADDING` (default) | ||
* `crypto.constants.RSA_PKCS1_PSS_PADDING` | ||
* `saltLength` {integer} Salt length for when padding is | ||
`RSA_PKCS1_PSS_PADDING`. The special value | ||
`crypto.constants.RSA_PSS_SALTLEN_DIGEST` sets the salt length to the digest | ||
size, `crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN` (default) sets it to the | ||
maximum permissible value. | ||
* Returns: {Promise} containing {Buffer} | ||
|
||
Calculates the signature for `data` using the given private key and | ||
algorithm. If `algorithm` is `null` or `undefined`, then the algorithm is | ||
dependent upon the key type (especially Ed25519 and Ed448). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest moving the details about the defaults for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tniessen is passing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't design this API. It would be used for SM2, too. But there's no decision yet whether SM2 will be added, see #37066. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apologies, i thought you did. @mscdex can you pitch in? |
||
|
||
### `cryptoPromises.verify(algorithm, data, key, signature[, options])` | ||
<!-- YAML | ||
added: REPLACEME | ||
--> | ||
|
||
* `algorithm` {string|null|undefined} | ||
* `data` {ArrayBuffer|TypedArray|DataView|Buffer} | ||
* `key` {KeyObject|CryptoKey} | ||
* `signature` {ArrayBuffer|TypedArray|DataView|Buffer} | ||
* `options` {Object} | ||
* `dsaEncoding` {string} For DSA and ECDSA, this option specifies the | ||
format of the generated signature. It can be one of the following: | ||
* `'der'` (default): DER-encoded ASN.1 signature structure encoding `(r, s)`. | ||
* `'ieee-p1363'`: Signature format `r || s` as proposed in IEEE-P1363. | ||
* `padding` {integer} Optional padding value for RSA, one of the following: | ||
* `crypto.constants.RSA_PKCS1_PADDING` (default) | ||
* `crypto.constants.RSA_PKCS1_PSS_PADDING` | ||
* `saltLength` {integer} Salt length for when padding is | ||
`RSA_PKCS1_PSS_PADDING`. The special value | ||
`crypto.constants.RSA_PSS_SALTLEN_DIGEST` sets the salt length to the digest | ||
size, `crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN` (default) sets it to the | ||
maximum permissible value. | ||
* Returns: {Promise} containing {boolean} | ||
|
||
Verifies the given signature for `data` using the given key and algorithm. If | ||
`algorithm` is `null` or `undefined`, then the algorithm is dependent upon the | ||
key type (especially Ed25519 and Ed448). | ||
panva marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The `signature` argument is the previously calculated signature for the `data`. | ||
|
||
Because public keys can be derived from private keys, a private key or a public | ||
key may be passed for `key`. | ||
|
||
## Notes | ||
|
||
### Legacy streams API (prior to Node.js 0.10) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
'use strict'; | ||
|
||
module.exports = require('internal/crypto/promises').exports; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -346,6 +346,46 @@ function deriveBitsDH(publicKey, privateKey, callback) { | |
job.run(); | ||
} | ||
|
||
async function asyncDiffieHellman(publicKey, privateKey) { | ||
const { asymmetricKeyType } = privateKey; | ||
|
||
if (asymmetricKeyType === 'dh') { | ||
return new Promise((resolve, reject) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this to be more efficient than the promisify implementation. Not a hill I want to die on tho. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's exactly as efficient since in recent version this code is what promisify generates - but not a hill to die on for me either was just trying to comment :] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://github.com/nodejs/node/blob/v15.8.0/lib/internal/util.js#L292-L326 sure it has the same outcome, but i think it's handling way more cases which we don't need. |
||
deriveBitsDH( | ||
publicKey[kHandle], | ||
privateKey[kHandle], | ||
(err, bits) => { | ||
if (err) reject(err); | ||
else resolve(bits); | ||
}); | ||
}); | ||
} | ||
|
||
if (asymmetricKeyType === 'x25519' || asymmetricKeyType === 'x448') { | ||
return new Promise((resolve, reject) => { | ||
deriveBitsECDH( | ||
`NODE-${asymmetricKeyType.toUpperCase()}`, | ||
publicKey[kHandle], | ||
privateKey[kHandle], | ||
(err, bits) => { | ||
if (err) reject(err); | ||
else resolve(bits); | ||
}); | ||
}); | ||
} | ||
|
||
return new Promise((resolve, reject) => { | ||
deriveBitsECDH( | ||
privateKey.asymmetricKeyDetails.namedCurve, | ||
publicKey[kHandle], | ||
privateKey[kHandle], | ||
(err, bits) => { | ||
if (err) reject(err); | ||
else resolve(bits); | ||
}); | ||
}); | ||
} | ||
|
||
function verifyAcceptableDhKeyUse(name, type, usages) { | ||
let checkSet; | ||
switch (type) { | ||
|
@@ -601,9 +641,11 @@ module.exports = { | |
DiffieHellman, | ||
DiffieHellmanGroup, | ||
ECDH, | ||
asyncDiffieHellman, | ||
diffieHellman, | ||
deriveBitsECDH, | ||
deriveBitsDH, | ||
dhEnabledKeyTypes, | ||
dhGenerateKey, | ||
asyncDeriveBitsECDH, | ||
asyncDeriveBitsDH, | ||
|
Uh oh!
There was an error while loading. Please reload this page.