Skip to content

Commit 85fda7e

Browse files
panvatniessen
authored andcommitted
crypto: add support for x25119 and x448 KeyObjects
PR-URL: #26774 Refs: #26626 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 4a07a62 commit 85fda7e

10 files changed

+61
-7
lines changed

doc/api/crypto.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -1129,14 +1129,17 @@ passing keys as strings or `Buffer`s due to improved security features.
11291129
<!-- YAML
11301130
added: v11.6.0
11311131
changes:
1132+
- version: REPLACEME
1133+
pr-url: https://github.com/nodejs/node/pull/26774
1134+
description: Added support for `'x25519'` and `'x448'`
11321135
- version: REPLACEME
11331136
pr-url: https://github.com/nodejs/node/pull/26319
11341137
description: Added support for `'ed25519'` and `'ed448'`
11351138
-->
11361139
* {string}
11371140

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

11421145
### keyObject.export([options])
@@ -1903,6 +1906,9 @@ algorithm names.
19031906
<!-- YAML
19041907
added: v10.12.0
19051908
changes:
1909+
- version: REPLACEME
1910+
pr-url: https://github.com/nodejs/node/pull/26774
1911+
description: Add ability to generate X25519 and X448 key pairs.
19061912
- version: REPLACEME
19071913
pr-url: https://github.com/nodejs/node/pull/26554
19081914
description: Add ability to generate Ed25519 and Ed448 key pairs.
@@ -1911,7 +1917,8 @@ changes:
19111917
description: The `generateKeyPair` and `generateKeyPairSync` functions now
19121918
produce key objects if no encoding was specified.
19131919
-->
1914-
* `type`: {string} Must be `'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, or `'ed448'`.
1920+
* `type`: {string} Must be `'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`,
1921+
`'x25519'`, or `'x448'`.
19151922
* `options`: {Object}
19161923
- `modulusLength`: {number} Key size in bits (RSA, DSA).
19171924
- `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`.

lib/internal/crypto/keygen.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ const {
88
generateKeyPairEdDSA,
99
EVP_PKEY_ED25519,
1010
EVP_PKEY_ED448,
11+
EVP_PKEY_X25519,
12+
EVP_PKEY_X448,
1113
OPENSSL_EC_NAMED_CURVE,
1214
OPENSSL_EC_EXPLICIT_CURVE
1315
} = internalBinding('crypto');
@@ -197,8 +199,24 @@ function check(type, options, callback) {
197199
break;
198200
case 'ed25519':
199201
case 'ed448':
202+
case 'x25519':
203+
case 'x448':
200204
{
201-
const id = type === 'ed25519' ? EVP_PKEY_ED25519 : EVP_PKEY_ED448;
205+
let id;
206+
switch (type) {
207+
case 'ed25519':
208+
id = EVP_PKEY_ED25519;
209+
break;
210+
case 'ed448':
211+
id = EVP_PKEY_ED448;
212+
break;
213+
case 'x25519':
214+
id = EVP_PKEY_X25519;
215+
break;
216+
case 'x448':
217+
id = EVP_PKEY_X448;
218+
break;
219+
}
202220
impl = (wrap) => generateKeyPairEdDSA(id,
203221
publicFormat, publicType,
204222
privateFormat, privateType,
@@ -208,7 +226,7 @@ function check(type, options, callback) {
208226
default:
209227
throw new ERR_INVALID_ARG_VALUE('type', type,
210228
"must be one of 'rsa', 'dsa', 'ec', " +
211-
"'ed25519', 'ed448'");
229+
"'ed25519', 'ed448', 'x25519', 'x448'");
212230
}
213231

214232
if (options) {

src/env.h

+2
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2;
147147
V(crypto_ec_string, "ec") \
148148
V(crypto_ed25519_string, "ed25519") \
149149
V(crypto_ed448_string, "ed448") \
150+
V(crypto_x25519_string, "x25519") \
151+
V(crypto_x448_string, "x448") \
150152
V(crypto_rsa_string, "rsa") \
151153
V(cwd_string, "cwd") \
152154
V(data_string, "data") \

src/node_crypto.cc

+6
Original file line numberDiff line numberDiff line change
@@ -3533,6 +3533,10 @@ Local<String> KeyObject::GetAsymmetricKeyType() const {
35333533
return env()->crypto_ed25519_string();
35343534
case EVP_PKEY_ED448:
35353535
return env()->crypto_ed448_string();
3536+
case EVP_PKEY_X25519:
3537+
return env()->crypto_x25519_string();
3538+
case EVP_PKEY_X448:
3539+
return env()->crypto_x448_string();
35363540
default:
35373541
CHECK(false);
35383542
}
@@ -6436,6 +6440,8 @@ void Initialize(Local<Object> target,
64366440
env->SetMethod(target, "generateKeyPairEdDSA", GenerateKeyPairEdDSA);
64376441
NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519);
64386442
NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448);
6443+
NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519);
6444+
NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448);
64396445
NODE_DEFINE_CONSTANT(target, OPENSSL_EC_NAMED_CURVE);
64406446
NODE_DEFINE_CONSTANT(target, OPENSSL_EC_EXPLICIT_CURVE);
64416447
NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);

test/fixtures/test_x25519_privkey.pem

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MC4CAQAwBQYDK2VuBCIEILD/13Y5R/tmcCjZVSooIcpfGvZxf+qt6dMu5FYaOC1a
3+
-----END PRIVATE KEY-----

test/fixtures/test_x25519_pubkey.pem

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MCowBQYDK2VuAyEAYHCXnz085FKclfnx+gdiGXAyy7BhJjx0pxyE4wbXF0A=
3+
-----END PUBLIC KEY-----

test/fixtures/test_x448_privkey.pem

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MEYCAQAwBQYDK2VvBDoEOPilLIAZTQqUbFb0LhTGaqn47zN2p2yGVk+2hhQQk9C8
3+
8SvFqEFw73YITSIJ2NUBZnZKNz2nGkrm
4+
-----END PRIVATE KEY-----

test/fixtures/test_x448_pubkey.pem

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MEIwBQYDK2VvAzkAbceBBM+LkveTK09QojZdnHokCh7lOWxyVZrlbH3Ny3WorprD
3+
Iir5A6heZzlRnz1elOHp7ZpPfWk=
4+
-----END PUBLIC KEY-----

test/parallel/test-crypto-key-objects.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,13 @@ const privatePem = fixtures.readSync('test_rsa_privkey.pem', 'ascii');
174174
keyType: 'ed25519' },
175175
{ private: fixtures.readSync('test_ed448_privkey.pem', 'ascii'),
176176
public: fixtures.readSync('test_ed448_pubkey.pem', 'ascii'),
177-
keyType: 'ed448' }
177+
keyType: 'ed448' },
178+
{ private: fixtures.readSync('test_x25519_privkey.pem', 'ascii'),
179+
public: fixtures.readSync('test_x25519_pubkey.pem', 'ascii'),
180+
keyType: 'x25519' },
181+
{ private: fixtures.readSync('test_x448_privkey.pem', 'ascii'),
182+
public: fixtures.readSync('test_x448_pubkey.pem', 'ascii'),
183+
keyType: 'x448' }
178184
].forEach((info) => {
179185
const keyType = info.keyType;
180186

test/parallel/test-crypto-keygen.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
425425
type: TypeError,
426426
code: 'ERR_INVALID_ARG_VALUE',
427427
message: "The argument 'type' must be one of " +
428-
"'rsa', 'dsa', 'ec', 'ed25519', 'ed448'. Received 'rsa2'"
428+
"'rsa', 'dsa', 'ec', 'ed25519', 'ed448'," +
429+
" 'x25519', 'x448'. Received 'rsa2'"
429430
});
430431
}
431432

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

0 commit comments

Comments
 (0)