crypto: add SubtleCrypto.supports feature detection in Web Cryptography · nodejs/node@f4fbcca

@@ -101,6 +101,10 @@ Key Formats:

101101

* `'raw-secret'`

102102

* `'raw-seed'`

103103104+

Methods:

105+106+

* [`SubtleCrypto.supports()`][]

107+104108

## Secure Curves in the Web Cryptography API

105109106110

> Stability: 1.1 - Active development

@@ -387,6 +391,76 @@ async function digest(data, algorithm = 'SHA-512') {

387391

}

388392

```

389393394+

### Checking for runtime algorithm support

395+396+

[`SubtleCrypto.supports()`][] allows feature detection in Web Crypto API,

397+

which can be used to detect whether a given algorithm identifier

398+

(including its parameters) is supported for the given operation.

399+400+

This example derives a key from a password using Argon2, if available,

401+

or PBKDF2, otherwise; and then encrypts and decrypts some text with it

402+

using AES-OCB, if available, and AES-GCM, otherwise.

403+404+

```mjs

405+

const { SubtleCrypto, crypto } = globalThis;

406+407+

const password = 'correct horse battery staple';

408+

const derivationAlg =

409+

SubtleCrypto.supports?.('importKey', 'Argon2id') ?

410+

'Argon2id' :

411+

'PBKDF2';

412+

const encryptionAlg =

413+

SubtleCrypto.supports?.('importKey', 'AES-OCB') ?

414+

'AES-OCB' :

415+

'AES-GCM';

416+

const passwordKey = await crypto.subtle.importKey(

417+

derivationAlg === 'Argon2id' ? 'raw-secret' : 'raw',

418+

new TextEncoder().encode(password),

419+

derivationAlg,

420+

false,

421+

['deriveKey'],

422+

);

423+

const nonce = crypto.getRandomValues(new Uint8Array(16));

424+

const derivationParams =

425+

derivationAlg === 'Argon2id' ?

426+

{

427+

nonce,

428+

parallelism: 4,

429+

memory: 2 ** 21,

430+

passes: 1,

431+

} :

432+

{

433+

salt: nonce,

434+

iterations: 100_000,

435+

hash: 'SHA-256',

436+

};

437+

const key = await crypto.subtle.deriveKey(

438+

{

439+

name: derivationAlg,

440+

...derivationParams,

441+

},

442+

passwordKey,

443+

{

444+

name: encryptionAlg,

445+

length: 256,

446+

},

447+

false,

448+

['encrypt', 'decrypt'],

449+

);

450+

const plaintext = 'Hello, world!';

451+

const iv = crypto.getRandomValues(new Uint8Array(16));

452+

const encrypted = await crypto.subtle.encrypt(

453+

{ name: encryptionAlg, iv },

454+

key,

455+

new TextEncoder().encode(plaintext),

456+

);

457+

const decrypted = new TextDecoder().decode(await crypto.subtle.decrypt(

458+

{ name: encryptionAlg, iv },

459+

key,

460+

encrypted,

461+

));

462+

```

463+390464

## Algorithm matrix

391465392466

The table details the algorithms supported by the Node.js Web Crypto API

@@ -591,6 +665,27 @@ added: v15.0.0

591665

added: v15.0.0

592666

-->

593667668+

### Static method: `SubtleCrypto.supports(operation, algorithm[, lengthOrAdditionalAlgorithm])`

669+670+

<!-- YAML

671+

added: REPLACEME

672+

-->

673+674+

> Stability: 1.1 - Active development

675+676+

<!--lint disable maximum-line-length remark-lint-->

677+678+

* `operation` {string} "encrypt", "decrypt", "sign", "verify", "digest", "generateKey", "deriveKey", "deriveBits", "importKey", "exportKey", "wrapKey", or "unwrapKey"

679+

* `algorithm` {string|Algorithm}

680+

* `lengthOrAdditionalAlgorithm` {null|number|string|Algorithm|undefined} Depending on the operation this is either ignored, the value of the length argument when operation is "deriveBits", the algorithm of key to be derived when operation is "deriveKey", the algorithm of key to be exported before wrapping when operation is "wrapKey", or the algorithm of key to be imported after unwrapping when operation is "unwrapKey". **Default:** `null` when operation is "deriveBits", `undefined` otherwise.

681+

* Returns: {boolean} Indicating whether the implementation supports the given operation

682+683+

<!--lint enable maximum-line-length remark-lint-->

684+685+

Allows feature detection in Web Crypto API,

686+

which can be used to detect whether a given algorithm identifier

687+

(including its parameters) is supported for the given operation.

688+594689

### `subtle.decrypt(algorithm, key, data)`

595690596691

<!-- YAML

@@ -1922,3 +2017,4 @@ The length (in bytes) of the random salt to use.

19222017

[RFC 4122]: https://www.rfc-editor.org/rfc/rfc4122.txt

19232018

[Secure Curves in the Web Cryptography API]: #secure-curves-in-the-web-cryptography-api

19242019

[Web Crypto API]: https://www.w3.org/TR/WebCryptoAPI/

2020+

[`SubtleCrypto.supports()`]: #static-method-subtlecryptosupportsoperation-algorithm-lengthoradditionalalgorithm