Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto: add key pair generation #22660

Closed
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
114 changes: 114 additions & 0 deletions doc/api/crypto.md
Expand Up @@ -1671,6 +1671,119 @@ Use [`crypto.getHashes()`][] to obtain an array of names of the available
signing algorithms. Optional `options` argument controls the
`stream.Writable` behavior.

### crypto.generateKeyPair(type, options, callback)
<!-- YAML
added: REPLACEME
-->
* `type`: {string} Must be `'rsa'`, `'dsa'` or `'ec'`.
tniessen marked this conversation as resolved.
Show resolved Hide resolved
* `options`: {Object}
- `modulusLength`: {number} Key size in bits (RSA, DSA).
- `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`.
- `divisorLength`: {number} Size of `q` in bits (DSA).
- `namedCurve`: {string} Name of the curve to use (EC).
- `publicKeyEncoding`: {Object}
- `type`: {string} Must be one of `'pkcs1'` (RSA only) or `'spki'`.
- `format`: {string} Must be `'pem'` or `'der'`.
- `privateKeyEncoding`: {Object}
- `type`: {string} Must be one of `'pkcs1'` (RSA only), `'pkcs8'` or
`'sec1'` (EC only).
- `format`: {string} Must be `'pem'` or `'der'`.
- `cipher`: {string} If specified, the private key will be encrypted with
the given `cipher` and `passphrase` using PKCS#5 v2.0 password based
encryption.
- `passphrase`: {string} The passphrase to use for encryption, see `cipher`.
* `callback`: {Function}
- `err`: {Error}
- `publicKey`: {string|Buffer}
- `privateKey`: {string|Buffer}

Generates a new asymmetric key pair of the given `type`. Only RSA, DSA and EC
are currently supported.

It is recommended to encode public keys as `'spki'` and private keys as
`'pkcs8'` with encryption:

```js
const { generateKeyPair } = require('crypto');
generateKeyPair('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'top secret'
}
}, (err, publicKey, privateKey) => {
// Handle errors and use the generated key pair.
});
```
tniessen marked this conversation as resolved.
Show resolved Hide resolved

On completion, `callback` will be called with `err` set to `undefined` and
`publicKey` / `privateKey` representing the generated key pair. When PEM
encoding was selected, the result will be a string, otherwise it will be a
buffer containing the data encoded as DER. Note that Node.js itself does not
accept DER, it is supported for interoperability with other libraries such as
WebCrypto only.

If this method is invoked as its [`util.promisify()`][]ed version, it returns
a `Promise` for an `Object` with `publicKey` and `privateKey` properties.

### crypto.generateKeyPairSync(type, options)
<!-- YAML
added: REPLACEME
-->
* `type`: {string} Must be `'rsa'`, `'dsa'` or `'ec'`.
* `options`: {Object}
- `modulusLength`: {number} Key size in bits (RSA, DSA).
- `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`.
- `divisorLength`: {number} Size of `q` in bits (DSA).
- `namedCurve`: {string} Name of the curve to use (EC).
- `publicKeyEncoding`: {Object}
- `type`: {string} Must be one of `'pkcs1'` (RSA only) or `'spki'`.
- `format`: {string} Must be `'pem'` or `'der'`.
- `privateKeyEncoding`: {Object}
- `type`: {string} Must be one of `'pkcs1'` (RSA only), `'pkcs8'` or
`'sec1'` (EC only).
- `format`: {string} Must be `'pem'` or `'der'`.
- `cipher`: {string} If specified, the private key will be encrypted with
the given `cipher` and `passphrase` using PKCS#5 v2.0 password based
encryption.
- `passphrase`: {string} The passphrase to use for encryption, see `cipher`.
* Returns: {Object}
- `publicKey`: {string|Buffer}
- `privateKey`: {string|Buffer}

Generates a new asymmetric key pair of the given `type`. Only RSA, DSA and EC
are currently supported.

It is recommended to encode public keys as `'spki'` and private keys as
`'pkcs8'` with encryption:

```js
const { generateKeyPairSync } = require('crypto');
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'top secret'
}
});
```

The return value `{ publicKey, privateKey }` represents the generated key pair.
When PEM encoding was selected, the respective key will be a string, otherwise
it will be a buffer containing the data encoded as DER.

### crypto.getCiphers()
<!-- YAML
added: v0.9.3
Expand Down Expand Up @@ -2756,6 +2869,7 @@ the `crypto`, `tls`, and `https` modules and are generally specific to OpenSSL.
[`sign.update()`]: #crypto_sign_update_data_inputencoding
[`stream.transform` options]: stream.html#stream_new_stream_transform_options
[`stream.Writable` options]: stream.html#stream_constructor_new_stream_writable_options
[`util.promisify()`]: util.html#util_util_promisify_original
[`verify.update()`]: #crypto_verify_update_data_inputencoding
[`verify.verify()`]: #crypto_verify_verify_object_signature_signatureformat
[AEAD algorithms]: https://en.wikipedia.org/wiki/Authenticated_encryption
Expand Down
5 changes: 5 additions & 0 deletions doc/api/errors.md
Expand Up @@ -729,6 +729,11 @@ be called no more than one time per instance of a `Hash` object.

[`hash.update()`][] failed for any reason. This should rarely, if ever, happen.

<a id="ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS"></a>
### ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS

The selected public or private key encoding is incompatible with other options.

<a id="ERR_CRYPTO_INVALID_DIGEST"></a>
### ERR_CRYPTO_INVALID_DIGEST

Expand Down
6 changes: 6 additions & 0 deletions lib/crypto.js
Expand Up @@ -54,6 +54,10 @@ const {
scrypt,
scryptSync
} = require('internal/crypto/scrypt');
const {
generateKeyPair,
generateKeyPairSync
} = require('internal/crypto/keygen');
const {
DiffieHellman,
DiffieHellmanGroup,
Expand Down Expand Up @@ -152,6 +156,8 @@ module.exports = exports = {
getHashes,
pbkdf2,
pbkdf2Sync,
generateKeyPair,
generateKeyPairSync,
privateDecrypt,
privateEncrypt,
publicDecrypt,
Expand Down