Skip to content

Commit

Permalink
crypto: add rsa-pss keygen parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Aug 31, 2021
1 parent 926152a commit a1e3fd9
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 22 deletions.
16 changes: 16 additions & 0 deletions doc/api/crypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -3375,6 +3375,10 @@ generateKey('hmac', { length: 64 }, (err, key) => {
<!-- YAML
added: v10.12.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/39927
description: Add ability to define `RSASSA-PSS-params` sequence parameters
for RSA-PSS keys pairs.
- version:
- v13.9.0
- v12.17.0
Expand All @@ -3397,6 +3401,10 @@ changes:
* `options`: {Object}
* `modulusLength`: {number} Key size in bits (RSA, DSA).
* `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`.
* `hashAlgorithm`: {string} Name of the message digest (RSA-PSS).
* `mgf1HashAlgorithm`: {string} Name of the message digest used by
MGF1 (RSA-PSS).
* `saltLength`: {number} Minimal salt length in bytes (RSA-PSS).
* `divisorLength`: {number} Size of `q` in bits (DSA).
* `namedCurve`: {string} Name of the curve to use (EC).
* `prime`: {Buffer} The prime parameter (DH).
Expand Down Expand Up @@ -3475,6 +3483,10 @@ a `Promise` for an `Object` with `publicKey` and `privateKey` properties.
<!-- YAML
added: v10.12.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/39927
description: Add ability to define `RSASSA-PSS-params` sequence parameters
for RSA-PSS keys pairs.
- version:
- v13.9.0
- v12.17.0
Expand All @@ -3494,6 +3506,10 @@ changes:
* `options`: {Object}
* `modulusLength`: {number} Key size in bits (RSA, DSA).
* `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`.
* `hashAlgorithm`: {string} Name of the message digest (RSA-PSS).
* `mgf1HashAlgorithm`: {string} Name of the message digest used by
MGF1 (RSA-PSS).
* `saltLength`: {number} Minimal salt length in bytes (RSA-PSS).
* `divisorLength`: {number} Size of `q` in bits (DSA).
* `namedCurve`: {string} Name of the curve to use (EC).
* `prime`: {Buffer} The prime parameter (DH).
Expand Down
13 changes: 13 additions & 0 deletions doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2801,6 +2801,19 @@ non-number value for `hints` option, a non-nullish non-boolean value for `all`
option, or a non-nullish non-boolean value for `verbatim` option in
[`dns.lookup()`][] and [`dnsPromises.lookup()`][] is deprecated.

### DEP0XXX: RSA-PSS generate key pair options
<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/39927
description: Runtime deprecation.
-->

Type: Runtime

The `'hash'` and `'mgf1Hash'` options are replaced with `'hashAlgorithm'`
and `'mgf1HashAlgorithm'`.

[Legacy URL API]: url.md#legacy-url-api
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
[RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3
Expand Down
32 changes: 25 additions & 7 deletions lib/internal/crypto/keygen.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,21 +193,39 @@ function createJob(mode, type, options) {
...encoding);
}

const { hash, mgf1Hash, saltLength } = options;
if (hash !== undefined && typeof hash !== 'string')
throw new ERR_INVALID_ARG_VALUE('options.hash', hash);
if (mgf1Hash !== undefined && typeof mgf1Hash !== 'string')
throw new ERR_INVALID_ARG_VALUE('options.mgf1Hash', mgf1Hash);
const {
hash, mgf1Hash, hashAlgorithm, mgf1HashAlgorithm, saltLength
} = options;
if (saltLength !== undefined && (!isInt32(saltLength) || saltLength < 0))
throw new ERR_INVALID_ARG_VALUE('options.saltLength', saltLength);
if (hashAlgorithm !== undefined && typeof hashAlgorithm !== 'string')
throw new ERR_INVALID_ARG_VALUE('options.hashAlgorithm', hashAlgorithm);
if (mgf1HashAlgorithm !== undefined &&
typeof mgf1HashAlgorithm !== 'string')
throw new ERR_INVALID_ARG_VALUE('options.mgf1HashAlgorithm',
mgf1HashAlgorithm);
if (hash !== undefined) {
process.emitWarning('"options.hash" is deprecated, use "options.hashAlgorithm" instead.', 'DeprecationWarning', 'DEP0XXX');
if (typeof hash !== 'string' ||
(hashAlgorithm && hash !== hashAlgorithm)) {
throw new ERR_INVALID_ARG_VALUE('options.hash', hash);
}
}
if (mgf1Hash !== undefined) {
process.emitWarning('"options.mgf1Hash" is deprecated, use "options.mgf1HashAlgorithm" instead.', 'DeprecationWarning', 'DEP0XXX');
if (typeof mgf1Hash !== 'string' ||
(mgf1HashAlgorithm && mgf1Hash !== mgf1HashAlgorithm)) {
throw new ERR_INVALID_ARG_VALUE('options.mgf1Hash', mgf1Hash);
}
}

return new RsaKeyPairGenJob(
mode,
kKeyVariantRSA_PSS,
modulusLength,
publicExponent,
hash,
mgf1Hash,
hashAlgorithm || hash,
mgf1HashAlgorithm || mgf1Hash,
saltLength,
...encoding);
}
Expand Down
30 changes: 15 additions & 15 deletions test/parallel/test-crypto-keygen.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,8 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
generateKeyPair('rsa-pss', {
modulusLength: 512,
saltLength: 16,
hash: 'sha256',
mgf1Hash: 'sha256'
hashAlgorithm: 'sha256',
mgf1HashAlgorithm: 'sha256'
}, common.mustSucceed((publicKey, privateKey) => {
assert.strictEqual(publicKey.type, 'public');
assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss');
Expand Down Expand Up @@ -1301,12 +1301,12 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
assert.throws(() => {
generateKeyPairSync('rsa-pss', {
modulusLength: 4096,
hash: hashValue
hashAlgorithm: hashValue
});
}, {
name: 'TypeError',
code: 'ERR_INVALID_ARG_VALUE',
message: "The property 'options.hash' is invalid. " +
message: "The property 'options.hashAlgorithm' is invalid. " +
`Received ${inspect(hashValue)}`
});
}
Expand All @@ -1316,8 +1316,8 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
generateKeyPair('rsa-pss', {
modulusLength: 512,
saltLength: 2147483648,
hash: 'sha256',
mgf1Hash: 'sha256'
hashAlgorithm: 'sha256',
mgf1HashAlgorithm: 'sha256'
}, common.mustNotCall());
}, {
name: 'TypeError',
Expand All @@ -1330,8 +1330,8 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
generateKeyPair('rsa-pss', {
modulusLength: 512,
saltLength: -1,
hash: 'sha256',
mgf1Hash: 'sha256'
hashAlgorithm: 'sha256',
mgf1HashAlgorithm: 'sha256'
}, common.mustNotCall());
}, {
name: 'TypeError',
Expand Down Expand Up @@ -1428,8 +1428,8 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
generateKeyPair('rsa-pss', {
modulusLength: 512,
saltLength: 16,
hash: 'sha256',
mgf1Hash: undefined
hashAlgorithm: 'sha256',
mgf1HashAlgorithm: undefined
});
},
{
Expand All @@ -1439,21 +1439,21 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
}
);

for (const mgf1Hash of [null, 0, false, {}, []]) {
for (const mgf1HashAlgorithm of [null, 0, false, {}, []]) {
assert.throws(
() => {
generateKeyPair('rsa-pss', {
modulusLength: 512,
saltLength: 16,
hash: 'sha256',
mgf1Hash
hashAlgorithm: 'sha256',
mgf1HashAlgorithm
}, common.mustNotCall());
},
{
name: 'TypeError',
code: 'ERR_INVALID_ARG_VALUE',
message: "The property 'options.mgf1Hash' is invalid. " +
`Received ${inspect(mgf1Hash)}`
message: "The property 'options.mgf1HashAlgorithm' is invalid. " +
`Received ${inspect(mgf1HashAlgorithm)}`

}
);
Expand Down

0 comments on commit a1e3fd9

Please sign in to comment.