From 4cf9037122f2580bf45fa6d7aea4bc3bfa32884e Mon Sep 17 00:00:00 2001
From: Filip Skokan
Date: Sat, 4 Jun 2022 08:20:27 +0200
Subject: [PATCH] crypto: add CFRG curves to Web Crypto API
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
PR-URL: https://github.com/nodejs/node/pull/42507
Reviewed-By: Tobias Nießen
---
doc/api/webcrypto.md | 341 +++++--------
lib/internal/crypto/cfrg.js | 369 ++++++++++++++
lib/internal/crypto/diffiehellman.js | 16 +-
lib/internal/crypto/ec.js | 302 ++---------
lib/internal/crypto/keys.js | 2 +-
lib/internal/crypto/util.js | 10 +-
lib/internal/crypto/webcrypto.js | 103 +++-
src/crypto/crypto_ec.cc | 8 +-
test/fixtures/crypto/eddsa.js | 51 ++
test/parallel/test-crypto-keygen.js | 16 -
.../test-webcrypto-derivebits-cfrg.js | 213 ++++++++
.../test-webcrypto-derivebits-ecdh.js | 2 +-
test/parallel/test-webcrypto-derivebits.js | 26 +
.../parallel/test-webcrypto-derivekey-cfrg.js | 188 +++++++
.../parallel/test-webcrypto-derivekey-ecdh.js | 2 +-
test/parallel/test-webcrypto-derivekey.js | 43 +-
test/parallel/test-webcrypto-ed25519-ed448.js | 481 ------------------
.../test-webcrypto-export-import-cfrg.js | 308 +++++++++++
test/parallel/test-webcrypto-keygen.js | 94 ++++
.../test-webcrypto-sign-verify-ecdsa.js | 24 +
.../test-webcrypto-sign-verify-eddsa.js | 263 ++++++++++
test/parallel/test-webcrypto-sign-verify.js | 40 ++
test/parallel/test-webcrypto-x25519-x448.js | 315 ------------
tools/doc/type-parser.mjs | 15 +-
24 files changed, 1898 insertions(+), 1334 deletions(-)
create mode 100644 lib/internal/crypto/cfrg.js
create mode 100644 test/fixtures/crypto/eddsa.js
create mode 100644 test/parallel/test-webcrypto-derivebits-cfrg.js
create mode 100644 test/parallel/test-webcrypto-derivekey-cfrg.js
delete mode 100644 test/parallel/test-webcrypto-ed25519-ed448.js
create mode 100644 test/parallel/test-webcrypto-export-import-cfrg.js
create mode 100644 test/parallel/test-webcrypto-sign-verify-eddsa.js
delete mode 100644 test/parallel/test-webcrypto-x25519-x448.js
diff --git a/doc/api/webcrypto.md b/doc/api/webcrypto.md
index 9454fead349b69..8973ce9d820545 100644
--- a/doc/api/webcrypto.md
+++ b/doc/api/webcrypto.md
@@ -1,5 +1,21 @@
# Web Crypto API
+
+
> Stability: 1 - Experimental
@@ -69,22 +85,22 @@ async function generateEcKey(namedCurve = 'P-521') {
}
```
-#### ED25519/ED448/X25519/X448 key pairs
+#### Ed25519/Ed448/X25519/X448 key pairs
+
+> Stability: 1 - Experimental
```js
const { subtle } = require('node:crypto').webcrypto;
async function generateEd25519Key() {
return subtle.generateKey({
- name: 'NODE-ED25519',
- namedCurve: 'NODE-ED25519',
+ name: 'Ed25519',
}, true, ['sign', 'verify']);
}
async function generateX25519Key() {
return subtle.generateKey({
- name: 'ECDH',
- namedCurve: 'NODE-X25519',
+ name: 'X25519',
}, true, ['deriveKey']);
}
```
@@ -315,7 +331,11 @@ implementation and the APIs supported for each:
| `'RSA-PSS'` | ✔ | ✔ | ✔ | | | | | | | ✔ | ✔ | |
| `'RSA-OAEP'` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | | | |
| `'ECDSA'` | ✔ | ✔ | ✔ | | | | | | | ✔ | ✔ | |
+| `'Ed25519'`[^2] | ✔ | ✔ | ✔ | | | | | | | ✔ | ✔ | |
+| `'Ed448'`[^2] | ✔ | ✔ | ✔ | | | | | | | ✔ | ✔ | |
| `'ECDH'` | ✔ | ✔ | ✔ | | | | | ✔ | ✔ | | | |
+| `'X25519'`[^2] | ✔ | ✔ | ✔ | | | | | ✔ | ✔ | | | |
+| `'X448'`[^2] | ✔ | ✔ | ✔ | | | | | ✔ | ✔ | | | |
| `'AES-CTR'` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | | | |
| `'AES-CBC'` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | | | |
| `'AES-GCM'` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | | | |
@@ -329,8 +349,6 @@ implementation and the APIs supported for each:
| `'SHA-512'` | | | | | | | | | | | | ✔ |
| `'NODE-DSA'`[^1] | ✔ | ✔ | ✔ | | | | | | | ✔ | ✔ | |
| `'NODE-DH'`[^1] | ✔ | ✔ | ✔ | | | | | ✔ | ✔ | | | |
-| `'NODE-ED25519'`[^1] | ✔ | ✔ | ✔ | | | | | | | ✔ | ✔ | |
-| `'NODE-ED448'`[^1] | ✔ | ✔ | ✔ | | | | | | | ✔ | ✔ | |
## Class: `Crypto`
@@ -394,7 +412,7 @@ added: v15.0.0
-* Type: {AesKeyGenParams|RsaHashedKeyGenParams|EcKeyGenParams|HmacKeyGenParams|NodeDsaKeyGenParams|NodeDhKeyGenParams|NodeEdKeyGenParams}
+* Type: {AesKeyGenParams|RsaHashedKeyGenParams|EcKeyGenParams|HmacKeyGenParams|NodeDsaKeyGenParams|NodeDhKeyGenParams}
@@ -459,7 +477,11 @@ Valid key usages depend on the key algorithm (identified by
| `'AES-GCM'` | ✔ | ✔ | | | | | ✔ | ✔ |
| `'AES-KW'` | | | | | | | ✔ | ✔ |
| `'ECDH'` | | | | | ✔ | ✔ | | |
+| `'X25519'`[^2] | | | | | ✔ | ✔ | | |
+| `'X448'`[^2] | | | | | ✔ | ✔ | | |
| `'ECDSA'` | | | ✔ | ✔ | | | | |
+| `'Ed25519'`[^2] | | | ✔ | ✔ | | | | |
+| `'Ed448'`[^2] | | | ✔ | ✔ | | | | |
| `'HDKF'` | | | | | ✔ | ✔ | | |
| `'HMAC'` | | | ✔ | ✔ | | | | |
| `'PBKDF2'` | | | | | ✔ | ✔ | | |
@@ -469,8 +491,6 @@ Valid key usages depend on the key algorithm (identified by
| `'NODE-DSA'`[^1] | | | ✔ | ✔ | | | | |
| `'NODE-DH'`[^1] | | | | | ✔ | ✔ | | |
| `'NODE-SCRYPT'`[^1] | | | | | ✔ | ✔ | | |
-| `'NODE-ED25519'`[^1] | | | ✔ | ✔ | | | | |
-| `'NODE-ED448'`[^1] | | | ✔ | ✔ | | | | |
## Class: `CryptoKeyPair`
@@ -530,11 +550,15 @@ The algorithms currently supported include:
-* `algorithm`: {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params|NodeDhDeriveBitsParams|NodeScryptParams}
+* `algorithm`: {AlgorithmIdentifier|EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params|NodeDhDeriveBitsParams|NodeScryptParams}
* `baseKey`: {CryptoKey}
* `length`: {number}
* Returns: {Promise} containing {ArrayBuffer}
@@ -559,11 +583,15 @@ The algorithms currently supported include:
-* `algorithm`: {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params|NodeDhDeriveBitsParams|NodeScryptParams}
+* `algorithm`: {AlgorithmIdentifier|EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params|NodeDhDeriveBitsParams|NodeScryptParams}
* `baseKey`: {CryptoKey}
* `derivedKeyAlgorithm`: {HmacKeyGenParams|AesKeyGenParams}
* `extractable`: {boolean}
@@ -640,6 +668,10 @@ The algorithms currently supported include:
-* `algorithm`: {RsaHashedKeyGenParams|EcKeyGenParams|HmacKeyGenParams|AesKeyGenParams|NodeDsaKeyGenParams|NodeDhKeyGenParams|NodeEdKeyGenParams}
+* `algorithm`: {AlgorithmIdentifier|RsaHashedKeyGenParams|EcKeyGenParams|HmacKeyGenParams|AesKeyGenParams|NodeDsaKeyGenParams|NodeDhKeyGenParams}
@@ -713,11 +745,13 @@ include:
* `'RSA-PSS'`
* `'RSA-OAEP'`
* `'ECDSA'`
+* `'Ed25519'`[^2]
+* `'Ed448'`[^2]
* `'ECDH'`
+* `'X25519'`[^2]
+* `'X448'`[^2]
* `'NODE-DSA'`[^1]
* `'NODE-DH'`[^1]
-* `'NODE-ED25519'`[^1]
-* `'NODE-ED448'`[^1]
The {CryptoKey} (secret key) generating algorithms supported include:
@@ -732,6 +766,10 @@ The {CryptoKey} (secret key) generating algorithms supported include:
-* `algorithm`: {RsaHashedImportParams|EcKeyImportParams|HmacImportParams|AesImportParams|Pbkdf2ImportParams|NodeDsaImportParams|NodeDhImportParams|NodeScryptImportParams|NodeEdKeyImportParams}
+* `algorithm`: {AlgorithmIdentifier|RsaHashedImportParams|EcKeyImportParams|HmacImportParams|NodeDsaImportParams}
@@ -770,7 +808,11 @@ The algorithms currently supported include:
| `'AES-GCM'` | | | ✔ | ✔ |
| `'AES-KW'` | | | ✔ | ✔ |
| `'ECDH'` | ✔ | ✔ | ✔ | ✔ |
+| `'X25519'`[^2] | ✔ | ✔ | ✔ | ✔ |
+| `'X448'`[^2] | ✔ | ✔ | ✔ | ✔ |
| `'ECDSA'` | ✔ | ✔ | ✔ | ✔ |
+| `'Ed25519'`[^2] | ✔ | ✔ | ✔ | ✔ |
+| `'Ed448'`[^2] | ✔ | ✔ | ✔ | ✔ |
| `'HDKF'` | | | | ✔ |
| `'HMAC'` | | | ✔ | ✔ |
| `'PBKDF2'` | | | | ✔ |
@@ -780,18 +822,20 @@ The algorithms currently supported include:
| `'NODE-DSA'`[^1] | ✔ | ✔ | | |
| `'NODE-DH'`[^1] | ✔ | ✔ | | |
| `'NODE-SCRYPT'`[^1] | | | | ✔ |
-| `'NODE-ED25519'`[^1] | ✔ | ✔ | ✔ | ✔ |
-| `'NODE-ED448'`[^1] | ✔ | ✔ | ✔ | ✔ |
### `subtle.sign(algorithm, key, data)`
-* `algorithm`: {RsaSignParams|RsaPssParams|EcdsaParams|HmacParams|NodeDsaSignParams}
+* `algorithm`: {AlgorithmIdentifier|RsaPssParams|EcdsaParams|Ed448Params}
* `key`: {CryptoKey}
* `data`: {ArrayBuffer|TypedArray|DataView|Buffer}
* Returns: {Promise} containing {ArrayBuffer}
@@ -808,10 +852,10 @@ The algorithms currently supported include:
* `'RSASSA-PKCS1-v1_5'`
* `'RSA-PSS'`
* `'ECDSA'`
+* `'Ed25519'`[^2]
+* `'Ed448'`[^2]
* `'HMAC'`
* `'NODE-DSA'`[^1]
-* `'NODE-ED25519'`[^1]
-* `'NODE-ED448'`[^1]
### `subtle.unwrapKey(format, wrappedKey, unwrappingKey, unwrapAlgo, unwrappedKeyAlgo, extractable, keyUsages)`
@@ -825,8 +869,8 @@ added: v15.0.0
-* `unwrapAlgo`: {RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams|AesKwParams}
-* `unwrappedKeyAlgo`: {RsaHashedImportParams|EcKeyImportParams|HmacImportParams|AesImportParams}
+* `unwrapAlgo`: {AlgorithmIdentifier|RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams}
+* `unwrappedKeyAlgo`: {AlgorithmIdentifier|RsaHashedImportParams|EcKeyImportParams|HmacImportParams}
@@ -870,11 +914,15 @@ The unwrapped key algorithms supported include:
-* `algorithm`: {RsaSignParams|RsaPssParams|EcdsaParams|HmacParams|NodeDsaSignParams}
+* `algorithm`: {AlgorithmIdentifier|RsaPssParams|EcdsaParams|Ed448Params}
* `key`: {CryptoKey}
* `signature`: {ArrayBuffer|TypedArray|DataView|Buffer}
* `data`: {ArrayBuffer|TypedArray|DataView|Buffer}
@@ -892,10 +940,10 @@ The algorithms currently supported include:
* `'RSASSA-PKCS1-v1_5'`
* `'RSA-PSS'`
* `'ECDSA'`
+* `'Ed25519'`[^2]
+* `'Ed448'`[^2]
* `'HMAC'`
* `'NODE-DSA'`[^1]
-* `'NODE-ED25519'`[^1]
-* `'NODE-ED448'`[^1]
### `subtle.wrapKey(format, key, wrappingKey, wrapAlgo)`
@@ -903,12 +951,16 @@ The algorithms currently supported include:
added: v15.0.0
-->
+
+
* `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`.
* `key`: {CryptoKey}
* `wrappingKey`: {CryptoKey}
-* `wrapAlgo`: {RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams|AesKwParams}
+* `wrapAlgo`: {AlgorithmIdentifier|RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams}
* Returns: {Promise} containing {ArrayBuffer}
+
+
In cryptography, "wrapping a key" refers to exporting and then encrypting the
keying material. The `subtle.wrapKey()` method exports the keying material into
the format identified by `format`, then encrypts it using the method and
@@ -933,6 +985,20 @@ The algorithm parameter objects define the methods and parameters used by
the various {SubtleCrypto} methods. While described here as "classes", they
are simple JavaScript dictionary objects.
+### Class: `AlgorithmIdentifier`
+
+
+
+#### `algorithmIdentifier.name`
+
+
+
+* Type: {string}
+
### Class: `AesCbcParams`
-
-#### `aesImportParams.name`
-
-
-
-* Type: {string} Must be one of `'AES-CTR'`, `'AES-CBC'`, `'AES-GCM'`, or
- `'AES-KW'`.
-
### Class: `AesKeyGenParams`
-
-#### `aesKwParams.name`
-
-
-
-* Type: {string} Must be `'AES-KW'`.
-
### Class: `EcdhKeyDeriveParams`
-* Type: {string} Must be `'ECDH'`.
+* Type: {string} Must be `'ECDH'`, `'X25519'`, or `'X448'`.
#### `ecdhKeyDeriveParams.public`
@@ -1181,8 +1218,7 @@ added: v15.0.0
added: v15.0.0
-->
-* Type: {string} Must be one of `'P-256'`, `'P-384'`, `'P-521'`,
- `'NODE-ED25519'`, `'NODE-ED448'`, `'NODE-X25519'`, or `'NODE-X448'`.
+* Type: {string} Must be one of `'P-256'`, `'P-384'`, `'P-521'`.
### Class: `EcKeyImportParams`
@@ -1204,8 +1240,34 @@ added: v15.0.0
added: v15.0.0
-->
-* Type: {string} Must be one of `'P-256'`, `'P-384'`, `'P-521'`,
- `'NODE-ED25519'`, `'NODE-ED448'`, `'NODE-X25519'`, or `'NODE-X448'`.
+* Type: {string} Must be one of `'P-256'`, `'P-384'`, `'P-521'`.
+
+### Class: `Ed448Params`
+
+
+
+#### `ed448Params.name`
+
+
+
+* Type: {string} Must be `'Ed448'`.
+
+#### `ed448Params.context`
+
+
+
+* Type: {ArrayBuffer|TypedArray|DataView|Buffer|undefined}
+
+The `context` member represents the optional context data to associate with
+the message.
+The Node.js Web Crypto API implementation only supports zero-length context
+which is equivalent to not providing context at all.
### Class: `HkdfParams`
@@ -1350,34 +1412,6 @@ added: v15.0.0
* Type: {string} Must be `'HMAC'`.
-### Class: `HmacParams`
-
-
-
-#### `hmacParams.name`
-
-
-
-* Type: {string} Must be `'HMAC'`.
-
-### Class: `Pbkdf2ImportParams`
-
-
-
-#### `pbkdf2ImportParams.name`
-
-
-
-* Type: {string} Must be `'PBKDF2'`
-
### Class: `Pbkdf2Params`
-
-#### `rsaSignParams.name`
-
-
-
-* Type: {string} Must be `'RSASSA-PKCS1-v1_5'`
-
## Node.js-specific extensions
The Node.js Web Crypto API extends various aspects of the Web Crypto API.
@@ -1607,20 +1627,6 @@ added: v15.0.0
The `NODE-DH` algorithm is the common implementation of Diffie-Hellman
key agreement.
-#### Class: `NodeDhImportParams`
-
-
-
-##### `nodeDhImportParams.name`
-
-
-
-* Type: {string} Must be `'NODE-DH'`.
-
#### Class: `NodeDhKeyGenParams`
-
-##### `nodeDsaSignParams.name`
-
-
-
-* Type: {string} Must be `'NODE-DSA'`
-
-### `NODE-ED25519` and `NODE-ED448` Algorithms
-
-
-
-#### Class: `NodeEdKeyGenParams`
-
-
-
-##### `nodeEdKeyGenParams.name`
-
-
-
-* Type: {string} Must be one of `'NODE-ED25519'`, `'NODE-ED448'` or `'ECDH'`.
-
-##### `nodeEdKeyGenParams.namedCurve`
-
-
-
-* Type: {string} Must be one of `'NODE-ED25519'`, `'NODE-ED448'`,
- `'NODE-X25519'`, or `'NODE-X448'`.
-
-#### Class: `NodeEdKeyImportParams`
-
-
-
-##### `nodeEdKeyImportParams.name`
-
-
-
-* Type: {string} Must be one of `'NODE-ED25519'` or `'NODE-ED448'`
- if importing an `Ed25519` or `Ed448` key, or `'ECDH'` if importing
- an `X25519` or `X448` key.
-
-##### `nodeEdKeyImportParams.namedCurve`
-
-
-
-* Type: {string} Must be one of `'NODE-ED25519'`, `'NODE-ED448'`,
- `'NODE-X25519'`, or `'NODE-X448'`.
-
-##### `nodeEdKeyImportParams.public`
-
-
-
-* Type: {boolean}
-
-The `public` parameter is used to specify that the `'raw'` format key is to be
-interpreted as a public key. **Default:** `false`.
-
### `NODE-SCRYPT` Algorithm
-
-##### `nodeScryptImportParams.name`
-
-
-
-* Type: {string} Must be `'NODE-SCRYPT'`.
-
#### Class: `NodeScryptParams`