GeezerVison is showing github.com — crypto: add JWK support for ML-KEM and SLH-DSA key types · nodejs/node@aeea8f4
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: benchmark/crypto/kem.js -3Lines changed: 0 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -54,9 +54,6 @@ const bench = common.createBenchmark(main, { | 54 | 54 | // assess whether mutexes over the key material impact the operation | 55 | 55 | if (p.keyFormat === 'keyObject.unique') | 56 | 56 | return p.mode === 'async-parallel'; | 57 | | - // JWK is not supported for ml-kem for now | 58 | | - if (p.keyFormat === 'jwk') | 59 | | - return !p.keyType.startsWith('ml-'); | 60 | 57 | // raw-public is only supported for encapsulate, not rsa | 61 | 58 | if (p.keyFormat === 'raw-public') | 62 | 59 | return p.keyType !== 'rsa' && p.op === 'encapsulate'; | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/crypto.md +27-15Lines changed: 27 additions & 15 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -86,23 +86,23 @@ The following table lists the asymmetric key types recognized by the | 86 | 86 | | `'ml-dsa-44'`[^openssl35] | ML-DSA-44 | 2.16.840.1.101.3.4.3.17 | ✔ | ✔ | ✔ | ✔ | | ✔ | | 87 | 87 | | `'ml-dsa-65'`[^openssl35] | ML-DSA-65 | 2.16.840.1.101.3.4.3.18 | ✔ | ✔ | ✔ | ✔ | | ✔ | | 88 | 88 | | `'ml-dsa-87'`[^openssl35] | ML-DSA-87 | 2.16.840.1.101.3.4.3.19 | ✔ | ✔ | ✔ | ✔ | | ✔ | | 89 | | -| `'ml-kem-512'`[^openssl35] | ML-KEM-512 | 2.16.840.1.101.3.4.4.1 | ✔ | ✔ | | ✔ | | ✔ | | 90 | | -| `'ml-kem-768'`[^openssl35] | ML-KEM-768 | 2.16.840.1.101.3.4.4.2 | ✔ | ✔ | | ✔ | | ✔ | | 91 | | -| `'ml-kem-1024'`[^openssl35] | ML-KEM-1024 | 2.16.840.1.101.3.4.4.3 | ✔ | ✔ | | ✔ | | ✔ | | | 89 | +| `'ml-kem-512'`[^openssl35] | ML-KEM-512 | 2.16.840.1.101.3.4.4.1 | ✔ | ✔ | ✔ | ✔ | | ✔ | | | 90 | +| `'ml-kem-768'`[^openssl35] | ML-KEM-768 | 2.16.840.1.101.3.4.4.2 | ✔ | ✔ | ✔ | ✔ | | ✔ | | | 91 | +| `'ml-kem-1024'`[^openssl35] | ML-KEM-1024 | 2.16.840.1.101.3.4.4.3 | ✔ | ✔ | ✔ | ✔ | | ✔ | | 92 | 92 | | `'rsa-pss'` | RSA PSS | 1.2.840.113549.1.1.10 | ✔ | ✔ | | | | | | 93 | 93 | | `'rsa'` | RSA | 1.2.840.113549.1.1.1 | ✔ | ✔ | ✔ | | | | | 94 | | -| `'slh-dsa-sha2-128f'`[^openssl35] | SLH-DSA-SHA2-128f | 2.16.840.1.101.3.4.3.21 | ✔ | ✔ | | ✔ | ✔ | | | 95 | | -| `'slh-dsa-sha2-128s'`[^openssl35] | SLH-DSA-SHA2-128s | 2.16.840.1.101.3.4.3.20 | ✔ | ✔ | | ✔ | ✔ | | | 96 | | -| `'slh-dsa-sha2-192f'`[^openssl35] | SLH-DSA-SHA2-192f | 2.16.840.1.101.3.4.3.23 | ✔ | ✔ | | ✔ | ✔ | | | 97 | | -| `'slh-dsa-sha2-192s'`[^openssl35] | SLH-DSA-SHA2-192s | 2.16.840.1.101.3.4.3.22 | ✔ | ✔ | | ✔ | ✔ | | | 98 | | -| `'slh-dsa-sha2-256f'`[^openssl35] | SLH-DSA-SHA2-256f | 2.16.840.1.101.3.4.3.25 | ✔ | ✔ | | ✔ | ✔ | | | 99 | | -| `'slh-dsa-sha2-256s'`[^openssl35] | SLH-DSA-SHA2-256s | 2.16.840.1.101.3.4.3.24 | ✔ | ✔ | | ✔ | ✔ | | | 100 | | -| `'slh-dsa-shake-128f'`[^openssl35] | SLH-DSA-SHAKE-128f | 2.16.840.1.101.3.4.3.27 | ✔ | ✔ | | ✔ | ✔ | | | 101 | | -| `'slh-dsa-shake-128s'`[^openssl35] | SLH-DSA-SHAKE-128s | 2.16.840.1.101.3.4.3.26 | ✔ | ✔ | | ✔ | ✔ | | | 102 | | -| `'slh-dsa-shake-192f'`[^openssl35] | SLH-DSA-SHAKE-192f | 2.16.840.1.101.3.4.3.29 | ✔ | ✔ | | ✔ | ✔ | | | 103 | | -| `'slh-dsa-shake-192s'`[^openssl35] | SLH-DSA-SHAKE-192s | 2.16.840.1.101.3.4.3.28 | ✔ | ✔ | | ✔ | ✔ | | | 104 | | -| `'slh-dsa-shake-256f'`[^openssl35] | SLH-DSA-SHAKE-256f | 2.16.840.1.101.3.4.3.31 | ✔ | ✔ | | ✔ | ✔ | | | 105 | | -| `'slh-dsa-shake-256s'`[^openssl35] | SLH-DSA-SHAKE-256s | 2.16.840.1.101.3.4.3.30 | ✔ | ✔ | | ✔ | ✔ | | | | 94 | +| `'slh-dsa-sha2-128f'`[^openssl35] | SLH-DSA-SHA2-128f | 2.16.840.1.101.3.4.3.21 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 95 | +| `'slh-dsa-sha2-128s'`[^openssl35] | SLH-DSA-SHA2-128s | 2.16.840.1.101.3.4.3.20 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 96 | +| `'slh-dsa-sha2-192f'`[^openssl35] | SLH-DSA-SHA2-192f | 2.16.840.1.101.3.4.3.23 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 97 | +| `'slh-dsa-sha2-192s'`[^openssl35] | SLH-DSA-SHA2-192s | 2.16.840.1.101.3.4.3.22 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 98 | +| `'slh-dsa-sha2-256f'`[^openssl35] | SLH-DSA-SHA2-256f | 2.16.840.1.101.3.4.3.25 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 99 | +| `'slh-dsa-sha2-256s'`[^openssl35] | SLH-DSA-SHA2-256s | 2.16.840.1.101.3.4.3.24 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 100 | +| `'slh-dsa-shake-128f'`[^openssl35] | SLH-DSA-SHAKE-128f | 2.16.840.1.101.3.4.3.27 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 101 | +| `'slh-dsa-shake-128s'`[^openssl35] | SLH-DSA-SHAKE-128s | 2.16.840.1.101.3.4.3.26 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 102 | +| `'slh-dsa-shake-192f'`[^openssl35] | SLH-DSA-SHAKE-192f | 2.16.840.1.101.3.4.3.29 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 103 | +| `'slh-dsa-shake-192s'`[^openssl35] | SLH-DSA-SHAKE-192s | 2.16.840.1.101.3.4.3.28 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 104 | +| `'slh-dsa-shake-256f'`[^openssl35] | SLH-DSA-SHAKE-256f | 2.16.840.1.101.3.4.3.31 | ✔ | ✔ | ✔ | ✔ | ✔ | | | | 105 | +| `'slh-dsa-shake-256s'`[^openssl35] | SLH-DSA-SHAKE-256s | 2.16.840.1.101.3.4.3.30 | ✔ | ✔ | ✔ | ✔ | ✔ | | | 106 | 106 | | `'x25519'` | X25519 | 1.3.101.110 | ✔ | ✔ | ✔ | ✔ | ✔ | | | 107 | 107 | | `'x448'` | X448 | 1.3.101.111 | ✔ | ✔ | ✔ | ✔ | ✔ | | | 108 | 108 |
| @@ -2393,6 +2393,10 @@ type, value, and parameters. This method is not | 2393 | 2393 | <!-- YAML | 2394 | 2394 | added: v11.6.0 | 2395 | 2395 | changes: | | 2396 | + - version: REPLACEME | | 2397 | + pr-url: https://github.com/nodejs/node/pull/62706 | | 2398 | + description: Added JWK format support for ML-KEM and SLH-DSA | | 2399 | + key types. | 2396 | 2400 | - version: v24.15.0 | 2397 | 2401 | pr-url: https://github.com/nodejs/node/pull/62240 | 2398 | 2402 | description: Added support for `'raw-public'`, `'raw-private'`, | @@ -3913,6 +3917,10 @@ input.on('readable', () => { | 3913 | 3917 | <!-- YAML | 3914 | 3918 | added: v11.6.0 | 3915 | 3919 | changes: | | 3920 | + - version: REPLACEME | | 3921 | + pr-url: https://github.com/nodejs/node/pull/62706 | | 3922 | + description: Added JWK format support for ML-KEM and SLH-DSA | | 3923 | + key types. | 3916 | 3924 | - version: v24.15.0 | 3917 | 3925 | pr-url: https://github.com/nodejs/node/pull/62240 | 3918 | 3926 | description: Added support for `'raw-private'` and `'raw-seed'` | @@ -3961,6 +3969,10 @@ of the passphrase is limited to 1024 bytes. | 3961 | 3969 | <!-- YAML | 3962 | 3970 | added: v11.6.0 | 3963 | 3971 | changes: | | 3972 | + - version: REPLACEME | | 3973 | + pr-url: https://github.com/nodejs/node/pull/62706 | | 3974 | + description: Added JWK format support for ML-KEM and SLH-DSA | | 3975 | + key types. | 3964 | 3976 | - version: v24.15.0 | 3965 | 3977 | pr-url: https://github.com/nodejs/node/pull/62240 | 3966 | 3978 | description: Added support for `'raw-public'` format. | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/webcrypto.md +12-6Lines changed: 12 additions & 6 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -1131,6 +1131,9 @@ The algorithms currently supported include: | 1131 | 1131 | <!-- YAML | 1132 | 1132 | added: v15.0.0 | 1133 | 1133 | changes: | | 1134 | + - version: REPLACEME | | 1135 | + pr-url: https://github.com/nodejs/node/pull/62706 | | 1136 | + description: Added JWK format support for ML-KEM key types. | 1134 | 1137 | - version: v24.8.0 | 1135 | 1138 | pr-url: https://github.com/nodejs/node/pull/59647 | 1136 | 1139 | description: KMAC algorithms are now supported. | @@ -1189,9 +1192,9 @@ specification. | 1189 | 1192 | | `'ML-DSA-44'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | 1190 | 1193 | | `'ML-DSA-65'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | 1191 | 1194 | | `'ML-DSA-87'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | 1192 | | -| `'ML-KEM-512'`[^modern-algos] | ✔ | ✔ | | | | ✔ | ✔ | | 1193 | | -| `'ML-KEM-768'`[^modern-algos] | ✔ | ✔ | | | | ✔ | ✔ | | 1194 | | -| `'ML-KEM-1024'`[^modern-algos] | ✔ | ✔ | | | | ✔ | ✔ | | | 1195 | +| `'ML-KEM-512'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | | 1196 | +| `'ML-KEM-768'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | | 1197 | +| `'ML-KEM-1024'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | 1195 | 1198 | | `'RSA-OAEP'` | ✔ | ✔ | ✔ | | | | | | 1196 | 1199 | | `'RSA-PSS'` | ✔ | ✔ | ✔ | | | | | | 1197 | 1200 | | `'RSASSA-PKCS1-v1_5'` | ✔ | ✔ | ✔ | | | | | | @@ -1279,6 +1282,9 @@ The {CryptoKey} (secret key) generating algorithms supported include: | 1279 | 1282 | <!-- YAML | 1280 | 1283 | added: v15.0.0 | 1281 | 1284 | changes: | | 1285 | + - version: REPLACEME | | 1286 | + pr-url: https://github.com/nodejs/node/pull/62706 | | 1287 | + description: Added JWK format support for ML-KEM key types. | 1282 | 1288 | - version: v24.15.0 | 1283 | 1289 | pr-url: https://github.com/nodejs/node/pull/62218 | 1284 | 1290 | description: Importing ML-DSA and ML-KEM PKCS#8 keys | @@ -1352,9 +1358,9 @@ The algorithms currently supported include: | 1352 | 1358 | | `'ML-DSA-44'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | 1353 | 1359 | | `'ML-DSA-65'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | 1354 | 1360 | | `'ML-DSA-87'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | 1355 | | -| `'ML-KEM-512'`[^modern-algos] | ✔ | ✔ | | | | ✔ | ✔ | | 1356 | | -| `'ML-KEM-768'`[^modern-algos] | ✔ | ✔ | | | | ✔ | ✔ | | 1357 | | -| `'ML-KEM-1024'`[^modern-algos] | ✔ | ✔ | | | | ✔ | ✔ | | | 1361 | +| `'ML-KEM-512'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | | 1362 | +| `'ML-KEM-768'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | | 1363 | +| `'ML-KEM-1024'`[^modern-algos] | ✔ | ✔ | ✔ | | | ✔ | ✔ | | 1358 | 1364 | | `'PBKDF2'` | | | | ✔ | ✔ | | | | 1359 | 1365 | | `'RSA-OAEP'` | ✔ | ✔ | ✔ | | | | | | 1360 | 1366 | | `'RSA-PSS'` | ✔ | ✔ | ✔ | | | | | | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/keys.js +5-6Lines changed: 5 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -628,7 +628,6 @@ function getKeyTypes(allowKeyObject, bufferOnly = false) { | 628 | 628 | return types; | 629 | 629 | } | 630 | 630 |
| 631 | | - | 632 | 631 | function prepareAsymmetricKey(key, ctx, name = 'key') { | 633 | 632 | if (isKeyObject(key)) { | 634 | 633 | // Best case: A key object, as simple as that. | @@ -661,17 +660,17 @@ function prepareAsymmetricKey(key, ctx, name = 'key') { | 661 | 660 | format === 'raw-seed') { | 662 | 661 | if (!isArrayBufferView(data) && !isAnyArrayBuffer(data)) { | 663 | 662 | throw new ERR_INVALID_ARG_TYPE( | 664 | | - 'key.key', | | 663 | + `${name}.key`, | 665 | 664 | ['ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'], | 666 | 665 | data); | 667 | 666 | } | 668 | | - validateString(key.asymmetricKeyType, 'key.asymmetricKeyType'); | | 667 | + validateString(key.asymmetricKeyType, `${name}.asymmetricKeyType`); | 669 | 668 | if (key.asymmetricKeyType === 'ec') { | 670 | | - validateString(key.namedCurve, 'key.namedCurve'); | | 669 | + validateString(key.namedCurve, `${name}.namedCurve`); | 671 | 670 | } | 672 | | - const rawFormat = parseKeyFormat(format, undefined, 'options.format'); | | 671 | + const rawFormat = parseKeyFormat(format, undefined, `${name}.format`); | 673 | 672 | return { | 674 | | - data: getArrayBufferOrView(data, 'key.key'), | | 673 | + data: getArrayBufferOrView(data, `${name}.key`), | 675 | 674 | format: rawFormat, | 676 | 675 | type: key.asymmetricKeyType, | 677 | 676 | namedCurve: key.namedCurve ?? null, | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/ml_kem.js +14Lines changed: 14 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -45,7 +45,9 @@ const { | 45 | 45 |
| 46 | 46 | const { | 47 | 47 | importDerKey, | | 48 | + importJwkKey, | 48 | 49 | importRawKey, | | 50 | + validateJwk, | 49 | 51 | } = require('internal/crypto/webcrypto_util'); | 50 | 52 |
| 51 | 53 | const generateKeyPair = promisify(_generateKeyPair); | @@ -184,6 +186,18 @@ function mlKemImportKey( | 184 | 186 | keyObject = importRawKey(isPublic, keyData, isPublic ? kKeyFormatRawPublic : kKeyFormatRawPrivate, name); | 185 | 187 | break; | 186 | 188 | } | | 189 | + case 'jwk': { | | 190 | + validateJwk(keyData, 'AKP', extractable, usagesSet, 'enc'); | | 191 | + | | 192 | + if (keyData.alg !== name) | | 193 | + throw lazyDOMException( | | 194 | + 'JWK "alg" Parameter and algorithm name mismatch', 'DataError'); | | 195 | + | | 196 | + const isPublic = keyData.priv === undefined; | | 197 | + verifyAcceptableMlKemKeyUse(name, isPublic, usagesSet); | | 198 | + keyObject = importJwkKey(isPublic, keyData); | | 199 | + break; | | 200 | + } | 187 | 201 | default: | 188 | 202 | return undefined; | 189 | 203 | } | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/webcrypto.js +6Lines changed: 6 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -611,6 +611,12 @@ async function exportKeyJWK(key) { | 611 | 611 | case 'ML-DSA-65': | 612 | 612 | // Fall through | 613 | 613 | case 'ML-DSA-87': | | 614 | + // Fall through | | 615 | + case 'ML-KEM-512': | | 616 | + // Fall through | | 617 | + case 'ML-KEM-768': | | 618 | + // Fall through | | 619 | + case 'ML-KEM-1024': | 614 | 620 | break; | 615 | 621 | case 'Ed25519': | 616 | 622 | // Fall through | |
Collapse file Copy file name to clipboardExpand all lines: node.gyp +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 384 | 384 | 'src/crypto/crypto_cipher.cc', | 385 | 385 | 'src/crypto/crypto_context.cc', | 386 | 386 | 'src/crypto/crypto_ec.cc', | 387 | | - 'src/crypto/crypto_ml_dsa.cc', | | 387 | + 'src/crypto/crypto_pqc.cc', | 388 | 388 | 'src/crypto/crypto_kem.cc', | 389 | 389 | 'src/crypto/crypto_hmac.cc', | 390 | 390 | 'src/crypto/crypto_kmac.cc', | | 422 | 422 | 'src/crypto/crypto_clienthello.h', | 423 | 423 | 'src/crypto/crypto_context.h', | 424 | 424 | 'src/crypto/crypto_ec.h', | 425 | | - 'src/crypto/crypto_ml_dsa.h', | | 425 | + 'src/crypto/crypto_pqc.h', | 426 | 426 | 'src/crypto/crypto_hkdf.h', | 427 | 427 | 'src/crypto/crypto_pbkdf2.h', | 428 | 428 | 'src/crypto/crypto_sig.h', | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_keys.cc +33-3Lines changed: 33 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 5 | 5 | #include "crypto/crypto_dh.h" | 6 | 6 | #include "crypto/crypto_dsa.h" | 7 | 7 | #include "crypto/crypto_ec.h" | 8 | | -#include "crypto/crypto_ml_dsa.h" | | 8 | +#include "crypto/crypto_pqc.h" | 9 | 9 | #include "crypto/crypto_rsa.h" | 10 | 10 | #include "crypto/crypto_util.h" | 11 | 11 | #include "env-inl.h" | @@ -201,7 +201,37 @@ bool ExportJWKAsymmetricKey(Environment* env, | 201 | 201 | case EVP_PKEY_ML_DSA_65: | 202 | 202 | // Fall through | 203 | 203 | case EVP_PKEY_ML_DSA_87: | 204 | | - return ExportJwkMlDsaKey(env, key, target); | | 204 | + // Fall through | | 205 | + case EVP_PKEY_SLH_DSA_SHA2_128F: | | 206 | + // Fall through | | 207 | + case EVP_PKEY_SLH_DSA_SHA2_128S: | | 208 | + // Fall through | | 209 | + case EVP_PKEY_SLH_DSA_SHA2_192F: | | 210 | + // Fall through | | 211 | + case EVP_PKEY_SLH_DSA_SHA2_192S: | | 212 | + // Fall through | | 213 | + case EVP_PKEY_SLH_DSA_SHA2_256F: | | 214 | + // Fall through | | 215 | + case EVP_PKEY_SLH_DSA_SHA2_256S: | | 216 | + // Fall through | | 217 | + case EVP_PKEY_SLH_DSA_SHAKE_128F: | | 218 | + // Fall through | | 219 | + case EVP_PKEY_SLH_DSA_SHAKE_128S: | | 220 | + // Fall through | | 221 | + case EVP_PKEY_SLH_DSA_SHAKE_192F: | | 222 | + // Fall through | | 223 | + case EVP_PKEY_SLH_DSA_SHAKE_192S: | | 224 | + // Fall through | | 225 | + case EVP_PKEY_SLH_DSA_SHAKE_256F: | | 226 | + // Fall through | | 227 | + case EVP_PKEY_SLH_DSA_SHAKE_256S: | | 228 | + // Fall through | | 229 | + case EVP_PKEY_ML_KEM_512: | | 230 | + // Fall through | | 231 | + case EVP_PKEY_ML_KEM_768: | | 232 | + // Fall through | | 233 | + case EVP_PKEY_ML_KEM_1024: | | 234 | + return ExportJwkPqcKey(env, key, target); | 205 | 235 | #endif | 206 | 236 | } | 207 | 237 | THROW_ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE(env); | @@ -724,7 +754,7 @@ static KeyObjectData ImportJWKFromArgs(Environment* env, Local<Object> jwk) { | 724 | 754 | return ImportJWKEdKey(env, jwk); | 725 | 755 | } else if (*kty_string == std::string_view("AKP")) { | 726 | 756 | #if OPENSSL_WITH_PQC | 727 | | - return ImportJWKAkpKey(env, jwk); | | 757 | + return ImportJWKPqcKey(env, jwk); | 728 | 758 | #else | 729 | 759 | THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported key type"); | 730 | 760 | return {}; | |
|