Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 120 additions & 4 deletions doc/api/webcrypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/59544
description: Argon2 algorithms are now supported.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/59539
description: AES-OCB algorithm is now supported.
Expand Down Expand Up @@ -108,15 +111,18 @@ WICG proposal:
Algorithms:

* `'AES-OCB'`[^openssl30]
* `'Argon2d'`[^openssl32]
* `'Argon2i'`[^openssl32]
* `'Argon2id'`[^openssl32]
* `'ChaCha20-Poly1305'`
* `'cSHAKE128'`
* `'cSHAKE256'`
* `'ML-DSA-44'`[^openssl35]
* `'ML-DSA-65'`[^openssl35]
* `'ML-DSA-87'`[^openssl35]
* `'ML-KEM-1024'`[^openssl35]
* `'ML-KEM-512'`[^openssl35]
* `'ML-KEM-768'`[^openssl35]
* `'ML-KEM-1024'`[^openssl35]
* `'SHA3-256'`
* `'SHA3-384'`
* `'SHA3-512'`
Expand Down Expand Up @@ -506,6 +512,9 @@ implementation and the APIs supported for each:
| `'AES-GCM'` | ✔ | ✔ | ✔ | |
| `'AES-KW'` | ✔ | ✔ | ✔ | |
| `'AES-OCB'` | ✔ | ✔ | ✔ | |
| `'Argon2d'` | | | ✔ | |
| `'Argon2i'` | | | ✔ | |
| `'Argon2id'` | | | ✔ | |
| `'ChaCha20-Poly1305'`[^modern-algos] | ✔ | ✔ | ✔ | |
| `'ECDH'` | ✔ | ✔ | ✔ | ✔ |
| `'ECDSA'` | ✔ | ✔ | ✔ | ✔ |
Expand Down Expand Up @@ -545,6 +554,9 @@ implementation and the APIs supported for each:
| `'AES-GCM'` | ✔ | | | ✔ | | |
| `'AES-KW'` | | | | ✔ | | |
| `'AES-OCB'` | ✔ | | | ✔ | | |
| `'Argon2d'` | | | ✔ | | | |
| `'Argon2i'` | | | ✔ | | | |
| `'Argon2id'` | | | ✔ | | | |
| `'ChaCha20-Poly1305'`[^modern-algos] | ✔ | | | ✔ | | |
| `'cSHAKE128'`[^modern-algos] | | | | | | ✔ |
| `'cSHAKE256'`[^modern-algos] | | | | | | ✔ |
Expand Down Expand Up @@ -714,6 +726,9 @@ Valid key usages depend on the key algorithm (identified by
| `'AES-GCM'` | ✔ | | | ✔ | |
| `'AES-KW'` | | | | ✔ | |
| `'AES-OCB'` | ✔ | | | ✔ | |
| `'Argon2d'` | | | ✔ | | |
| `'Argon2i'` | | | ✔ | | |
| `'Argon2id'` | | | ✔ | | |
| `'ChaCha20-Poly1305'`[^modern-algos] | ✔ | | | ✔ | |
| `'ECDH'` | | | ✔ | | |
| `'ECDSA'` | | ✔ | | | |
Expand Down Expand Up @@ -864,6 +879,9 @@ The algorithms currently supported include:
<!-- YAML
added: v15.0.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/59544
description: Argon2 algorithms are now supported.
- version:
- v22.5.0
- v20.17.0
Expand All @@ -880,7 +898,7 @@ changes:

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

* `algorithm` {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params}
* `algorithm` {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params|Argon2Params}
* `baseKey` {CryptoKey}
* `length` {number|null} **Default:** `null`
* Returns: {Promise} Fulfills with an {ArrayBuffer} upon success.
Expand All @@ -900,6 +918,9 @@ containing the generated data.

The algorithms currently supported include:

* `'Argon2d'`[^modern-algos]
* `'Argon2i'`[^modern-algos]
* `'Argon2id'`[^modern-algos]
* `'ECDH'`
* `'HKDF'`
* `'PBKDF2'`
Expand All @@ -911,6 +932,9 @@ The algorithms currently supported include:
<!-- YAML
added: v15.0.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/59544
description: Argon2 algorithms are now supported.
- version:
- v18.4.0
- v16.17.0
Expand All @@ -920,7 +944,7 @@ changes:

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

* `algorithm` {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params}
* `algorithm` {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params|Argon2Params}
* `baseKey` {CryptoKey}
* `derivedKeyAlgorithm` {string|Algorithm|HmacImportParams|AesDerivedKeyParams}
* `extractable` {boolean}
Expand All @@ -940,6 +964,9 @@ generate raw keying material, then passing the result into the

The algorithms currently supported include:

* `'Argon2d'`[^modern-algos]
* `'Argon2i'`[^modern-algos]
* `'Argon2id'`[^modern-algos]
* `'ECDH'`
* `'HKDF'`
* `'PBKDF2'`
Expand Down Expand Up @@ -1235,7 +1262,7 @@ as the given `format` to create a {CryptoKey} instance using the provided
`algorithm`, `extractable`, and `keyUsages` arguments. If the import is
successful, the returned promise will be resolved with the created {CryptoKey}.

If importing a `'PBKDF2'` key, `extractable` must be `false`.
If importing KDF algorithm keys, `extractable` must be `false`.

The algorithms currently supported include:

Expand All @@ -1246,6 +1273,9 @@ The algorithms currently supported include:
| `'AES-GCM'` | | | ✔ | ✔ | ✔ | | |
| `'AES-KW'` | | | ✔ | ✔ | ✔ | | |
| `'AES-OCB'`[^modern-algos] | | | ✔ | | ✔ | | |
| `'Argon2d'`[^modern-algos] | | | | | ✔ | | |
| `'Argon2i'`[^modern-algos] | | | | | ✔ | | |
| `'Argon2id'`[^modern-algos] | | | | | ✔ | | |
| `'ChaCha20-Poly1305'`[^modern-algos] | | | ✔ | | ✔ | | |
| `'ECDH'` | ✔ | ✔ | ✔ | ✔ | | ✔ | |
| `'ECDSA'` | ✔ | ✔ | ✔ | ✔ | | ✔ | |
Expand Down Expand Up @@ -1666,6 +1696,90 @@ added: v15.0.0
* Type: {string} Must be one of `'AES-CBC'`, `'AES-CTR'`, `'AES-GCM'`, or
`'AES-KW'`

### Class: `Argon2Params`

<!-- YAML
added: REPLACEME
-->

#### `argon2Params.associatedData`

<!-- YAML
added: REPLACEME
-->

* Type: {ArrayBuffer|TypedArray|DataView|Buffer}

Represents the optional associated data.

#### `argon2Params.memory`

<!-- YAML
added: REPLACEME
-->

* Type: {number}

Represents the memory size in kibibytes. It must be at least 8 times the degree of parallelism.

#### `argon2Params.name`

<!-- YAML
added: REPLACEME
-->

* Type: {string} Must be one of `'Argon2d'`, `'Argon2i'`, or `'Argon2id'`.

#### `argon2Params.nonce`

<!-- YAML
added: REPLACEME
-->

* Type: {ArrayBuffer|TypedArray|DataView|Buffer}

Represents the nonce, which is a salt for password hashing applications.

#### `argon2Params.parallelism`

<!-- YAML
added: REPLACEME
-->

* Type: {number}

Represents the degree of parallelism.

#### `argon2Params.passes`

<!-- YAML
added: REPLACEME
-->

* Type: {number}

Represents the number of passes.

#### `argon2Params.secretValue`

<!-- YAML
added: REPLACEME
-->

* Type: {ArrayBuffer|TypedArray|DataView|Buffer}

Represents the optional secret value.

#### `argon2Params.version`

<!-- YAML
added: REPLACEME
-->

* Type: {number}

Represents the Argon2 version number. The default and currently only defined version is `19` (`0x13`).

### Class: `ContextParams`

<!-- YAML
Expand Down Expand Up @@ -2420,6 +2534,8 @@ The length (in bytes) of the random salt to use.

[^openssl30]: Requires OpenSSL >= 3.0

[^openssl32]: Requires OpenSSL >= 3.2

[^openssl35]: Requires OpenSSL >= 3.5

[JSON Web Key]: https://tools.ietf.org/html/rfc7517
Expand Down
59 changes: 58 additions & 1 deletion lib/internal/crypto/argon2.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const {
FunctionPrototypeCall,
MathPow,
StringPrototypeToLowerCase,
Uint8Array,
} = primordials;

Expand All @@ -17,7 +18,16 @@ const {
kTypeArgon2id,
} = internalBinding('crypto');

const { getArrayBufferOrView } = require('internal/crypto/util');
const {
lazyDOMException,
promisify,
} = require('internal/util');

const {
getArrayBufferOrView,
kKeyObject,
} = require('internal/crypto/util');

const {
validateString,
validateFunction,
Expand Down Expand Up @@ -179,7 +189,54 @@ function check(algorithm, parameters) {
return { message, nonce, secret, associatedData, tagLength, passes, parallelism, memory, type };
}

const argon2Promise = promisify(argon2);
function validateArgon2DeriveBitsLength(length) {
if (length === null)
throw lazyDOMException('length cannot be null', 'OperationError');

if (length % 8) {
throw lazyDOMException(
'length must be a multiple of 8',
'OperationError');
}

if (length < 32) {
throw lazyDOMException(
'length must be >= 32',
'OperationError');
}
}

async function argon2DeriveBits(algorithm, baseKey, length) {
validateArgon2DeriveBitsLength(length);

let result;
try {
result = await argon2Promise(
StringPrototypeToLowerCase(algorithm.name),
{
message: baseKey[kKeyObject].export(),
nonce: algorithm.nonce,
parallelism: algorithm.parallelism,
tagLength: length / 8,
memory: algorithm.memory,
passes: algorithm.passes,
secret: algorithm.secretValue,
associatedData: algorithm.associatedData,
},
);
} catch (err) {
throw lazyDOMException(
'The operation failed for an operation-specific reason',
{ name: 'OperationError', cause: err });
}

return result.buffer;
}

module.exports = {
argon2,
argon2Sync,
argon2DeriveBits,
validateArgon2DeriveBitsLength,
};
7 changes: 7 additions & 0 deletions lib/internal/crypto/keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,12 @@ const {
case 'HKDF':
// Fall through
case 'PBKDF2':
// Fall through
case 'Argon2d':
// Fall through
case 'Argon2i':
// Fall through
case 'Argon2id':
result = importGenericSecretKey(
algorithm,
'KeyObject',
Expand Down Expand Up @@ -998,6 +1004,7 @@ function importGenericSecretKey(
keyObject = keyData;
break;
}
case 'raw-secret':
case 'raw': {
keyObject = createSecretKey(keyData);
break;
Expand Down
Loading
Loading