react-native-quick-crypto 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/CMakeLists.txt +16 -0
- package/cpp/argon2/HybridArgon2.cpp +103 -0
- package/cpp/argon2/HybridArgon2.hpp +32 -0
- package/cpp/certificate/HybridCertificate.cpp +42 -0
- package/cpp/certificate/HybridCertificate.hpp +16 -0
- package/cpp/cipher/CCMCipher.cpp +4 -1
- package/cpp/cipher/ChaCha20Cipher.cpp +3 -1
- package/cpp/cipher/ChaCha20Poly1305Cipher.cpp +5 -5
- package/cpp/cipher/ChaCha20Poly1305Cipher.hpp +1 -2
- package/cpp/cipher/HybridCipher.cpp +68 -1
- package/cpp/cipher/HybridCipher.hpp +6 -0
- package/cpp/cipher/HybridRsaCipher.cpp +0 -13
- package/cpp/cipher/XChaCha20Poly1305Cipher.cpp +7 -5
- package/cpp/cipher/XChaCha20Poly1305Cipher.hpp +1 -2
- package/cpp/cipher/XSalsa20Cipher.cpp +4 -0
- package/cpp/cipher/XSalsa20Poly1305Cipher.cpp +7 -5
- package/cpp/cipher/XSalsa20Poly1305Cipher.hpp +1 -2
- package/cpp/dh/HybridDhKeyPair.cpp +179 -0
- package/cpp/dh/HybridDhKeyPair.hpp +37 -0
- package/cpp/dsa/HybridDsaKeyPair.cpp +128 -0
- package/cpp/dsa/HybridDsaKeyPair.hpp +32 -0
- package/cpp/ecdh/HybridECDH.cpp +42 -120
- package/cpp/ecdh/HybridECDH.hpp +1 -0
- package/cpp/keys/HybridKeyObjectHandle.cpp +150 -128
- package/cpp/keys/HybridKeyObjectHandle.hpp +6 -3
- package/cpp/keys/KeyObjectData.hpp +2 -0
- package/cpp/kmac/HybridKmac.cpp +83 -0
- package/cpp/kmac/HybridKmac.hpp +31 -0
- package/cpp/mldsa/HybridMlDsaKeyPair.cpp +11 -20
- package/cpp/mldsa/HybridMlDsaKeyPair.hpp +4 -2
- package/cpp/mlkem/HybridMlKemKeyPair.cpp +319 -0
- package/cpp/mlkem/HybridMlKemKeyPair.hpp +48 -0
- package/cpp/prime/HybridPrime.cpp +81 -0
- package/cpp/prime/HybridPrime.hpp +20 -0
- package/cpp/sign/SignUtils.hpp +9 -26
- package/cpp/utils/QuickCryptoUtils.cpp +44 -0
- package/cpp/utils/QuickCryptoUtils.hpp +39 -0
- package/cpp/x509/HybridX509Certificate.cpp +174 -0
- package/cpp/x509/HybridX509Certificate.hpp +51 -0
- package/lib/commonjs/argon2.js +39 -0
- package/lib/commonjs/argon2.js.map +1 -0
- package/lib/commonjs/certificate.js +35 -0
- package/lib/commonjs/certificate.js.map +1 -0
- package/lib/commonjs/cipher.js +23 -2
- package/lib/commonjs/cipher.js.map +1 -1
- package/lib/commonjs/dhKeyPair.js +109 -0
- package/lib/commonjs/dhKeyPair.js.map +1 -0
- package/lib/commonjs/dsa.js +92 -0
- package/lib/commonjs/dsa.js.map +1 -0
- package/lib/commonjs/ec.js +18 -18
- package/lib/commonjs/ec.js.map +1 -1
- package/lib/commonjs/ecdh.js +37 -0
- package/lib/commonjs/ecdh.js.map +1 -1
- package/lib/commonjs/ed.js +9 -9
- package/lib/commonjs/ed.js.map +1 -1
- package/lib/commonjs/hash.js +17 -12
- package/lib/commonjs/hash.js.map +1 -1
- package/lib/commonjs/hkdf.js.map +1 -1
- package/lib/commonjs/index.js +57 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/keys/classes.js +11 -9
- package/lib/commonjs/keys/classes.js.map +1 -1
- package/lib/commonjs/keys/generateKeyPair.js +11 -0
- package/lib/commonjs/keys/generateKeyPair.js.map +1 -1
- package/lib/commonjs/keys/index.js +24 -0
- package/lib/commonjs/keys/index.js.map +1 -1
- package/lib/commonjs/keys/signVerify.js +0 -2
- package/lib/commonjs/keys/signVerify.js.map +1 -1
- package/lib/commonjs/mlkem.js +219 -0
- package/lib/commonjs/mlkem.js.map +1 -0
- package/lib/commonjs/pbkdf2.js +18 -1
- package/lib/commonjs/pbkdf2.js.map +1 -1
- package/lib/commonjs/prime.js +84 -0
- package/lib/commonjs/prime.js.map +1 -0
- package/lib/commonjs/rsa.js +7 -7
- package/lib/commonjs/rsa.js.map +1 -1
- package/lib/commonjs/specs/argon2.nitro.js +6 -0
- package/lib/commonjs/specs/argon2.nitro.js.map +1 -0
- package/lib/commonjs/specs/certificate.nitro.js +6 -0
- package/lib/commonjs/specs/certificate.nitro.js.map +1 -0
- package/lib/commonjs/specs/dhKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/dhKeyPair.nitro.js.map +1 -0
- package/lib/commonjs/specs/dsaKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/dsaKeyPair.nitro.js.map +1 -0
- package/lib/commonjs/specs/kmac.nitro.js +6 -0
- package/lib/commonjs/specs/kmac.nitro.js.map +1 -0
- package/lib/commonjs/specs/mlKemKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/mlKemKeyPair.nitro.js.map +1 -0
- package/lib/commonjs/specs/prime.nitro.js +6 -0
- package/lib/commonjs/specs/prime.nitro.js.map +1 -0
- package/lib/commonjs/specs/x509certificate.nitro.js +6 -0
- package/lib/commonjs/specs/x509certificate.nitro.js.map +1 -0
- package/lib/commonjs/subtle.js +385 -114
- package/lib/commonjs/subtle.js.map +1 -1
- package/lib/commonjs/utils/conversion.js +3 -3
- package/lib/commonjs/utils/conversion.js.map +1 -1
- package/lib/commonjs/utils/hashnames.js +31 -0
- package/lib/commonjs/utils/hashnames.js.map +1 -1
- package/lib/commonjs/utils/types.js.map +1 -1
- package/lib/commonjs/x509certificate.js +189 -0
- package/lib/commonjs/x509certificate.js.map +1 -0
- package/lib/module/argon2.js +34 -0
- package/lib/module/argon2.js.map +1 -0
- package/lib/module/certificate.js +30 -0
- package/lib/module/certificate.js.map +1 -0
- package/lib/module/cipher.js +23 -3
- package/lib/module/cipher.js.map +1 -1
- package/lib/module/dhKeyPair.js +102 -0
- package/lib/module/dhKeyPair.js.map +1 -0
- package/lib/module/dsa.js +85 -0
- package/lib/module/dsa.js.map +1 -0
- package/lib/module/ec.js +6 -6
- package/lib/module/ec.js.map +1 -1
- package/lib/module/ecdh.js +37 -0
- package/lib/module/ecdh.js.map +1 -1
- package/lib/module/ed.js +1 -1
- package/lib/module/ed.js.map +1 -1
- package/lib/module/hash.js +17 -12
- package/lib/module/hash.js.map +1 -1
- package/lib/module/hkdf.js.map +1 -1
- package/lib/module/index.js +15 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/keys/classes.js +11 -9
- package/lib/module/keys/classes.js.map +1 -1
- package/lib/module/keys/generateKeyPair.js +11 -0
- package/lib/module/keys/generateKeyPair.js.map +1 -1
- package/lib/module/keys/index.js +25 -1
- package/lib/module/keys/index.js.map +1 -1
- package/lib/module/keys/signVerify.js +0 -2
- package/lib/module/keys/signVerify.js.map +1 -1
- package/lib/module/mlkem.js +211 -0
- package/lib/module/mlkem.js.map +1 -0
- package/lib/module/pbkdf2.js +18 -1
- package/lib/module/pbkdf2.js.map +1 -1
- package/lib/module/prime.js +77 -0
- package/lib/module/prime.js.map +1 -0
- package/lib/module/rsa.js +1 -1
- package/lib/module/rsa.js.map +1 -1
- package/lib/module/specs/argon2.nitro.js +4 -0
- package/lib/module/specs/argon2.nitro.js.map +1 -0
- package/lib/module/specs/certificate.nitro.js +4 -0
- package/lib/module/specs/certificate.nitro.js.map +1 -0
- package/lib/module/specs/dhKeyPair.nitro.js +4 -0
- package/lib/module/specs/dhKeyPair.nitro.js.map +1 -0
- package/lib/module/specs/dsaKeyPair.nitro.js +4 -0
- package/lib/module/specs/dsaKeyPair.nitro.js.map +1 -0
- package/lib/module/specs/kmac.nitro.js +4 -0
- package/lib/module/specs/kmac.nitro.js.map +1 -0
- package/lib/module/specs/mlKemKeyPair.nitro.js +4 -0
- package/lib/module/specs/mlKemKeyPair.nitro.js.map +1 -0
- package/lib/module/specs/prime.nitro.js +4 -0
- package/lib/module/specs/prime.nitro.js.map +1 -0
- package/lib/module/specs/x509certificate.nitro.js +4 -0
- package/lib/module/specs/x509certificate.nitro.js.map +1 -0
- package/lib/module/subtle.js +386 -116
- package/lib/module/subtle.js.map +1 -1
- package/lib/module/utils/conversion.js +3 -4
- package/lib/module/utils/conversion.js.map +1 -1
- package/lib/module/utils/hashnames.js +31 -0
- package/lib/module/utils/hashnames.js.map +1 -1
- package/lib/module/utils/types.js.map +1 -1
- package/lib/module/x509certificate.js +184 -0
- package/lib/module/x509certificate.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/typescript/argon2.d.ts +16 -0
- package/lib/typescript/argon2.d.ts.map +1 -0
- package/lib/typescript/certificate.d.ts +8 -0
- package/lib/typescript/certificate.d.ts.map +1 -0
- package/lib/typescript/cipher.d.ts +15 -0
- package/lib/typescript/cipher.d.ts.map +1 -1
- package/lib/typescript/dhKeyPair.d.ts +19 -0
- package/lib/typescript/dhKeyPair.d.ts.map +1 -0
- package/lib/typescript/dsa.d.ts +19 -0
- package/lib/typescript/dsa.d.ts.map +1 -0
- package/lib/typescript/ec.d.ts +1 -1
- package/lib/typescript/ec.d.ts.map +1 -1
- package/lib/typescript/ecdh.d.ts +3 -0
- package/lib/typescript/ecdh.d.ts.map +1 -1
- package/lib/typescript/ed.d.ts +1 -1
- package/lib/typescript/ed.d.ts.map +1 -1
- package/lib/typescript/hash.d.ts.map +1 -1
- package/lib/typescript/hkdf.d.ts +2 -6
- package/lib/typescript/hkdf.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +32 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/keys/classes.d.ts +7 -5
- package/lib/typescript/keys/classes.d.ts.map +1 -1
- package/lib/typescript/keys/generateKeyPair.d.ts.map +1 -1
- package/lib/typescript/keys/index.d.ts +2 -2
- package/lib/typescript/keys/index.d.ts.map +1 -1
- package/lib/typescript/keys/signVerify.d.ts.map +1 -1
- package/lib/typescript/mlkem.d.ts +30 -0
- package/lib/typescript/mlkem.d.ts.map +1 -0
- package/lib/typescript/pbkdf2.d.ts +2 -2
- package/lib/typescript/pbkdf2.d.ts.map +1 -1
- package/lib/typescript/prime.d.ts +19 -0
- package/lib/typescript/prime.d.ts.map +1 -0
- package/lib/typescript/rsa.d.ts +1 -1
- package/lib/typescript/rsa.d.ts.map +1 -1
- package/lib/typescript/specs/argon2.nitro.d.ts +9 -0
- package/lib/typescript/specs/argon2.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/certificate.nitro.d.ts +10 -0
- package/lib/typescript/specs/certificate.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/cipher.nitro.d.ts +9 -0
- package/lib/typescript/specs/cipher.nitro.d.ts.map +1 -1
- package/lib/typescript/specs/dhKeyPair.nitro.d.ts +14 -0
- package/lib/typescript/specs/dhKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/dsaKeyPair.nitro.d.ts +13 -0
- package/lib/typescript/specs/dsaKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/ecdh.nitro.d.ts +1 -0
- package/lib/typescript/specs/ecdh.nitro.d.ts.map +1 -1
- package/lib/typescript/specs/keyObjectHandle.nitro.d.ts +1 -0
- package/lib/typescript/specs/keyObjectHandle.nitro.d.ts.map +1 -1
- package/lib/typescript/specs/kmac.nitro.d.ts +10 -0
- package/lib/typescript/specs/kmac.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/mlKemKeyPair.nitro.d.ts +18 -0
- package/lib/typescript/specs/mlKemKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/prime.nitro.d.ts +11 -0
- package/lib/typescript/specs/prime.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/x509certificate.nitro.d.ts +34 -0
- package/lib/typescript/specs/x509certificate.nitro.d.ts.map +1 -0
- package/lib/typescript/subtle.d.ts +12 -0
- package/lib/typescript/subtle.d.ts.map +1 -1
- package/lib/typescript/utils/conversion.d.ts.map +1 -1
- package/lib/typescript/utils/hashnames.d.ts +1 -1
- package/lib/typescript/utils/hashnames.d.ts.map +1 -1
- package/lib/typescript/utils/types.d.ts +25 -9
- package/lib/typescript/utils/types.d.ts.map +1 -1
- package/lib/typescript/x509certificate.d.ts +64 -0
- package/lib/typescript/x509certificate.d.ts.map +1 -0
- package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +8 -0
- package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +80 -0
- package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +80 -0
- package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +12 -0
- package/nitrogen/generated/shared/c++/CipherInfo.hpp +104 -0
- package/nitrogen/generated/shared/c++/HybridArgon2Spec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridArgon2Spec.hpp +66 -0
- package/nitrogen/generated/shared/c++/HybridCertificateSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridCertificateSpec.hpp +64 -0
- package/nitrogen/generated/shared/c++/HybridCipherSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridCipherSpec.hpp +4 -0
- package/nitrogen/generated/shared/c++/HybridDhKeyPairSpec.cpp +27 -0
- package/nitrogen/generated/shared/c++/HybridDhKeyPairSpec.hpp +69 -0
- package/nitrogen/generated/shared/c++/HybridDsaKeyPairSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridDsaKeyPairSpec.hpp +68 -0
- package/nitrogen/generated/shared/c++/HybridECDHSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridECDHSpec.hpp +1 -0
- package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +1 -0
- package/nitrogen/generated/shared/c++/HybridKmacSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridKmacSpec.hpp +66 -0
- package/nitrogen/generated/shared/c++/HybridMlKemKeyPairSpec.cpp +31 -0
- package/nitrogen/generated/shared/c++/HybridMlKemKeyPairSpec.hpp +74 -0
- package/nitrogen/generated/shared/c++/HybridPrimeSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridPrimeSpec.hpp +67 -0
- package/nitrogen/generated/shared/c++/HybridX509CertificateHandleSpec.cpp +46 -0
- package/nitrogen/generated/shared/c++/HybridX509CertificateHandleSpec.hpp +96 -0
- package/package.json +4 -1
- package/src/argon2.ts +83 -0
- package/src/certificate.ts +41 -0
- package/src/cipher.ts +41 -3
- package/src/dhKeyPair.ts +156 -0
- package/src/dsa.ts +129 -0
- package/src/ec.ts +9 -9
- package/src/ecdh.ts +59 -0
- package/src/ed.ts +2 -2
- package/src/hash.ts +34 -11
- package/src/hkdf.ts +2 -7
- package/src/index.ts +16 -0
- package/src/keys/classes.ts +26 -14
- package/src/keys/generateKeyPair.ts +14 -0
- package/src/keys/index.ts +37 -2
- package/src/keys/signVerify.ts +0 -5
- package/src/mlkem.ts +350 -0
- package/src/pbkdf2.ts +34 -5
- package/src/prime.ts +134 -0
- package/src/rsa.ts +1 -1
- package/src/specs/argon2.nitro.ts +29 -0
- package/src/specs/certificate.nitro.ts +8 -0
- package/src/specs/cipher.nitro.ts +14 -0
- package/src/specs/dhKeyPair.nitro.ts +14 -0
- package/src/specs/dsaKeyPair.nitro.ts +13 -0
- package/src/specs/ecdh.nitro.ts +1 -0
- package/src/specs/keyObjectHandle.nitro.ts +5 -0
- package/src/specs/kmac.nitro.ts +12 -0
- package/src/specs/mlKemKeyPair.nitro.ts +32 -0
- package/src/specs/prime.nitro.ts +18 -0
- package/src/specs/x509certificate.nitro.ts +38 -0
- package/src/subtle.ts +821 -136
- package/src/utils/conversion.ts +10 -4
- package/src/utils/hashnames.ts +33 -2
- package/src/utils/types.ts +64 -8
- package/src/x509certificate.ts +277 -0
package/src/subtle.ts
CHANGED
|
@@ -28,11 +28,12 @@ import {
|
|
|
28
28
|
} from './keys';
|
|
29
29
|
import type { CryptoKeyPair } from './utils/types';
|
|
30
30
|
import { bufferLikeToArrayBuffer } from './utils/conversion';
|
|
31
|
+
import { argon2Sync } from './argon2';
|
|
31
32
|
import { lazyDOMException } from './utils/errors';
|
|
32
33
|
import { normalizeHashName, HashContext } from './utils/hashnames';
|
|
33
34
|
import { validateMaxBufferLength } from './utils/validation';
|
|
34
35
|
import { asyncDigest } from './hash';
|
|
35
|
-
import { createSecretKey } from './keys';
|
|
36
|
+
import { createSecretKey, createPublicKey } from './keys';
|
|
36
37
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
37
38
|
import type { KeyObjectHandle } from './specs/keyObjectHandle.nitro';
|
|
38
39
|
import type { RsaCipher } from './specs/rsaCipher.nitro';
|
|
@@ -47,6 +48,8 @@ import {
|
|
|
47
48
|
import { rsa_generateKeyPair } from './rsa';
|
|
48
49
|
import { getRandomValues } from './random';
|
|
49
50
|
import { createHmac } from './hmac';
|
|
51
|
+
import type { Kmac } from './specs/kmac.nitro';
|
|
52
|
+
import { timingSafeEqual } from './utils/timingSafeEqual';
|
|
50
53
|
import { createSign, createVerify } from './keys/signVerify';
|
|
51
54
|
import {
|
|
52
55
|
ed_generateKeyPairWebCrypto,
|
|
@@ -55,13 +58,13 @@ import {
|
|
|
55
58
|
Ed,
|
|
56
59
|
} from './ed';
|
|
57
60
|
import { mldsa_generateKeyPairWebCrypto, type MlDsaVariant } from './mldsa';
|
|
61
|
+
import {
|
|
62
|
+
mlkem_generateKeyPairWebCrypto,
|
|
63
|
+
type MlKemVariant,
|
|
64
|
+
MlKem,
|
|
65
|
+
} from './mlkem';
|
|
66
|
+
import type { EncapsulateResult } from './utils';
|
|
58
67
|
import { hkdfDeriveBits, type HkdfAlgorithm } from './hkdf';
|
|
59
|
-
// import { pbkdf2DeriveBits } from './pbkdf2';
|
|
60
|
-
// import { aesCipher, aesGenerateKey, aesImportKey, getAlgorithmName } from './aes';
|
|
61
|
-
// import { rsaCipher, rsaExportKey, rsaImportKey, rsaKeyGenerate } from './rsa';
|
|
62
|
-
// import { normalizeAlgorithm, type Operation } from './algorithms';
|
|
63
|
-
// import { hmacImportKey } from './mac';
|
|
64
|
-
|
|
65
68
|
// Temporary enums that need to be defined
|
|
66
69
|
|
|
67
70
|
enum KWebCryptoKeyFormat {
|
|
@@ -113,12 +116,12 @@ function getAlgorithmName(name: string, length: number): string {
|
|
|
113
116
|
function ecExportKey(key: CryptoKey, format: KWebCryptoKeyFormat): ArrayBuffer {
|
|
114
117
|
const keyObject = key.keyObject;
|
|
115
118
|
|
|
116
|
-
if (format === KWebCryptoKeyFormat.
|
|
117
|
-
|
|
119
|
+
if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatRaw) {
|
|
120
|
+
return bufferLikeToArrayBuffer(keyObject.handle.exportKey());
|
|
121
|
+
} else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI) {
|
|
118
122
|
const exported = keyObject.export({ format: 'der', type: 'spki' });
|
|
119
123
|
return bufferLikeToArrayBuffer(exported);
|
|
120
124
|
} else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatPKCS8) {
|
|
121
|
-
// Export private key in PKCS8 format
|
|
122
125
|
const exported = keyObject.export({ format: 'der', type: 'pkcs8' });
|
|
123
126
|
return bufferLikeToArrayBuffer(exported);
|
|
124
127
|
} else {
|
|
@@ -704,6 +707,164 @@ async function hmacGenerateKey(
|
|
|
704
707
|
return new CryptoKey(keyObject, keyAlgorithm, keyUsages, extractable);
|
|
705
708
|
}
|
|
706
709
|
|
|
710
|
+
async function kmacGenerateKey(
|
|
711
|
+
algorithm: SubtleAlgorithm,
|
|
712
|
+
extractable: boolean,
|
|
713
|
+
keyUsages: KeyUsage[],
|
|
714
|
+
): Promise<CryptoKey> {
|
|
715
|
+
const { name } = algorithm;
|
|
716
|
+
|
|
717
|
+
if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
|
|
718
|
+
throw lazyDOMException(
|
|
719
|
+
`Unsupported key usage for ${name} key`,
|
|
720
|
+
'SyntaxError',
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
const defaultLength = name === 'KMAC128' ? 128 : 256;
|
|
725
|
+
const length = algorithm.length ?? defaultLength;
|
|
726
|
+
|
|
727
|
+
if (length === 0) {
|
|
728
|
+
throw lazyDOMException(
|
|
729
|
+
'Zero-length key is not supported',
|
|
730
|
+
'OperationError',
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
const keyBytes = new Uint8Array(Math.ceil(length / 8));
|
|
735
|
+
getRandomValues(keyBytes);
|
|
736
|
+
|
|
737
|
+
const keyObject = createSecretKey(keyBytes);
|
|
738
|
+
|
|
739
|
+
const keyAlgorithm: SubtleAlgorithm = { name: name as AnyAlgorithm, length };
|
|
740
|
+
|
|
741
|
+
return new CryptoKey(keyObject, keyAlgorithm, keyUsages, extractable);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function kmacSignVerify(
|
|
745
|
+
key: CryptoKey,
|
|
746
|
+
data: BufferLike,
|
|
747
|
+
algorithm: SubtleAlgorithm,
|
|
748
|
+
signature?: BufferLike,
|
|
749
|
+
): ArrayBuffer | boolean {
|
|
750
|
+
const { name } = algorithm;
|
|
751
|
+
|
|
752
|
+
const defaultLength = name === 'KMAC128' ? 256 : 512;
|
|
753
|
+
const outputLengthBits = algorithm.length ?? defaultLength;
|
|
754
|
+
|
|
755
|
+
if (outputLengthBits % 8 !== 0) {
|
|
756
|
+
throw lazyDOMException(
|
|
757
|
+
'KMAC output length must be a multiple of 8',
|
|
758
|
+
'OperationError',
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
const outputLengthBytes = outputLengthBits / 8;
|
|
763
|
+
|
|
764
|
+
const keyData = key.keyObject.export();
|
|
765
|
+
|
|
766
|
+
const kmac = NitroModules.createHybridObject<Kmac>('Kmac');
|
|
767
|
+
|
|
768
|
+
let customizationBuffer: ArrayBuffer | undefined;
|
|
769
|
+
if (algorithm.customization !== undefined) {
|
|
770
|
+
customizationBuffer = bufferLikeToArrayBuffer(algorithm.customization);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
kmac.createKmac(
|
|
774
|
+
name,
|
|
775
|
+
bufferLikeToArrayBuffer(keyData),
|
|
776
|
+
outputLengthBytes,
|
|
777
|
+
customizationBuffer,
|
|
778
|
+
);
|
|
779
|
+
kmac.update(bufferLikeToArrayBuffer(data));
|
|
780
|
+
const computed = kmac.digest();
|
|
781
|
+
|
|
782
|
+
if (signature === undefined) {
|
|
783
|
+
return computed;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
const sigBuffer = bufferLikeToArrayBuffer(signature);
|
|
787
|
+
if (computed.byteLength !== sigBuffer.byteLength) {
|
|
788
|
+
return false;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
return timingSafeEqual(new Uint8Array(computed), new Uint8Array(sigBuffer));
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
async function kmacImportKey(
|
|
795
|
+
algorithm: SubtleAlgorithm,
|
|
796
|
+
format: ImportFormat,
|
|
797
|
+
data: BufferLike | JWK,
|
|
798
|
+
extractable: boolean,
|
|
799
|
+
keyUsages: KeyUsage[],
|
|
800
|
+
): Promise<CryptoKey> {
|
|
801
|
+
const { name } = algorithm;
|
|
802
|
+
|
|
803
|
+
if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
|
|
804
|
+
throw lazyDOMException(
|
|
805
|
+
`Unsupported key usage for ${name} key`,
|
|
806
|
+
'SyntaxError',
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
let keyObject: KeyObject;
|
|
811
|
+
|
|
812
|
+
if (format === 'jwk') {
|
|
813
|
+
const jwk = data as JWK;
|
|
814
|
+
|
|
815
|
+
if (!jwk || typeof jwk !== 'object') {
|
|
816
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
if (jwk.kty !== 'oct') {
|
|
820
|
+
throw lazyDOMException('Invalid JWK format for KMAC key', 'DataError');
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const expectedAlg = name === 'KMAC128' ? 'K128' : 'K256';
|
|
824
|
+
if (jwk.alg !== undefined && jwk.alg !== expectedAlg) {
|
|
825
|
+
throw lazyDOMException(
|
|
826
|
+
'JWK "alg" does not match the requested algorithm',
|
|
827
|
+
'DataError',
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
const handle =
|
|
832
|
+
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
833
|
+
const keyType = handle.initJwk(jwk, undefined);
|
|
834
|
+
|
|
835
|
+
if (keyType === undefined || keyType !== 0) {
|
|
836
|
+
throw lazyDOMException('Failed to import KMAC JWK', 'DataError');
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
keyObject = new SecretKeyObject(handle);
|
|
840
|
+
} else if (format === 'raw' || format === 'raw-secret') {
|
|
841
|
+
keyObject = createSecretKey(data as BinaryLike);
|
|
842
|
+
} else {
|
|
843
|
+
throw lazyDOMException(
|
|
844
|
+
`Unable to import ${name} key with format ${format}`,
|
|
845
|
+
'NotSupportedError',
|
|
846
|
+
);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
const exported = keyObject.export();
|
|
850
|
+
const keyLength = exported.byteLength * 8;
|
|
851
|
+
|
|
852
|
+
if (keyLength === 0) {
|
|
853
|
+
throw lazyDOMException('Zero-length key is not supported', 'DataError');
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
if (algorithm.length !== undefined && algorithm.length !== keyLength) {
|
|
857
|
+
throw lazyDOMException('Invalid key length', 'DataError');
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
const keyAlgorithm: SubtleAlgorithm = {
|
|
861
|
+
name: name as AnyAlgorithm,
|
|
862
|
+
length: keyLength,
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
return new CryptoKey(keyObject, keyAlgorithm, keyUsages, extractable);
|
|
866
|
+
}
|
|
867
|
+
|
|
707
868
|
function rsaImportKey(
|
|
708
869
|
format: ImportFormat,
|
|
709
870
|
data: BufferLike | JWK,
|
|
@@ -1024,6 +1185,49 @@ function edImportKey(
|
|
|
1024
1185
|
return new CryptoKey(keyObject, { name }, keyUsages, extractable);
|
|
1025
1186
|
}
|
|
1026
1187
|
|
|
1188
|
+
function pqcImportKeyObject(
|
|
1189
|
+
format: ImportFormat,
|
|
1190
|
+
data: BufferLike,
|
|
1191
|
+
name: string,
|
|
1192
|
+
): KeyObject {
|
|
1193
|
+
if (format === 'spki') {
|
|
1194
|
+
return KeyObject.createKeyObject(
|
|
1195
|
+
'public',
|
|
1196
|
+
bufferLikeToArrayBuffer(data),
|
|
1197
|
+
KFormatType.DER,
|
|
1198
|
+
KeyEncoding.SPKI,
|
|
1199
|
+
);
|
|
1200
|
+
} else if (format === 'pkcs8') {
|
|
1201
|
+
return KeyObject.createKeyObject(
|
|
1202
|
+
'private',
|
|
1203
|
+
bufferLikeToArrayBuffer(data),
|
|
1204
|
+
KFormatType.DER,
|
|
1205
|
+
KeyEncoding.PKCS8,
|
|
1206
|
+
);
|
|
1207
|
+
} else if (format === 'raw') {
|
|
1208
|
+
const handle =
|
|
1209
|
+
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1210
|
+
if (!handle.initPqcRaw(name, bufferLikeToArrayBuffer(data), true)) {
|
|
1211
|
+
throw lazyDOMException(
|
|
1212
|
+
`Failed to import ${name} raw public key`,
|
|
1213
|
+
'DataError',
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
return new PublicKeyObject(handle);
|
|
1217
|
+
} else if (format === 'raw-seed') {
|
|
1218
|
+
const handle =
|
|
1219
|
+
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1220
|
+
if (!handle.initPqcRaw(name, bufferLikeToArrayBuffer(data), false)) {
|
|
1221
|
+
throw lazyDOMException(`Failed to import ${name} raw seed`, 'DataError');
|
|
1222
|
+
}
|
|
1223
|
+
return new PrivateKeyObject(handle);
|
|
1224
|
+
}
|
|
1225
|
+
throw lazyDOMException(
|
|
1226
|
+
`Unsupported format for ${name} import: ${format}`,
|
|
1227
|
+
'NotSupportedError',
|
|
1228
|
+
);
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1027
1231
|
function mldsaImportKey(
|
|
1028
1232
|
format: ImportFormat,
|
|
1029
1233
|
data: BufferLike,
|
|
@@ -1032,43 +1236,45 @@ function mldsaImportKey(
|
|
|
1032
1236
|
keyUsages: KeyUsage[],
|
|
1033
1237
|
): CryptoKey {
|
|
1034
1238
|
const { name } = algorithm;
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
|
|
1239
|
+
const isPublicFormat = format === 'spki' || format === 'raw';
|
|
1240
|
+
if (hasAnyNotIn(keyUsages, isPublicFormat ? ['verify'] : ['sign'])) {
|
|
1038
1241
|
throw lazyDOMException(
|
|
1039
1242
|
`Unsupported key usage for ${name} key`,
|
|
1040
1243
|
'SyntaxError',
|
|
1041
1244
|
);
|
|
1042
1245
|
}
|
|
1246
|
+
return new CryptoKey(
|
|
1247
|
+
pqcImportKeyObject(format, data, name),
|
|
1248
|
+
{ name },
|
|
1249
|
+
keyUsages,
|
|
1250
|
+
extractable,
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1043
1253
|
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
const keyData = bufferLikeToArrayBuffer(data);
|
|
1058
|
-
keyObject = KeyObject.createKeyObject(
|
|
1059
|
-
'private',
|
|
1060
|
-
keyData,
|
|
1061
|
-
KFormatType.DER,
|
|
1062
|
-
KeyEncoding.PKCS8,
|
|
1063
|
-
);
|
|
1064
|
-
} else {
|
|
1254
|
+
function mlkemImportKey(
|
|
1255
|
+
format: ImportFormat,
|
|
1256
|
+
data: BufferLike,
|
|
1257
|
+
algorithm: SubtleAlgorithm,
|
|
1258
|
+
extractable: boolean,
|
|
1259
|
+
keyUsages: KeyUsage[],
|
|
1260
|
+
): CryptoKey {
|
|
1261
|
+
const { name } = algorithm;
|
|
1262
|
+
const isPublicFormat = format === 'spki' || format === 'raw';
|
|
1263
|
+
const allowedUsages: KeyUsage[] = isPublicFormat
|
|
1264
|
+
? ['encapsulateBits', 'encapsulateKey']
|
|
1265
|
+
: ['decapsulateBits', 'decapsulateKey'];
|
|
1266
|
+
if (hasAnyNotIn(keyUsages, allowedUsages)) {
|
|
1065
1267
|
throw lazyDOMException(
|
|
1066
|
-
`Unsupported
|
|
1067
|
-
'
|
|
1268
|
+
`Unsupported key usage for ${name} key`,
|
|
1269
|
+
'SyntaxError',
|
|
1068
1270
|
);
|
|
1069
1271
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1272
|
+
return new CryptoKey(
|
|
1273
|
+
pqcImportKeyObject(format, data, name),
|
|
1274
|
+
{ name },
|
|
1275
|
+
keyUsages,
|
|
1276
|
+
extractable,
|
|
1277
|
+
);
|
|
1072
1278
|
}
|
|
1073
1279
|
|
|
1074
1280
|
const exportKeySpki = async (
|
|
@@ -1117,6 +1323,17 @@ const exportKeySpki = async (
|
|
|
1117
1323
|
);
|
|
1118
1324
|
}
|
|
1119
1325
|
break;
|
|
1326
|
+
case 'ML-KEM-512':
|
|
1327
|
+
// Fall through
|
|
1328
|
+
case 'ML-KEM-768':
|
|
1329
|
+
// Fall through
|
|
1330
|
+
case 'ML-KEM-1024':
|
|
1331
|
+
if (key.type === 'public') {
|
|
1332
|
+
return bufferLikeToArrayBuffer(
|
|
1333
|
+
key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.SPKI),
|
|
1334
|
+
);
|
|
1335
|
+
}
|
|
1336
|
+
break;
|
|
1120
1337
|
}
|
|
1121
1338
|
|
|
1122
1339
|
throw new Error(
|
|
@@ -1170,6 +1387,17 @@ const exportKeyPkcs8 = async (
|
|
|
1170
1387
|
);
|
|
1171
1388
|
}
|
|
1172
1389
|
break;
|
|
1390
|
+
case 'ML-KEM-512':
|
|
1391
|
+
// Fall through
|
|
1392
|
+
case 'ML-KEM-768':
|
|
1393
|
+
// Fall through
|
|
1394
|
+
case 'ML-KEM-1024':
|
|
1395
|
+
if (key.type === 'private') {
|
|
1396
|
+
return bufferLikeToArrayBuffer(
|
|
1397
|
+
key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
break;
|
|
1173
1401
|
}
|
|
1174
1402
|
|
|
1175
1403
|
throw new Error(
|
|
@@ -1194,7 +1422,22 @@ const exportKeyRaw = (key: CryptoKey): ArrayBuffer | unknown => {
|
|
|
1194
1422
|
// Fall through
|
|
1195
1423
|
case 'X448':
|
|
1196
1424
|
if (key.type === 'public') {
|
|
1197
|
-
|
|
1425
|
+
const exported = key.keyObject.handle.exportKey();
|
|
1426
|
+
return bufferLikeToArrayBuffer(exported);
|
|
1427
|
+
}
|
|
1428
|
+
break;
|
|
1429
|
+
case 'ML-KEM-512':
|
|
1430
|
+
// Fall through
|
|
1431
|
+
case 'ML-KEM-768':
|
|
1432
|
+
// Fall through
|
|
1433
|
+
case 'ML-KEM-1024':
|
|
1434
|
+
// Fall through
|
|
1435
|
+
case 'ML-DSA-44':
|
|
1436
|
+
// Fall through
|
|
1437
|
+
case 'ML-DSA-65':
|
|
1438
|
+
// Fall through
|
|
1439
|
+
case 'ML-DSA-87':
|
|
1440
|
+
if (key.type === 'public') {
|
|
1198
1441
|
const exported = key.keyObject.handle.exportKey();
|
|
1199
1442
|
return bufferLikeToArrayBuffer(exported);
|
|
1200
1443
|
}
|
|
@@ -1211,7 +1454,11 @@ const exportKeyRaw = (key: CryptoKey): ArrayBuffer | unknown => {
|
|
|
1211
1454
|
// Fall through
|
|
1212
1455
|
case 'ChaCha20-Poly1305':
|
|
1213
1456
|
// Fall through
|
|
1214
|
-
case 'HMAC':
|
|
1457
|
+
case 'HMAC':
|
|
1458
|
+
// Fall through
|
|
1459
|
+
case 'KMAC128':
|
|
1460
|
+
// Fall through
|
|
1461
|
+
case 'KMAC256': {
|
|
1215
1462
|
const exported = key.keyObject.export();
|
|
1216
1463
|
// Convert Buffer to ArrayBuffer
|
|
1217
1464
|
return exported.buffer.slice(
|
|
@@ -1248,6 +1495,12 @@ const exportKeyJWK = (key: CryptoKey): ArrayBuffer | unknown => {
|
|
|
1248
1495
|
case 'HMAC':
|
|
1249
1496
|
jwk.alg = normalizeHashName(key.algorithm.hash, HashContext.JwkHmac);
|
|
1250
1497
|
return jwk;
|
|
1498
|
+
case 'KMAC128':
|
|
1499
|
+
jwk.alg = 'K128';
|
|
1500
|
+
return jwk;
|
|
1501
|
+
case 'KMAC256':
|
|
1502
|
+
jwk.alg = 'K256';
|
|
1503
|
+
return jwk;
|
|
1251
1504
|
case 'ECDSA':
|
|
1252
1505
|
// Fall through
|
|
1253
1506
|
case 'ECDH':
|
|
@@ -1364,6 +1617,45 @@ const checkCryptoKeyPairUsages = (pair: CryptoKeyPair) => {
|
|
|
1364
1617
|
);
|
|
1365
1618
|
};
|
|
1366
1619
|
|
|
1620
|
+
function argon2DeriveBits(
|
|
1621
|
+
algorithm: SubtleAlgorithm,
|
|
1622
|
+
baseKey: CryptoKey,
|
|
1623
|
+
length: number,
|
|
1624
|
+
): ArrayBuffer {
|
|
1625
|
+
if (length === 0 || length % 8 !== 0) {
|
|
1626
|
+
throw lazyDOMException(
|
|
1627
|
+
'Invalid Argon2 derived key length',
|
|
1628
|
+
'OperationError',
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1631
|
+
if (length < 32) {
|
|
1632
|
+
throw lazyDOMException(
|
|
1633
|
+
'Argon2 derived key length must be at least 32 bits',
|
|
1634
|
+
'OperationError',
|
|
1635
|
+
);
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
const { nonce, parallelism, memory, passes, secretValue, associatedData } =
|
|
1639
|
+
algorithm;
|
|
1640
|
+
const tagLength = length / 8;
|
|
1641
|
+
const message = baseKey.keyObject.export();
|
|
1642
|
+
const algName = algorithm.name.toLowerCase();
|
|
1643
|
+
|
|
1644
|
+
const result = argon2Sync(algName, {
|
|
1645
|
+
message,
|
|
1646
|
+
nonce: nonce ?? new Uint8Array(0),
|
|
1647
|
+
parallelism: parallelism ?? 1,
|
|
1648
|
+
tagLength,
|
|
1649
|
+
memory: memory ?? 65536,
|
|
1650
|
+
passes: passes ?? 3,
|
|
1651
|
+
secret: secretValue,
|
|
1652
|
+
associatedData,
|
|
1653
|
+
version: algorithm.version,
|
|
1654
|
+
});
|
|
1655
|
+
|
|
1656
|
+
return bufferLikeToArrayBuffer(result);
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1367
1659
|
// Type guard to check if result is CryptoKeyPair
|
|
1368
1660
|
export function isCryptoKeyPair(
|
|
1369
1661
|
result: CryptoKey | CryptoKeyPair,
|
|
@@ -1395,24 +1687,20 @@ function hmacSignVerify(
|
|
|
1395
1687
|
);
|
|
1396
1688
|
}
|
|
1397
1689
|
|
|
1398
|
-
|
|
1399
|
-
const
|
|
1400
|
-
const computedBytes = new Uint8Array(
|
|
1401
|
-
computed.buffer,
|
|
1690
|
+
const sigBuffer = bufferLikeToArrayBuffer(signature);
|
|
1691
|
+
const computedBuffer = computed.buffer.slice(
|
|
1402
1692
|
computed.byteOffset,
|
|
1403
|
-
computed.byteLength,
|
|
1693
|
+
computed.byteOffset + computed.byteLength,
|
|
1404
1694
|
);
|
|
1405
1695
|
|
|
1406
|
-
if (
|
|
1696
|
+
if (computedBuffer.byteLength !== sigBuffer.byteLength) {
|
|
1407
1697
|
return false;
|
|
1408
1698
|
}
|
|
1409
1699
|
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
}
|
|
1415
|
-
return result === 0;
|
|
1700
|
+
return timingSafeEqual(
|
|
1701
|
+
new Uint8Array(computedBuffer),
|
|
1702
|
+
new Uint8Array(sigBuffer),
|
|
1703
|
+
);
|
|
1416
1704
|
}
|
|
1417
1705
|
|
|
1418
1706
|
function rsaSignVerify(
|
|
@@ -1555,6 +1843,9 @@ const signVerify = (
|
|
|
1555
1843
|
case 'ML-DSA-65':
|
|
1556
1844
|
case 'ML-DSA-87':
|
|
1557
1845
|
return mldsaSignVerify(key, data, signature);
|
|
1846
|
+
case 'KMAC128':
|
|
1847
|
+
case 'KMAC256':
|
|
1848
|
+
return kmacSignVerify(key, data, algorithm, signature);
|
|
1558
1849
|
}
|
|
1559
1850
|
throw lazyDOMException(
|
|
1560
1851
|
`Unrecognized algorithm name '${algorithm.name}' for '${usage}'`,
|
|
@@ -1604,7 +1895,241 @@ const cipherOrWrap = async (
|
|
|
1604
1895
|
}
|
|
1605
1896
|
};
|
|
1606
1897
|
|
|
1898
|
+
const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
|
|
1899
|
+
encrypt: new Set([
|
|
1900
|
+
'RSA-OAEP',
|
|
1901
|
+
'AES-CTR',
|
|
1902
|
+
'AES-CBC',
|
|
1903
|
+
'AES-GCM',
|
|
1904
|
+
'AES-OCB',
|
|
1905
|
+
'ChaCha20-Poly1305',
|
|
1906
|
+
]),
|
|
1907
|
+
decrypt: new Set([
|
|
1908
|
+
'RSA-OAEP',
|
|
1909
|
+
'AES-CTR',
|
|
1910
|
+
'AES-CBC',
|
|
1911
|
+
'AES-GCM',
|
|
1912
|
+
'AES-OCB',
|
|
1913
|
+
'ChaCha20-Poly1305',
|
|
1914
|
+
]),
|
|
1915
|
+
sign: new Set([
|
|
1916
|
+
'RSASSA-PKCS1-v1_5',
|
|
1917
|
+
'RSA-PSS',
|
|
1918
|
+
'ECDSA',
|
|
1919
|
+
'HMAC',
|
|
1920
|
+
'KMAC128',
|
|
1921
|
+
'KMAC256',
|
|
1922
|
+
'Ed25519',
|
|
1923
|
+
'Ed448',
|
|
1924
|
+
'ML-DSA-44',
|
|
1925
|
+
'ML-DSA-65',
|
|
1926
|
+
'ML-DSA-87',
|
|
1927
|
+
]),
|
|
1928
|
+
verify: new Set([
|
|
1929
|
+
'RSASSA-PKCS1-v1_5',
|
|
1930
|
+
'RSA-PSS',
|
|
1931
|
+
'ECDSA',
|
|
1932
|
+
'HMAC',
|
|
1933
|
+
'KMAC128',
|
|
1934
|
+
'KMAC256',
|
|
1935
|
+
'Ed25519',
|
|
1936
|
+
'Ed448',
|
|
1937
|
+
'ML-DSA-44',
|
|
1938
|
+
'ML-DSA-65',
|
|
1939
|
+
'ML-DSA-87',
|
|
1940
|
+
]),
|
|
1941
|
+
digest: new Set([
|
|
1942
|
+
'SHA-1',
|
|
1943
|
+
'SHA-256',
|
|
1944
|
+
'SHA-384',
|
|
1945
|
+
'SHA-512',
|
|
1946
|
+
'SHA3-256',
|
|
1947
|
+
'SHA3-384',
|
|
1948
|
+
'SHA3-512',
|
|
1949
|
+
'cSHAKE128',
|
|
1950
|
+
'cSHAKE256',
|
|
1951
|
+
]),
|
|
1952
|
+
generateKey: new Set([
|
|
1953
|
+
'RSASSA-PKCS1-v1_5',
|
|
1954
|
+
'RSA-PSS',
|
|
1955
|
+
'RSA-OAEP',
|
|
1956
|
+
'ECDSA',
|
|
1957
|
+
'ECDH',
|
|
1958
|
+
'Ed25519',
|
|
1959
|
+
'Ed448',
|
|
1960
|
+
'X25519',
|
|
1961
|
+
'X448',
|
|
1962
|
+
'AES-CTR',
|
|
1963
|
+
'AES-CBC',
|
|
1964
|
+
'AES-GCM',
|
|
1965
|
+
'AES-KW',
|
|
1966
|
+
'AES-OCB',
|
|
1967
|
+
'ChaCha20-Poly1305',
|
|
1968
|
+
'HMAC',
|
|
1969
|
+
'KMAC128',
|
|
1970
|
+
'KMAC256',
|
|
1971
|
+
'ML-DSA-44',
|
|
1972
|
+
'ML-DSA-65',
|
|
1973
|
+
'ML-DSA-87',
|
|
1974
|
+
'ML-KEM-512',
|
|
1975
|
+
'ML-KEM-768',
|
|
1976
|
+
'ML-KEM-1024',
|
|
1977
|
+
]),
|
|
1978
|
+
importKey: new Set([
|
|
1979
|
+
'RSASSA-PKCS1-v1_5',
|
|
1980
|
+
'RSA-PSS',
|
|
1981
|
+
'RSA-OAEP',
|
|
1982
|
+
'ECDSA',
|
|
1983
|
+
'ECDH',
|
|
1984
|
+
'Ed25519',
|
|
1985
|
+
'Ed448',
|
|
1986
|
+
'X25519',
|
|
1987
|
+
'X448',
|
|
1988
|
+
'AES-CTR',
|
|
1989
|
+
'AES-CBC',
|
|
1990
|
+
'AES-GCM',
|
|
1991
|
+
'AES-KW',
|
|
1992
|
+
'AES-OCB',
|
|
1993
|
+
'ChaCha20-Poly1305',
|
|
1994
|
+
'HMAC',
|
|
1995
|
+
'KMAC128',
|
|
1996
|
+
'KMAC256',
|
|
1997
|
+
'HKDF',
|
|
1998
|
+
'PBKDF2',
|
|
1999
|
+
'Argon2d',
|
|
2000
|
+
'Argon2i',
|
|
2001
|
+
'Argon2id',
|
|
2002
|
+
'ML-DSA-44',
|
|
2003
|
+
'ML-DSA-65',
|
|
2004
|
+
'ML-DSA-87',
|
|
2005
|
+
'ML-KEM-512',
|
|
2006
|
+
'ML-KEM-768',
|
|
2007
|
+
'ML-KEM-1024',
|
|
2008
|
+
]),
|
|
2009
|
+
exportKey: new Set([
|
|
2010
|
+
'RSASSA-PKCS1-v1_5',
|
|
2011
|
+
'RSA-PSS',
|
|
2012
|
+
'RSA-OAEP',
|
|
2013
|
+
'ECDSA',
|
|
2014
|
+
'ECDH',
|
|
2015
|
+
'Ed25519',
|
|
2016
|
+
'Ed448',
|
|
2017
|
+
'X25519',
|
|
2018
|
+
'X448',
|
|
2019
|
+
'AES-CTR',
|
|
2020
|
+
'AES-CBC',
|
|
2021
|
+
'AES-GCM',
|
|
2022
|
+
'AES-KW',
|
|
2023
|
+
'AES-OCB',
|
|
2024
|
+
'ChaCha20-Poly1305',
|
|
2025
|
+
'HMAC',
|
|
2026
|
+
'KMAC128',
|
|
2027
|
+
'KMAC256',
|
|
2028
|
+
'ML-DSA-44',
|
|
2029
|
+
'ML-DSA-65',
|
|
2030
|
+
'ML-DSA-87',
|
|
2031
|
+
'ML-KEM-512',
|
|
2032
|
+
'ML-KEM-768',
|
|
2033
|
+
'ML-KEM-1024',
|
|
2034
|
+
]),
|
|
2035
|
+
deriveBits: new Set([
|
|
2036
|
+
'PBKDF2',
|
|
2037
|
+
'HKDF',
|
|
2038
|
+
'ECDH',
|
|
2039
|
+
'X25519',
|
|
2040
|
+
'X448',
|
|
2041
|
+
'Argon2d',
|
|
2042
|
+
'Argon2i',
|
|
2043
|
+
'Argon2id',
|
|
2044
|
+
]),
|
|
2045
|
+
wrapKey: new Set([
|
|
2046
|
+
'AES-CTR',
|
|
2047
|
+
'AES-CBC',
|
|
2048
|
+
'AES-GCM',
|
|
2049
|
+
'AES-KW',
|
|
2050
|
+
'AES-OCB',
|
|
2051
|
+
'ChaCha20-Poly1305',
|
|
2052
|
+
'RSA-OAEP',
|
|
2053
|
+
]),
|
|
2054
|
+
unwrapKey: new Set([
|
|
2055
|
+
'AES-CTR',
|
|
2056
|
+
'AES-CBC',
|
|
2057
|
+
'AES-GCM',
|
|
2058
|
+
'AES-KW',
|
|
2059
|
+
'AES-OCB',
|
|
2060
|
+
'ChaCha20-Poly1305',
|
|
2061
|
+
'RSA-OAEP',
|
|
2062
|
+
]),
|
|
2063
|
+
encapsulateBits: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
|
|
2064
|
+
decapsulateBits: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
|
|
2065
|
+
encapsulateKey: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
|
|
2066
|
+
decapsulateKey: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
|
|
2067
|
+
};
|
|
2068
|
+
|
|
2069
|
+
const ASYMMETRIC_ALGORITHMS = new Set([
|
|
2070
|
+
'RSASSA-PKCS1-v1_5',
|
|
2071
|
+
'RSA-PSS',
|
|
2072
|
+
'RSA-OAEP',
|
|
2073
|
+
'ECDSA',
|
|
2074
|
+
'ECDH',
|
|
2075
|
+
'Ed25519',
|
|
2076
|
+
'Ed448',
|
|
2077
|
+
'X25519',
|
|
2078
|
+
'X448',
|
|
2079
|
+
'ML-DSA-44',
|
|
2080
|
+
'ML-DSA-65',
|
|
2081
|
+
'ML-DSA-87',
|
|
2082
|
+
'ML-KEM-512',
|
|
2083
|
+
'ML-KEM-768',
|
|
2084
|
+
'ML-KEM-1024',
|
|
2085
|
+
]);
|
|
2086
|
+
|
|
1607
2087
|
export class Subtle {
|
|
2088
|
+
static supports(
|
|
2089
|
+
operation: string,
|
|
2090
|
+
algorithm: SubtleAlgorithm | AnyAlgorithm,
|
|
2091
|
+
_lengthOrAdditionalAlgorithm?: unknown,
|
|
2092
|
+
): boolean {
|
|
2093
|
+
let normalizedAlgorithm: SubtleAlgorithm;
|
|
2094
|
+
try {
|
|
2095
|
+
normalizedAlgorithm = normalizeAlgorithm(
|
|
2096
|
+
algorithm,
|
|
2097
|
+
(operation === 'getPublicKey' ? 'exportKey' : operation) as Operation,
|
|
2098
|
+
);
|
|
2099
|
+
} catch {
|
|
2100
|
+
return false;
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
const name = normalizedAlgorithm.name;
|
|
2104
|
+
|
|
2105
|
+
if (operation === 'getPublicKey') {
|
|
2106
|
+
return ASYMMETRIC_ALGORITHMS.has(name);
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
if (operation === 'deriveKey') {
|
|
2110
|
+
// deriveKey decomposes to deriveBits + importKey of additional algorithm
|
|
2111
|
+
if (!SUPPORTED_ALGORITHMS.deriveBits?.has(name)) return false;
|
|
2112
|
+
if (_lengthOrAdditionalAlgorithm != null) {
|
|
2113
|
+
try {
|
|
2114
|
+
const additionalAlg = normalizeAlgorithm(
|
|
2115
|
+
_lengthOrAdditionalAlgorithm as SubtleAlgorithm | AnyAlgorithm,
|
|
2116
|
+
'importKey',
|
|
2117
|
+
);
|
|
2118
|
+
return (
|
|
2119
|
+
SUPPORTED_ALGORITHMS.importKey?.has(additionalAlg.name) ?? false
|
|
2120
|
+
);
|
|
2121
|
+
} catch {
|
|
2122
|
+
return false;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
return true;
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
const supported = SUPPORTED_ALGORITHMS[operation];
|
|
2129
|
+
if (!supported) return false;
|
|
2130
|
+
return supported.has(name);
|
|
2131
|
+
}
|
|
2132
|
+
|
|
1608
2133
|
async decrypt(
|
|
1609
2134
|
algorithm: EncryptDecryptParams,
|
|
1610
2135
|
key: CryptoKey,
|
|
@@ -1660,6 +2185,10 @@ export class Subtle {
|
|
|
1660
2185
|
baseKey,
|
|
1661
2186
|
length,
|
|
1662
2187
|
);
|
|
2188
|
+
case 'Argon2d':
|
|
2189
|
+
case 'Argon2i':
|
|
2190
|
+
case 'Argon2id':
|
|
2191
|
+
return argon2DeriveBits(algorithm, baseKey, length);
|
|
1663
2192
|
}
|
|
1664
2193
|
throw new Error(
|
|
1665
2194
|
`'subtle.deriveBits()' for ${algorithm.name} is not implemented.`,
|
|
@@ -1711,6 +2240,11 @@ export class Subtle {
|
|
|
1711
2240
|
length,
|
|
1712
2241
|
);
|
|
1713
2242
|
break;
|
|
2243
|
+
case 'Argon2d':
|
|
2244
|
+
case 'Argon2i':
|
|
2245
|
+
case 'Argon2id':
|
|
2246
|
+
derivedBits = argon2DeriveBits(algorithm, baseKey, length);
|
|
2247
|
+
break;
|
|
1714
2248
|
default:
|
|
1715
2249
|
throw new Error(
|
|
1716
2250
|
`'subtle.deriveKey()' for ${algorithm.name} is not implemented.`,
|
|
@@ -1748,7 +2282,32 @@ export class Subtle {
|
|
|
1748
2282
|
): Promise<ArrayBuffer | JWK> {
|
|
1749
2283
|
if (!key.extractable) throw new Error('key is not extractable');
|
|
1750
2284
|
|
|
1751
|
-
if (format === 'raw-
|
|
2285
|
+
if (format === 'raw-seed') {
|
|
2286
|
+
const pqcAlgos = [
|
|
2287
|
+
'ML-KEM-512',
|
|
2288
|
+
'ML-KEM-768',
|
|
2289
|
+
'ML-KEM-1024',
|
|
2290
|
+
'ML-DSA-44',
|
|
2291
|
+
'ML-DSA-65',
|
|
2292
|
+
'ML-DSA-87',
|
|
2293
|
+
];
|
|
2294
|
+
if (!pqcAlgos.includes(key.algorithm.name)) {
|
|
2295
|
+
throw lazyDOMException(
|
|
2296
|
+
'raw-seed export only supported for PQC keys',
|
|
2297
|
+
'NotSupportedError',
|
|
2298
|
+
);
|
|
2299
|
+
}
|
|
2300
|
+
if (key.type !== 'private') {
|
|
2301
|
+
throw lazyDOMException(
|
|
2302
|
+
'raw-seed export requires a private key',
|
|
2303
|
+
'InvalidAccessError',
|
|
2304
|
+
);
|
|
2305
|
+
}
|
|
2306
|
+
return bufferLikeToArrayBuffer(key.keyObject.handle.exportKey());
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
// Note: 'raw-seed' is handled above; do NOT normalize it here
|
|
2310
|
+
if (format === 'raw-secret' || format === 'raw-public') format = 'raw';
|
|
1752
2311
|
|
|
1753
2312
|
switch (format) {
|
|
1754
2313
|
case 'spki':
|
|
@@ -1935,6 +2494,11 @@ export class Subtle {
|
|
|
1935
2494
|
case 'HMAC':
|
|
1936
2495
|
result = await hmacGenerateKey(algorithm, extractable, keyUsages);
|
|
1937
2496
|
break;
|
|
2497
|
+
case 'KMAC128':
|
|
2498
|
+
// Fall through
|
|
2499
|
+
case 'KMAC256':
|
|
2500
|
+
result = await kmacGenerateKey(algorithm, extractable, keyUsages);
|
|
2501
|
+
break;
|
|
1938
2502
|
case 'Ed25519':
|
|
1939
2503
|
// Fall through
|
|
1940
2504
|
case 'Ed448':
|
|
@@ -1967,6 +2531,18 @@ export class Subtle {
|
|
|
1967
2531
|
);
|
|
1968
2532
|
checkCryptoKeyPairUsages(result as CryptoKeyPair);
|
|
1969
2533
|
break;
|
|
2534
|
+
case 'ML-KEM-512':
|
|
2535
|
+
// Fall through
|
|
2536
|
+
case 'ML-KEM-768':
|
|
2537
|
+
// Fall through
|
|
2538
|
+
case 'ML-KEM-1024':
|
|
2539
|
+
result = await mlkem_generateKeyPairWebCrypto(
|
|
2540
|
+
algorithm.name as MlKemVariant,
|
|
2541
|
+
extractable,
|
|
2542
|
+
keyUsages,
|
|
2543
|
+
);
|
|
2544
|
+
checkCryptoKeyPairUsages(result as CryptoKeyPair);
|
|
2545
|
+
break;
|
|
1970
2546
|
default:
|
|
1971
2547
|
throw new Error(
|
|
1972
2548
|
`'subtle.generateKey()' is not implemented for ${algorithm.name}.
|
|
@@ -1977,6 +2553,21 @@ export class Subtle {
|
|
|
1977
2553
|
return result;
|
|
1978
2554
|
}
|
|
1979
2555
|
|
|
2556
|
+
async getPublicKey(
|
|
2557
|
+
key: CryptoKey,
|
|
2558
|
+
keyUsages: KeyUsage[],
|
|
2559
|
+
): Promise<CryptoKey> {
|
|
2560
|
+
if (key.type === 'secret') {
|
|
2561
|
+
throw lazyDOMException('key must be a private key', 'NotSupportedError');
|
|
2562
|
+
}
|
|
2563
|
+
if (key.type !== 'private') {
|
|
2564
|
+
throw lazyDOMException('key must be a private key', 'InvalidAccessError');
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2567
|
+
const publicKeyObject = createPublicKey(key.keyObject);
|
|
2568
|
+
return publicKeyObject.toCryptoKey(key.algorithm, true, keyUsages);
|
|
2569
|
+
}
|
|
2570
|
+
|
|
1980
2571
|
async importKey(
|
|
1981
2572
|
format: ImportFormat,
|
|
1982
2573
|
data: BufferLike | BinaryLike | JWK,
|
|
@@ -1984,7 +2575,8 @@ export class Subtle {
|
|
|
1984
2575
|
extractable: boolean,
|
|
1985
2576
|
keyUsages: KeyUsage[],
|
|
1986
2577
|
): Promise<CryptoKey> {
|
|
1987
|
-
|
|
2578
|
+
// Note: 'raw-seed' is NOT normalized — PQC import functions handle it directly
|
|
2579
|
+
if (format === 'raw-secret' || format === 'raw-public') format = 'raw';
|
|
1988
2580
|
const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'importKey');
|
|
1989
2581
|
let result: CryptoKey;
|
|
1990
2582
|
switch (normalizedAlgorithm.name) {
|
|
@@ -2021,6 +2613,17 @@ export class Subtle {
|
|
|
2021
2613
|
keyUsages,
|
|
2022
2614
|
);
|
|
2023
2615
|
break;
|
|
2616
|
+
case 'KMAC128':
|
|
2617
|
+
// Fall through
|
|
2618
|
+
case 'KMAC256':
|
|
2619
|
+
result = await kmacImportKey(
|
|
2620
|
+
normalizedAlgorithm,
|
|
2621
|
+
format,
|
|
2622
|
+
data as BufferLike | JWK,
|
|
2623
|
+
extractable,
|
|
2624
|
+
keyUsages,
|
|
2625
|
+
);
|
|
2626
|
+
break;
|
|
2024
2627
|
case 'AES-CTR':
|
|
2025
2628
|
// Fall through
|
|
2026
2629
|
case 'AES-CBC':
|
|
@@ -2041,6 +2644,9 @@ export class Subtle {
|
|
|
2041
2644
|
);
|
|
2042
2645
|
break;
|
|
2043
2646
|
case 'PBKDF2':
|
|
2647
|
+
case 'Argon2d':
|
|
2648
|
+
case 'Argon2i':
|
|
2649
|
+
case 'Argon2id':
|
|
2044
2650
|
result = await importGenericSecretKey(
|
|
2045
2651
|
normalizedAlgorithm,
|
|
2046
2652
|
format,
|
|
@@ -2086,6 +2692,19 @@ export class Subtle {
|
|
|
2086
2692
|
keyUsages,
|
|
2087
2693
|
);
|
|
2088
2694
|
break;
|
|
2695
|
+
case 'ML-KEM-512':
|
|
2696
|
+
// Fall through
|
|
2697
|
+
case 'ML-KEM-768':
|
|
2698
|
+
// Fall through
|
|
2699
|
+
case 'ML-KEM-1024':
|
|
2700
|
+
result = mlkemImportKey(
|
|
2701
|
+
format,
|
|
2702
|
+
data as BufferLike,
|
|
2703
|
+
normalizedAlgorithm,
|
|
2704
|
+
extractable,
|
|
2705
|
+
keyUsages,
|
|
2706
|
+
);
|
|
2707
|
+
break;
|
|
2089
2708
|
default:
|
|
2090
2709
|
throw new Error(
|
|
2091
2710
|
`"subtle.importKey()" is not implemented for ${normalizedAlgorithm.name}`,
|
|
@@ -2109,103 +2728,164 @@ export class Subtle {
|
|
|
2109
2728
|
key: CryptoKey,
|
|
2110
2729
|
data: BufferLike,
|
|
2111
2730
|
): Promise<ArrayBuffer> {
|
|
2112
|
-
|
|
2731
|
+
return signVerify(
|
|
2732
|
+
normalizeAlgorithm(algorithm, 'sign'),
|
|
2733
|
+
key,
|
|
2734
|
+
data,
|
|
2735
|
+
) as ArrayBuffer;
|
|
2736
|
+
}
|
|
2113
2737
|
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2738
|
+
async verify(
|
|
2739
|
+
algorithm: SubtleAlgorithm,
|
|
2740
|
+
key: CryptoKey,
|
|
2741
|
+
signature: BufferLike,
|
|
2742
|
+
data: BufferLike,
|
|
2743
|
+
): Promise<boolean> {
|
|
2744
|
+
return signVerify(
|
|
2745
|
+
normalizeAlgorithm(algorithm, 'verify'),
|
|
2746
|
+
key,
|
|
2747
|
+
data,
|
|
2748
|
+
signature,
|
|
2749
|
+
) as boolean;
|
|
2750
|
+
}
|
|
2122
2751
|
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
if (typeof alg.hash === 'string') {
|
|
2132
|
-
hashAlgorithm = alg.hash;
|
|
2133
|
-
} else if (alg.hash?.name) {
|
|
2134
|
-
hashAlgorithm = alg.hash.name;
|
|
2135
|
-
} else if (typeof keyAlg.hash === 'string') {
|
|
2136
|
-
hashAlgorithm = keyAlg.hash;
|
|
2137
|
-
} else if (keyAlg.hash?.name) {
|
|
2138
|
-
hashAlgorithm = keyAlg.hash.name;
|
|
2139
|
-
}
|
|
2752
|
+
private _encapsulateCore(
|
|
2753
|
+
algorithm: SubtleAlgorithm,
|
|
2754
|
+
key: CryptoKey,
|
|
2755
|
+
): EncapsulateResult {
|
|
2756
|
+
const normalizedAlgorithm = normalizeAlgorithm(
|
|
2757
|
+
algorithm,
|
|
2758
|
+
'encapsulateBits' as Operation,
|
|
2759
|
+
);
|
|
2140
2760
|
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
const hmac = createHmac(hashAlgorithm, keyData);
|
|
2144
|
-
hmac.update(bufferLikeToArrayBuffer(data));
|
|
2145
|
-
return bufferLikeToArrayBuffer(hmac.digest());
|
|
2761
|
+
if (key.algorithm.name !== normalizedAlgorithm.name) {
|
|
2762
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
2146
2763
|
}
|
|
2147
2764
|
|
|
2148
|
-
|
|
2765
|
+
const variant = normalizedAlgorithm.name as MlKemVariant;
|
|
2766
|
+
const mlkem = new MlKem(variant);
|
|
2767
|
+
|
|
2768
|
+
const keyData = key.keyObject.handle.exportKey(
|
|
2769
|
+
KFormatType.DER,
|
|
2770
|
+
KeyEncoding.SPKI,
|
|
2771
|
+
);
|
|
2772
|
+
mlkem.setPublicKey(
|
|
2773
|
+
bufferLikeToArrayBuffer(keyData),
|
|
2774
|
+
KFormatType.DER,
|
|
2775
|
+
KeyEncoding.SPKI,
|
|
2776
|
+
);
|
|
2777
|
+
|
|
2778
|
+
return mlkem.encapsulateSync();
|
|
2149
2779
|
}
|
|
2150
2780
|
|
|
2151
|
-
|
|
2781
|
+
private _decapsulateCore(
|
|
2152
2782
|
algorithm: SubtleAlgorithm,
|
|
2153
2783
|
key: CryptoKey,
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2784
|
+
ciphertext: BufferLike,
|
|
2785
|
+
): ArrayBuffer {
|
|
2786
|
+
const normalizedAlgorithm = normalizeAlgorithm(
|
|
2787
|
+
algorithm,
|
|
2788
|
+
'decapsulateBits' as Operation,
|
|
2789
|
+
);
|
|
2158
2790
|
|
|
2159
|
-
if (
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
throw lazyDOMException(
|
|
2163
|
-
'Key does not have verify usage',
|
|
2164
|
-
'InvalidAccessError',
|
|
2165
|
-
);
|
|
2166
|
-
}
|
|
2791
|
+
if (key.algorithm.name !== normalizedAlgorithm.name) {
|
|
2792
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
2793
|
+
}
|
|
2167
2794
|
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2171
|
-
const alg = normalizedAlgorithm as any;
|
|
2172
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2173
|
-
const keyAlg = key.algorithm as any;
|
|
2174
|
-
let hashAlgorithm = 'SHA-256';
|
|
2175
|
-
|
|
2176
|
-
if (typeof alg.hash === 'string') {
|
|
2177
|
-
hashAlgorithm = alg.hash;
|
|
2178
|
-
} else if (alg.hash?.name) {
|
|
2179
|
-
hashAlgorithm = alg.hash.name;
|
|
2180
|
-
} else if (typeof keyAlg.hash === 'string') {
|
|
2181
|
-
hashAlgorithm = keyAlg.hash;
|
|
2182
|
-
} else if (keyAlg.hash?.name) {
|
|
2183
|
-
hashAlgorithm = keyAlg.hash.name;
|
|
2184
|
-
}
|
|
2795
|
+
const variant = normalizedAlgorithm.name as MlKemVariant;
|
|
2796
|
+
const mlkem = new MlKem(variant);
|
|
2185
2797
|
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
const signatureArray = new Uint8Array(bufferLikeToArrayBuffer(signature));
|
|
2196
|
-
if (expected.length !== signatureArray.length) {
|
|
2197
|
-
return false;
|
|
2198
|
-
}
|
|
2798
|
+
const keyData = key.keyObject.handle.exportKey(
|
|
2799
|
+
KFormatType.DER,
|
|
2800
|
+
KeyEncoding.PKCS8,
|
|
2801
|
+
);
|
|
2802
|
+
mlkem.setPrivateKey(
|
|
2803
|
+
bufferLikeToArrayBuffer(keyData),
|
|
2804
|
+
KFormatType.DER,
|
|
2805
|
+
KeyEncoding.PKCS8,
|
|
2806
|
+
);
|
|
2199
2807
|
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2808
|
+
return mlkem.decapsulateSync(bufferLikeToArrayBuffer(ciphertext));
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
async encapsulateBits(
|
|
2812
|
+
algorithm: SubtleAlgorithm,
|
|
2813
|
+
key: CryptoKey,
|
|
2814
|
+
): Promise<EncapsulateResult> {
|
|
2815
|
+
if (!key.usages.includes('encapsulateBits')) {
|
|
2816
|
+
throw lazyDOMException(
|
|
2817
|
+
'Key does not have encapsulateBits usage',
|
|
2818
|
+
'InvalidAccessError',
|
|
2819
|
+
);
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
return this._encapsulateCore(algorithm, key);
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
async encapsulateKey(
|
|
2826
|
+
algorithm: SubtleAlgorithm,
|
|
2827
|
+
key: CryptoKey,
|
|
2828
|
+
sharedKeyAlgorithm: SubtleAlgorithm | AnyAlgorithm,
|
|
2829
|
+
extractable: boolean,
|
|
2830
|
+
usages: KeyUsage[],
|
|
2831
|
+
): Promise<{ key: CryptoKey; ciphertext: ArrayBuffer }> {
|
|
2832
|
+
if (!key.usages.includes('encapsulateKey')) {
|
|
2833
|
+
throw lazyDOMException(
|
|
2834
|
+
'Key does not have encapsulateKey usage',
|
|
2835
|
+
'InvalidAccessError',
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2839
|
+
const { sharedKey, ciphertext } = this._encapsulateCore(algorithm, key);
|
|
2840
|
+
const importedKey = await this.importKey(
|
|
2841
|
+
'raw',
|
|
2842
|
+
sharedKey,
|
|
2843
|
+
sharedKeyAlgorithm,
|
|
2844
|
+
extractable,
|
|
2845
|
+
usages,
|
|
2846
|
+
);
|
|
2847
|
+
|
|
2848
|
+
return { key: importedKey, ciphertext };
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
async decapsulateBits(
|
|
2852
|
+
algorithm: SubtleAlgorithm,
|
|
2853
|
+
key: CryptoKey,
|
|
2854
|
+
ciphertext: BufferLike,
|
|
2855
|
+
): Promise<ArrayBuffer> {
|
|
2856
|
+
if (!key.usages.includes('decapsulateBits')) {
|
|
2857
|
+
throw lazyDOMException(
|
|
2858
|
+
'Key does not have decapsulateBits usage',
|
|
2859
|
+
'InvalidAccessError',
|
|
2860
|
+
);
|
|
2206
2861
|
}
|
|
2207
2862
|
|
|
2208
|
-
return
|
|
2863
|
+
return this._decapsulateCore(algorithm, key, ciphertext);
|
|
2864
|
+
}
|
|
2865
|
+
|
|
2866
|
+
async decapsulateKey(
|
|
2867
|
+
algorithm: SubtleAlgorithm,
|
|
2868
|
+
key: CryptoKey,
|
|
2869
|
+
ciphertext: BufferLike,
|
|
2870
|
+
sharedKeyAlgorithm: SubtleAlgorithm | AnyAlgorithm,
|
|
2871
|
+
extractable: boolean,
|
|
2872
|
+
usages: KeyUsage[],
|
|
2873
|
+
): Promise<CryptoKey> {
|
|
2874
|
+
if (!key.usages.includes('decapsulateKey')) {
|
|
2875
|
+
throw lazyDOMException(
|
|
2876
|
+
'Key does not have decapsulateKey usage',
|
|
2877
|
+
'InvalidAccessError',
|
|
2878
|
+
);
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
const sharedKey = this._decapsulateCore(algorithm, key, ciphertext);
|
|
2882
|
+
return this.importKey(
|
|
2883
|
+
'raw',
|
|
2884
|
+
sharedKey,
|
|
2885
|
+
sharedKeyAlgorithm,
|
|
2886
|
+
extractable,
|
|
2887
|
+
usages,
|
|
2888
|
+
);
|
|
2209
2889
|
}
|
|
2210
2890
|
}
|
|
2211
2891
|
|
|
@@ -2228,6 +2908,11 @@ function getKeyLength(algorithm: SubtleAlgorithm): number {
|
|
|
2228
2908
|
return hmacAlg.length || 256;
|
|
2229
2909
|
}
|
|
2230
2910
|
|
|
2911
|
+
case 'KMAC128':
|
|
2912
|
+
return algorithm.length || 128;
|
|
2913
|
+
case 'KMAC256':
|
|
2914
|
+
return algorithm.length || 256;
|
|
2915
|
+
|
|
2231
2916
|
default:
|
|
2232
2917
|
throw lazyDOMException(
|
|
2233
2918
|
`Cannot determine key length for ${name}`,
|