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 targos committed Mar 28, 2019
1 parent 652e5f8 commit 1ecee83
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 @@ -3433,6 +3433,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 @@ -6314,6 +6318,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

2 comments on commit 1ecee83

@zhangliang-xiaohe-hanxin

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it in latest version of node already?

@Trott
Copy link
Member

@Trott Trott commented on 1ecee83 Jul 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it in latest version of node already?

Yes, this was added in 12.0.0.

Please sign in to comment.