Skip to content

Commit

Permalink
crypto: add support for x25119 and x448 KeyObjects
Browse files Browse the repository at this point in the history
PR-URL: #26774
Refs: #26626
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
panva authored and tniessen committed Mar 25, 2019
1 parent 4a07a62 commit 85fda7e
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 7 deletions.
11 changes: 9 additions & 2 deletions doc/api/crypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -1129,14 +1129,17 @@ passing keys as strings or `Buffer`s due to improved security features.
<!-- YAML
added: v11.6.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/26774
description: Added support for `'x25519'` and `'x448'`
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/26319
description: Added support for `'ed25519'` and `'ed448'`
-->
* {string}

For asymmetric keys, this property represents the type of the embedded key
(`'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, or `'ed448'`).
(`'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`, `'x25519'` or `'x448'`).
This property is `undefined` for symmetric keys.

### keyObject.export([options])
Expand Down Expand Up @@ -1903,6 +1906,9 @@ algorithm names.
<!-- YAML
added: v10.12.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/26774
description: Add ability to generate X25519 and X448 key pairs.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/26554
description: Add ability to generate Ed25519 and Ed448 key pairs.
Expand All @@ -1911,7 +1917,8 @@ changes:
description: The `generateKeyPair` and `generateKeyPairSync` functions now
produce key objects if no encoding was specified.
-->
* `type`: {string} Must be `'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, or `'ed448'`.
* `type`: {string} Must be `'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`,
`'x25519'`, or `'x448'`.
* `options`: {Object}
- `modulusLength`: {number} Key size in bits (RSA, DSA).
- `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`.
Expand Down
22 changes: 20 additions & 2 deletions lib/internal/crypto/keygen.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const {
generateKeyPairEdDSA,
EVP_PKEY_ED25519,
EVP_PKEY_ED448,
EVP_PKEY_X25519,
EVP_PKEY_X448,
OPENSSL_EC_NAMED_CURVE,
OPENSSL_EC_EXPLICIT_CURVE
} = internalBinding('crypto');
Expand Down Expand Up @@ -197,8 +199,24 @@ function check(type, options, callback) {
break;
case 'ed25519':
case 'ed448':
case 'x25519':
case 'x448':
{
const id = type === 'ed25519' ? EVP_PKEY_ED25519 : EVP_PKEY_ED448;
let id;
switch (type) {
case 'ed25519':
id = EVP_PKEY_ED25519;
break;
case 'ed448':
id = EVP_PKEY_ED448;
break;
case 'x25519':
id = EVP_PKEY_X25519;
break;
case 'x448':
id = EVP_PKEY_X448;
break;
}
impl = (wrap) => generateKeyPairEdDSA(id,
publicFormat, publicType,
privateFormat, privateType,
Expand All @@ -208,7 +226,7 @@ function check(type, options, callback) {
default:
throw new ERR_INVALID_ARG_VALUE('type', type,
"must be one of 'rsa', 'dsa', 'ec', " +
"'ed25519', 'ed448'");
"'ed25519', 'ed448', 'x25519', 'x448'");
}

if (options) {
Expand Down
2 changes: 2 additions & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2;
V(crypto_ec_string, "ec") \
V(crypto_ed25519_string, "ed25519") \
V(crypto_ed448_string, "ed448") \
V(crypto_x25519_string, "x25519") \
V(crypto_x448_string, "x448") \
V(crypto_rsa_string, "rsa") \
V(cwd_string, "cwd") \
V(data_string, "data") \
Expand Down
6 changes: 6 additions & 0 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3533,6 +3533,10 @@ Local<String> KeyObject::GetAsymmetricKeyType() const {
return env()->crypto_ed25519_string();
case EVP_PKEY_ED448:
return env()->crypto_ed448_string();
case EVP_PKEY_X25519:
return env()->crypto_x25519_string();
case EVP_PKEY_X448:
return env()->crypto_x448_string();
default:
CHECK(false);
}
Expand Down Expand Up @@ -6436,6 +6440,8 @@ void Initialize(Local<Object> target,
env->SetMethod(target, "generateKeyPairEdDSA", GenerateKeyPairEdDSA);
NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519);
NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448);
NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519);
NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448);
NODE_DEFINE_CONSTANT(target, OPENSSL_EC_NAMED_CURVE);
NODE_DEFINE_CONSTANT(target, OPENSSL_EC_EXPLICIT_CURVE);
NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/test_x25519_privkey.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEILD/13Y5R/tmcCjZVSooIcpfGvZxf+qt6dMu5FYaOC1a
-----END PRIVATE KEY-----
3 changes: 3 additions & 0 deletions test/fixtures/test_x25519_pubkey.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEAYHCXnz085FKclfnx+gdiGXAyy7BhJjx0pxyE4wbXF0A=
-----END PUBLIC KEY-----
4 changes: 4 additions & 0 deletions test/fixtures/test_x448_privkey.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PRIVATE KEY-----
MEYCAQAwBQYDK2VvBDoEOPilLIAZTQqUbFb0LhTGaqn47zN2p2yGVk+2hhQQk9C8
8SvFqEFw73YITSIJ2NUBZnZKNz2nGkrm
-----END PRIVATE KEY-----
4 changes: 4 additions & 0 deletions test/fixtures/test_x448_pubkey.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MEIwBQYDK2VvAzkAbceBBM+LkveTK09QojZdnHokCh7lOWxyVZrlbH3Ny3WorprD
Iir5A6heZzlRnz1elOHp7ZpPfWk=
-----END PUBLIC KEY-----
8 changes: 7 additions & 1 deletion test/parallel/test-crypto-key-objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,13 @@ const privatePem = fixtures.readSync('test_rsa_privkey.pem', 'ascii');
keyType: 'ed25519' },
{ private: fixtures.readSync('test_ed448_privkey.pem', 'ascii'),
public: fixtures.readSync('test_ed448_pubkey.pem', 'ascii'),
keyType: 'ed448' }
keyType: 'ed448' },
{ private: fixtures.readSync('test_x25519_privkey.pem', 'ascii'),
public: fixtures.readSync('test_x25519_pubkey.pem', 'ascii'),
keyType: 'x25519' },
{ private: fixtures.readSync('test_x448_privkey.pem', 'ascii'),
public: fixtures.readSync('test_x448_pubkey.pem', 'ascii'),
keyType: 'x448' }
].forEach((info) => {
const keyType = info.keyType;

Expand Down
5 changes: 3 additions & 2 deletions test/parallel/test-crypto-keygen.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,8 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
type: TypeError,
code: 'ERR_INVALID_ARG_VALUE',
message: "The argument 'type' must be one of " +
"'rsa', 'dsa', 'ec', 'ed25519', 'ed448'. Received 'rsa2'"
"'rsa', 'dsa', 'ec', 'ed25519', 'ed448'," +
" 'x25519', 'x448'. Received 'rsa2'"
});
}

Expand Down Expand Up @@ -786,7 +787,7 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
// Test EdDSA key generation.
{
if (!/^1\.1\.0/.test(process.versions.openssl)) {
['ed25519', 'ed448'].forEach((keyType) => {
['ed25519', 'ed448', 'x25519', 'x448'].forEach((keyType) => {
generateKeyPair(keyType, common.mustCall((err, publicKey, privateKey) => {
assert.ifError(err);

Expand Down

0 comments on commit 85fda7e

Please sign in to comment.