From 7e5da97d157a9db0fa0f9e8bc5b3efe92c05588a 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`