react-native-quick-crypto 1.1.0 → 1.1.2
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/QuickCrypto.podspec +1 -0
- package/android/CMakeLists.txt +4 -0
- package/android/build.gradle +5 -1
- package/cpp/argon2/HybridArgon2.cpp +10 -3
- package/cpp/blake3/HybridBlake3.cpp +5 -3
- package/cpp/cipher/CCMCipher.cpp +35 -26
- package/cpp/cipher/CCMCipher.hpp +2 -4
- package/cpp/cipher/ChaCha20Cipher.cpp +19 -27
- package/cpp/cipher/ChaCha20Cipher.hpp +2 -4
- package/cpp/cipher/ChaCha20Poly1305Cipher.cpp +41 -36
- package/cpp/cipher/ChaCha20Poly1305Cipher.hpp +2 -4
- package/cpp/cipher/GCMCipher.cpp +17 -20
- package/cpp/cipher/HybridCipher.cpp +44 -47
- package/cpp/cipher/HybridCipher.hpp +17 -1
- package/cpp/cipher/HybridRsaCipher.cpp +93 -56
- package/cpp/cipher/OCBCipher.cpp +5 -5
- package/cpp/cipher/XChaCha20Poly1305Cipher.cpp +27 -32
- package/cpp/cipher/XSalsa20Cipher.cpp +78 -16
- package/cpp/cipher/XSalsa20Cipher.hpp +25 -3
- package/cpp/cipher/XSalsa20Poly1305Cipher.cpp +32 -41
- package/cpp/dh/HybridDiffieHellman.cpp +29 -0
- package/cpp/ec/HybridEcKeyPair.cpp +35 -33
- package/cpp/ec/HybridEcKeyPair.hpp +3 -7
- package/cpp/ecdh/HybridECDH.cpp +23 -0
- package/cpp/ed25519/HybridEdKeyPair.cpp +73 -117
- package/cpp/ed25519/HybridEdKeyPair.hpp +5 -9
- package/cpp/hash/HybridHash.cpp +5 -7
- package/cpp/hkdf/HybridHkdf.cpp +6 -4
- package/cpp/hmac/HybridHmac.cpp +4 -6
- package/cpp/keys/HybridKeyObjectHandle.cpp +630 -2
- package/cpp/keys/HybridKeyObjectHandle.hpp +21 -1
- package/cpp/kmac/HybridKmac.cpp +4 -4
- package/cpp/mldsa/HybridMlDsaKeyPair.cpp +37 -49
- package/cpp/mlkem/HybridMlKemKeyPair.cpp +39 -43
- package/cpp/pbkdf2/HybridPbkdf2.cpp +7 -8
- package/cpp/rsa/HybridRsaKeyPair.cpp +5 -8
- package/cpp/rsa/HybridRsaKeyPair.hpp +4 -7
- package/cpp/scrypt/HybridScrypt.cpp +6 -4
- package/cpp/sign/HybridSignHandle.cpp +47 -72
- package/cpp/sign/HybridVerifyHandle.cpp +47 -67
- package/cpp/slhdsa/HybridSlhDsaKeyPair.cpp +245 -0
- package/cpp/slhdsa/HybridSlhDsaKeyPair.hpp +48 -0
- package/cpp/turboshake/HybridTurboShake.cpp +379 -0
- package/cpp/turboshake/HybridTurboShake.hpp +28 -0
- package/cpp/utils/HybridUtils.cpp +195 -43
- package/cpp/utils/HybridUtils.hpp +9 -2
- package/cpp/utils/QuickCryptoUtils.hpp +72 -0
- package/deps/blake3/README.md +6 -7
- package/deps/blake3/c/blake3.c +3 -2
- package/deps/blake3/c/blake3.h +2 -2
- package/deps/blake3/c/blake3_dispatch.c +2 -2
- package/deps/blake3/c/blake3_impl.h +1 -1
- package/deps/blake3/c/blake3_neon.c +5 -4
- package/deps/ncrypto/include/ncrypto/version.h +2 -2
- package/deps/ncrypto/include/ncrypto.h +9 -2
- package/deps/ncrypto/src/ncrypto.cpp +130 -35
- package/lib/commonjs/argon2.js +51 -2
- package/lib/commonjs/argon2.js.map +1 -1
- package/lib/commonjs/cipher.js +109 -11
- package/lib/commonjs/cipher.js.map +1 -1
- package/lib/commonjs/dhKeyPair.js +3 -0
- package/lib/commonjs/dhKeyPair.js.map +1 -1
- package/lib/commonjs/dsa.js +11 -2
- package/lib/commonjs/dsa.js.map +1 -1
- package/lib/commonjs/ec.js +37 -30
- package/lib/commonjs/ec.js.map +1 -1
- package/lib/commonjs/ed.js +60 -6
- package/lib/commonjs/ed.js.map +1 -1
- package/lib/commonjs/hash.js +67 -10
- package/lib/commonjs/hash.js.map +1 -1
- package/lib/commonjs/hkdf.js +33 -6
- package/lib/commonjs/hkdf.js.map +1 -1
- package/lib/commonjs/hmac.js +15 -5
- package/lib/commonjs/hmac.js.map +1 -1
- package/lib/commonjs/keys/classes.js +33 -7
- package/lib/commonjs/keys/classes.js.map +1 -1
- package/lib/commonjs/keys/generateKeyPair.js +85 -4
- package/lib/commonjs/keys/generateKeyPair.js.map +1 -1
- package/lib/commonjs/keys/index.js +50 -2
- package/lib/commonjs/keys/index.js.map +1 -1
- package/lib/commonjs/keys/publicCipher.js +10 -4
- package/lib/commonjs/keys/publicCipher.js.map +1 -1
- package/lib/commonjs/keys/signVerify.js +9 -2
- package/lib/commonjs/keys/signVerify.js.map +1 -1
- package/lib/commonjs/keys/utils.js +59 -1
- package/lib/commonjs/keys/utils.js.map +1 -1
- package/lib/commonjs/random.js +74 -11
- package/lib/commonjs/random.js.map +1 -1
- package/lib/commonjs/rsa.js +15 -5
- package/lib/commonjs/rsa.js.map +1 -1
- package/lib/commonjs/scrypt.js +47 -6
- package/lib/commonjs/scrypt.js.map +1 -1
- package/lib/commonjs/slhdsa.js +70 -0
- package/lib/commonjs/slhdsa.js.map +1 -0
- package/lib/commonjs/specs/slhDsaKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/slhDsaKeyPair.nitro.js.map +1 -0
- package/lib/commonjs/specs/turboshake.nitro.js +6 -0
- package/lib/commonjs/specs/turboshake.nitro.js.map +1 -0
- package/lib/commonjs/subtle.js +975 -253
- package/lib/commonjs/subtle.js.map +1 -1
- package/lib/commonjs/utils/cipher.js +18 -7
- package/lib/commonjs/utils/cipher.js.map +1 -1
- package/lib/commonjs/utils/conversion.js +86 -28
- package/lib/commonjs/utils/conversion.js.map +1 -1
- package/lib/commonjs/utils/errors.js +63 -4
- package/lib/commonjs/utils/errors.js.map +1 -1
- package/lib/commonjs/utils/timingSafeEqual.js +7 -2
- package/lib/commonjs/utils/timingSafeEqual.js.map +1 -1
- package/lib/commonjs/utils/types.js.map +1 -1
- package/lib/commonjs/utils/validation.js +46 -0
- package/lib/commonjs/utils/validation.js.map +1 -1
- package/lib/commonjs/x509certificate.js +6 -6
- package/lib/commonjs/x509certificate.js.map +1 -1
- package/lib/module/argon2.js +51 -2
- package/lib/module/argon2.js.map +1 -1
- package/lib/module/cipher.js +109 -11
- package/lib/module/cipher.js.map +1 -1
- package/lib/module/dhKeyPair.js +3 -0
- package/lib/module/dhKeyPair.js.map +1 -1
- package/lib/module/dsa.js +11 -2
- package/lib/module/dsa.js.map +1 -1
- package/lib/module/ec.js +38 -31
- package/lib/module/ec.js.map +1 -1
- package/lib/module/ed.js +61 -7
- package/lib/module/ed.js.map +1 -1
- package/lib/module/hash.js +67 -10
- package/lib/module/hash.js.map +1 -1
- package/lib/module/hkdf.js +33 -6
- package/lib/module/hkdf.js.map +1 -1
- package/lib/module/hmac.js +15 -5
- package/lib/module/hmac.js.map +1 -1
- package/lib/module/keys/classes.js +31 -5
- package/lib/module/keys/classes.js.map +1 -1
- package/lib/module/keys/generateKeyPair.js +86 -5
- package/lib/module/keys/generateKeyPair.js.map +1 -1
- package/lib/module/keys/index.js +50 -2
- package/lib/module/keys/index.js.map +1 -1
- package/lib/module/keys/publicCipher.js +10 -4
- package/lib/module/keys/publicCipher.js.map +1 -1
- package/lib/module/keys/signVerify.js +9 -2
- package/lib/module/keys/signVerify.js.map +1 -1
- package/lib/module/keys/utils.js +57 -1
- package/lib/module/keys/utils.js.map +1 -1
- package/lib/module/random.js +74 -12
- package/lib/module/random.js.map +1 -1
- package/lib/module/rsa.js +14 -4
- package/lib/module/rsa.js.map +1 -1
- package/lib/module/scrypt.js +47 -6
- package/lib/module/scrypt.js.map +1 -1
- package/lib/module/slhdsa.js +64 -0
- package/lib/module/slhdsa.js.map +1 -0
- package/lib/module/specs/slhDsaKeyPair.nitro.js +4 -0
- package/lib/module/specs/slhDsaKeyPair.nitro.js.map +1 -0
- package/lib/module/specs/turboshake.nitro.js +4 -0
- package/lib/module/specs/turboshake.nitro.js.map +1 -0
- package/lib/module/subtle.js +976 -254
- package/lib/module/subtle.js.map +1 -1
- package/lib/module/utils/cipher.js +18 -7
- package/lib/module/utils/cipher.js.map +1 -1
- package/lib/module/utils/conversion.js +84 -28
- package/lib/module/utils/conversion.js.map +1 -1
- package/lib/module/utils/errors.js +61 -4
- package/lib/module/utils/errors.js.map +1 -1
- package/lib/module/utils/timingSafeEqual.js +8 -3
- package/lib/module/utils/timingSafeEqual.js.map +1 -1
- package/lib/module/utils/types.js.map +1 -1
- package/lib/module/utils/validation.js +44 -0
- package/lib/module/utils/validation.js.map +1 -1
- package/lib/module/x509certificate.js +6 -6
- package/lib/module/x509certificate.js.map +1 -1
- package/lib/typescript/argon2.d.ts.map +1 -1
- package/lib/typescript/cipher.d.ts +2 -2
- package/lib/typescript/cipher.d.ts.map +1 -1
- package/lib/typescript/dhKeyPair.d.ts.map +1 -1
- package/lib/typescript/dsa.d.ts.map +1 -1
- package/lib/typescript/ec.d.ts.map +1 -1
- package/lib/typescript/ed.d.ts.map +1 -1
- package/lib/typescript/hash.d.ts +2 -2
- package/lib/typescript/hash.d.ts.map +1 -1
- package/lib/typescript/hkdf.d.ts.map +1 -1
- package/lib/typescript/hmac.d.ts +2 -2
- package/lib/typescript/hmac.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +13 -8
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/keys/classes.d.ts +10 -1
- package/lib/typescript/keys/classes.d.ts.map +1 -1
- package/lib/typescript/keys/generateKeyPair.d.ts +12 -1
- package/lib/typescript/keys/generateKeyPair.d.ts.map +1 -1
- package/lib/typescript/keys/index.d.ts +3 -1
- package/lib/typescript/keys/index.d.ts.map +1 -1
- package/lib/typescript/keys/publicCipher.d.ts.map +1 -1
- package/lib/typescript/keys/signVerify.d.ts.map +1 -1
- package/lib/typescript/keys/utils.d.ts +21 -4
- package/lib/typescript/keys/utils.d.ts.map +1 -1
- package/lib/typescript/random.d.ts +5 -1
- package/lib/typescript/random.d.ts.map +1 -1
- package/lib/typescript/rsa.d.ts.map +1 -1
- package/lib/typescript/scrypt.d.ts.map +1 -1
- package/lib/typescript/slhdsa.d.ts +19 -0
- package/lib/typescript/slhdsa.d.ts.map +1 -0
- package/lib/typescript/specs/keyObjectHandle.nitro.d.ts +9 -0
- package/lib/typescript/specs/keyObjectHandle.nitro.d.ts.map +1 -1
- package/lib/typescript/specs/slhDsaKeyPair.nitro.d.ts +16 -0
- package/lib/typescript/specs/slhDsaKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/turboshake.nitro.d.ts +11 -0
- package/lib/typescript/specs/turboshake.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/utils.nitro.d.ts +0 -2
- package/lib/typescript/specs/utils.nitro.d.ts.map +1 -1
- package/lib/typescript/subtle.d.ts +3 -2
- package/lib/typescript/subtle.d.ts.map +1 -1
- package/lib/typescript/utils/cipher.d.ts +13 -1
- package/lib/typescript/utils/cipher.d.ts.map +1 -1
- package/lib/typescript/utils/conversion.d.ts +13 -9
- package/lib/typescript/utils/conversion.d.ts.map +1 -1
- package/lib/typescript/utils/errors.d.ts +12 -0
- package/lib/typescript/utils/errors.d.ts.map +1 -1
- package/lib/typescript/utils/timingSafeEqual.d.ts.map +1 -1
- package/lib/typescript/utils/types.d.ts +32 -15
- package/lib/typescript/utils/types.d.ts.map +1 -1
- package/lib/typescript/utils/validation.d.ts +3 -1
- package/lib/typescript/utils/validation.d.ts.map +1 -1
- package/lib/typescript/x509certificate.d.ts.map +1 -1
- package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +2 -0
- package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +20 -0
- package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +20 -0
- package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +48 -0
- package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.cpp +9 -0
- package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +9 -0
- package/nitrogen/generated/shared/c++/HybridSlhDsaKeyPairSpec.cpp +29 -0
- package/nitrogen/generated/shared/c++/HybridSlhDsaKeyPairSpec.hpp +72 -0
- package/nitrogen/generated/shared/c++/HybridTurboShakeSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridTurboShakeSpec.hpp +70 -0
- package/nitrogen/generated/shared/c++/HybridUtilsSpec.cpp +0 -2
- package/nitrogen/generated/shared/c++/HybridUtilsSpec.hpp +0 -3
- package/nitrogen/generated/shared/c++/JWK.hpp +9 -1
- package/nitrogen/generated/shared/c++/JWKkty.hpp +4 -0
- package/nitrogen/generated/shared/c++/KangarooTwelveVariant.hpp +76 -0
- package/nitrogen/generated/shared/c++/TurboShakeVariant.hpp +76 -0
- package/package.json +38 -7
- package/src/argon2.ts +80 -2
- package/src/cipher.ts +139 -15
- package/src/dhKeyPair.ts +8 -0
- package/src/dsa.ts +19 -2
- package/src/ec.ts +52 -29
- package/src/ed.ts +95 -16
- package/src/hash.ts +125 -12
- package/src/hkdf.ts +44 -6
- package/src/hmac.ts +17 -7
- package/src/keys/classes.ts +46 -5
- package/src/keys/generateKeyPair.ts +151 -5
- package/src/keys/index.ts +73 -3
- package/src/keys/publicCipher.ts +10 -4
- package/src/keys/signVerify.ts +13 -2
- package/src/keys/utils.ts +78 -5
- package/src/random.ts +104 -11
- package/src/rsa.ts +26 -4
- package/src/scrypt.ts +73 -6
- package/src/slhdsa.ts +146 -0
- package/src/specs/keyObjectHandle.nitro.ts +17 -0
- package/src/specs/slhDsaKeyPair.nitro.ts +29 -0
- package/src/specs/turboshake.nitro.ts +21 -0
- package/src/specs/utils.nitro.ts +0 -2
- package/src/subtle.ts +1246 -333
- package/src/utils/cipher.ts +30 -8
- package/src/utils/conversion.ts +129 -40
- package/src/utils/errors.ts +72 -4
- package/src/utils/timingSafeEqual.ts +8 -3
- package/src/utils/types.ts +80 -15
- package/src/utils/validation.ts +70 -1
- package/src/x509certificate.ts +5 -6
- package/deps/blake3/.cargo/config.toml +0 -2
- package/deps/blake3/.git-blame-ignore-revs +0 -2
- package/deps/blake3/.github/workflows/build_b3sum.py +0 -38
- package/deps/blake3/.github/workflows/ci.yml +0 -491
- package/deps/blake3/.github/workflows/tag.yml +0 -43
- package/deps/blake3/.github/workflows/upload_github_release_asset.py +0 -73
- package/deps/blake3/CONTRIBUTING.md +0 -31
- package/deps/blake3/Cargo.toml +0 -135
- package/deps/blake3/b3sum/Cargo.lock +0 -513
- package/deps/blake3/b3sum/Cargo.toml +0 -26
- package/deps/blake3/b3sum/README.md +0 -72
- package/deps/blake3/b3sum/src/main.rs +0 -564
- package/deps/blake3/b3sum/src/unit_tests.rs +0 -235
- package/deps/blake3/b3sum/tests/cli_tests.rs +0 -680
- package/deps/blake3/b3sum/what_does_check_do.md +0 -176
- package/deps/blake3/benches/bench.rs +0 -623
- package/deps/blake3/build.rs +0 -389
- package/deps/blake3/c/CMakeLists.txt +0 -383
- package/deps/blake3/c/CMakePresets.json +0 -73
- package/deps/blake3/c/Makefile.testing +0 -82
- package/deps/blake3/c/blake3-config.cmake.in +0 -14
- package/deps/blake3/c/blake3_avx2.c +0 -326
- package/deps/blake3/c/blake3_avx2_x86-64_unix.S +0 -1815
- package/deps/blake3/c/blake3_avx2_x86-64_windows_gnu.S +0 -1817
- package/deps/blake3/c/blake3_avx2_x86-64_windows_msvc.asm +0 -1828
- package/deps/blake3/c/blake3_avx512.c +0 -1388
- package/deps/blake3/c/blake3_avx512_x86-64_unix.S +0 -4824
- package/deps/blake3/c/blake3_avx512_x86-64_windows_gnu.S +0 -2615
- package/deps/blake3/c/blake3_avx512_x86-64_windows_msvc.asm +0 -2634
- package/deps/blake3/c/blake3_c_rust_bindings/Cargo.toml +0 -32
- package/deps/blake3/c/blake3_c_rust_bindings/README.md +0 -4
- package/deps/blake3/c/blake3_c_rust_bindings/benches/bench.rs +0 -477
- package/deps/blake3/c/blake3_c_rust_bindings/build.rs +0 -253
- package/deps/blake3/c/blake3_c_rust_bindings/cross_test.sh +0 -31
- package/deps/blake3/c/blake3_c_rust_bindings/src/lib.rs +0 -333
- package/deps/blake3/c/blake3_c_rust_bindings/src/test.rs +0 -696
- package/deps/blake3/c/blake3_sse2.c +0 -566
- package/deps/blake3/c/blake3_sse2_x86-64_unix.S +0 -2291
- package/deps/blake3/c/blake3_sse2_x86-64_windows_gnu.S +0 -2332
- package/deps/blake3/c/blake3_sse2_x86-64_windows_msvc.asm +0 -2350
- package/deps/blake3/c/blake3_sse41.c +0 -560
- package/deps/blake3/c/blake3_sse41_x86-64_unix.S +0 -2028
- package/deps/blake3/c/blake3_sse41_x86-64_windows_gnu.S +0 -2069
- package/deps/blake3/c/blake3_sse41_x86-64_windows_msvc.asm +0 -2089
- package/deps/blake3/c/blake3_tbb.cpp +0 -37
- package/deps/blake3/c/dependencies/CMakeLists.txt +0 -3
- package/deps/blake3/c/dependencies/tbb/CMakeLists.txt +0 -28
- package/deps/blake3/c/example.c +0 -36
- package/deps/blake3/c/example_tbb.c +0 -57
- package/deps/blake3/c/libblake3.pc.in +0 -12
- package/deps/blake3/c/main.c +0 -166
- package/deps/blake3/c/test.py +0 -97
- package/deps/blake3/media/B3.svg +0 -70
- package/deps/blake3/media/BLAKE3.svg +0 -85
- package/deps/blake3/media/speed.svg +0 -1474
- package/deps/blake3/reference_impl/Cargo.toml +0 -8
- package/deps/blake3/reference_impl/README.md +0 -14
- package/deps/blake3/reference_impl/reference_impl.rs +0 -374
- package/deps/blake3/src/ffi_avx2.rs +0 -65
- package/deps/blake3/src/ffi_avx512.rs +0 -169
- package/deps/blake3/src/ffi_neon.rs +0 -82
- package/deps/blake3/src/ffi_sse2.rs +0 -126
- package/deps/blake3/src/ffi_sse41.rs +0 -126
- package/deps/blake3/src/guts.rs +0 -60
- package/deps/blake3/src/hazmat.rs +0 -704
- package/deps/blake3/src/io.rs +0 -64
- package/deps/blake3/src/join.rs +0 -92
- package/deps/blake3/src/lib.rs +0 -1835
- package/deps/blake3/src/platform.rs +0 -587
- package/deps/blake3/src/portable.rs +0 -198
- package/deps/blake3/src/rust_avx2.rs +0 -474
- package/deps/blake3/src/rust_sse2.rs +0 -775
- package/deps/blake3/src/rust_sse41.rs +0 -766
- package/deps/blake3/src/test.rs +0 -1049
- package/deps/blake3/src/traits.rs +0 -227
- package/deps/blake3/src/wasm32_simd.rs +0 -794
- package/deps/blake3/test_vectors/Cargo.toml +0 -19
- package/deps/blake3/test_vectors/cross_test.sh +0 -25
- package/deps/blake3/test_vectors/src/bin/generate.rs +0 -4
- package/deps/blake3/test_vectors/src/lib.rs +0 -350
- package/deps/blake3/test_vectors/test_vectors.json +0 -217
- package/deps/blake3/tools/compiler_version/Cargo.toml +0 -7
- package/deps/blake3/tools/compiler_version/build.rs +0 -6
- package/deps/blake3/tools/compiler_version/src/main.rs +0 -27
- package/deps/blake3/tools/instruction_set_support/Cargo.toml +0 -6
- package/deps/blake3/tools/instruction_set_support/src/main.rs +0 -10
- package/deps/blake3/tools/release.md +0 -16
- package/deps/ncrypto/.bazelignore +0 -4
- package/deps/ncrypto/.bazelrc +0 -1
- package/deps/ncrypto/.bazelversion +0 -1
- package/deps/ncrypto/.clang-format +0 -111
- package/deps/ncrypto/.github/workflows/bazel.yml +0 -58
- package/deps/ncrypto/.github/workflows/commitlint.yml +0 -16
- package/deps/ncrypto/.github/workflows/linter.yml +0 -38
- package/deps/ncrypto/.github/workflows/macos.yml +0 -43
- package/deps/ncrypto/.github/workflows/release-please.yml +0 -16
- package/deps/ncrypto/.github/workflows/ubuntu.yml +0 -128
- package/deps/ncrypto/.github/workflows/visual-studio.yml +0 -49
- package/deps/ncrypto/.python-version +0 -1
- package/deps/ncrypto/.release-please-manifest.json +0 -3
- package/deps/ncrypto/BUILD.bazel +0 -44
- package/deps/ncrypto/CHANGELOG.md +0 -37
- package/deps/ncrypto/CMakeLists.txt +0 -79
- package/deps/ncrypto/MODULE.bazel +0 -16
- package/deps/ncrypto/MODULE.bazel.lock +0 -461
- package/deps/ncrypto/cmake/CPM.cmake +0 -1225
- package/deps/ncrypto/cmake/ncrypto-flags.cmake +0 -17
- package/deps/ncrypto/ncrypto.pc.in +0 -10
- package/deps/ncrypto/patches/0001-Expose-libdecrepit-so-NodeJS-can-use-it-for-ncrypto.patch +0 -28
- package/deps/ncrypto/pyproject.toml +0 -38
- package/deps/ncrypto/release-please-config.json +0 -11
- package/deps/ncrypto/src/CMakeLists.txt +0 -40
- package/deps/ncrypto/tests/BUILD.bazel +0 -11
- package/deps/ncrypto/tests/CMakeLists.txt +0 -7
- package/deps/ncrypto/tests/basic.cpp +0 -856
- package/deps/ncrypto/tools/run-clang-format.sh +0 -42
- package/deps/simdutf/.clang-format +0 -4
- package/deps/simdutf/.github/ISSUE_TEMPLATE/bug_report.md +0 -62
- package/deps/simdutf/.github/ISSUE_TEMPLATE/config.yml +0 -1
- package/deps/simdutf/.github/ISSUE_TEMPLATE/feature_request.md +0 -35
- package/deps/simdutf/.github/ISSUE_TEMPLATE/standard-issue-template.md +0 -29
- package/deps/simdutf/.github/pull_request_template.md +0 -51
- package/deps/simdutf/.github/workflows/aarch64.yml +0 -39
- package/deps/simdutf/.github/workflows/alpine.yml +0 -27
- package/deps/simdutf/.github/workflows/amalgamation_demos.yml +0 -34
- package/deps/simdutf/.github/workflows/armv7.yml +0 -32
- package/deps/simdutf/.github/workflows/atomic_fuzz.yml +0 -25
- package/deps/simdutf/.github/workflows/cifuzz.yml +0 -37
- package/deps/simdutf/.github/workflows/clangformat.yml +0 -36
- package/deps/simdutf/.github/workflows/debian-latestcxxstandards.yml +0 -40
- package/deps/simdutf/.github/workflows/debian.yml +0 -33
- package/deps/simdutf/.github/workflows/documentation.yml +0 -36
- package/deps/simdutf/.github/workflows/emscripten.yml +0 -19
- package/deps/simdutf/.github/workflows/loongarch64-gcc-14.2.yml +0 -39
- package/deps/simdutf/.github/workflows/macos-latest.yml +0 -29
- package/deps/simdutf/.github/workflows/msys2-clang.yml +0 -48
- package/deps/simdutf/.github/workflows/msys2.yml +0 -50
- package/deps/simdutf/.github/workflows/ppc64le.yml +0 -29
- package/deps/simdutf/.github/workflows/rvv-1024-clang-18.yml +0 -35
- package/deps/simdutf/.github/workflows/rvv-128-clang-17.yml +0 -35
- package/deps/simdutf/.github/workflows/rvv-256-gcc-14.yml +0 -31
- package/deps/simdutf/.github/workflows/s390x.yml +0 -29
- package/deps/simdutf/.github/workflows/selective-amalgamation.yml +0 -29
- package/deps/simdutf/.github/workflows/typos.yml +0 -19
- package/deps/simdutf/.github/workflows/ubuntu22-cxx20.yml +0 -30
- package/deps/simdutf/.github/workflows/ubuntu22.yml +0 -32
- package/deps/simdutf/.github/workflows/ubuntu22_gcc12.yml +0 -27
- package/deps/simdutf/.github/workflows/ubuntu22sani.yml +0 -29
- package/deps/simdutf/.github/workflows/ubuntu24-cxxstandards.yml +0 -34
- package/deps/simdutf/.github/workflows/ubuntu24-unsignedchar.yml +0 -34
- package/deps/simdutf/.github/workflows/ubuntu24.yml +0 -32
- package/deps/simdutf/.github/workflows/ubuntu24sani.yml +0 -36
- package/deps/simdutf/.github/workflows/ubuntu24sani_clang.yml +0 -29
- package/deps/simdutf/.github/workflows/vs17-arm-ci.yml +0 -21
- package/deps/simdutf/.github/workflows/vs17-ci-cxx20.yml +0 -41
- package/deps/simdutf/.github/workflows/vs17-ci.yml +0 -41
- package/deps/simdutf/.github/workflows/vs17-clang-ci.yml +0 -41
- package/deps/simdutf/.github/workflows/vs17-cxxstandards.yml +0 -36
- package/deps/simdutf/AI_USAGE_POLICY.md +0 -56
- package/deps/simdutf/AUTHORS +0 -6
- package/deps/simdutf/CMakeLists.txt +0 -231
- package/deps/simdutf/CONTRIBUTING.md +0 -214
- package/deps/simdutf/CONTRIBUTORS +0 -1
- package/deps/simdutf/Doxyfile +0 -2584
- package/deps/simdutf/Makefile.crosscompile +0 -54
- package/deps/simdutf/README-RVV.md +0 -16
- package/deps/simdutf/SECURITY.md +0 -8
- package/deps/simdutf/benchmarks/CMakeLists.txt +0 -101
- package/deps/simdutf/benchmarks/alignment.cpp +0 -150
- package/deps/simdutf/benchmarks/base64/CMakeLists.txt +0 -30
- package/deps/simdutf/benchmarks/base64/benchmark_base64.cpp +0 -875
- package/deps/simdutf/benchmarks/base64/libbase64_spaces.h +0 -49
- package/deps/simdutf/benchmarks/base64/node_base64.h +0 -227
- package/deps/simdutf/benchmarks/base64/openssl3_base64.h +0 -334
- package/deps/simdutf/benchmarks/benchmark.cpp +0 -65
- package/deps/simdutf/benchmarks/benchmark_to_well_formed_utf16.cpp +0 -347
- package/deps/simdutf/benchmarks/competition/.clang-format-ignore +0 -5
- package/deps/simdutf/benchmarks/competition/CppCon2018/utf_utils.cpp +0 -1276
- package/deps/simdutf/benchmarks/competition/CppCon2018/utf_utils.h +0 -595
- package/deps/simdutf/benchmarks/competition/README.md +0 -7
- package/deps/simdutf/benchmarks/competition/hoehrmann/hoehrmann.h +0 -91
- package/deps/simdutf/benchmarks/competition/inoue2008/inoue_utf8_to_utf16.h +0 -444
- package/deps/simdutf/benchmarks/competition/inoue2008/inoue_utf8_to_utf16_tables.h +0 -13183
- package/deps/simdutf/benchmarks/competition/inoue2008/script.py +0 -73
- package/deps/simdutf/benchmarks/competition/llvm/ConvertUTF.cpp +0 -738
- package/deps/simdutf/benchmarks/competition/llvm/ConvertUTF.h +0 -293
- package/deps/simdutf/benchmarks/competition/u8u16/COPYRIGHT +0 -8
- package/deps/simdutf/benchmarks/competition/u8u16/Makefile +0 -44
- package/deps/simdutf/benchmarks/competition/u8u16/OSL3.0.txt +0 -169
- package/deps/simdutf/benchmarks/competition/u8u16/Profiling/BOM_Profiler.h +0 -148
- package/deps/simdutf/benchmarks/competition/u8u16/Profiling/i386_timer.h +0 -45
- package/deps/simdutf/benchmarks/competition/u8u16/Profiling/ppc_timer.c +0 -34
- package/deps/simdutf/benchmarks/competition/u8u16/README +0 -56
- package/deps/simdutf/benchmarks/competition/u8u16/config/config_defs.h +0 -43
- package/deps/simdutf/benchmarks/competition/u8u16/config/g4_config.h +0 -27
- package/deps/simdutf/benchmarks/competition/u8u16/config/mmx_config.h +0 -16
- package/deps/simdutf/benchmarks/competition/u8u16/config/p4_config.h +0 -18
- package/deps/simdutf/benchmarks/competition/u8u16/config/p4_ideal_config.h +0 -16
- package/deps/simdutf/benchmarks/competition/u8u16/config/spu_config.h +0 -28
- package/deps/simdutf/benchmarks/competition/u8u16/config/ssse3_config.h +0 -20
- package/deps/simdutf/benchmarks/competition/u8u16/iconv_u8u16.c +0 -2
- package/deps/simdutf/benchmarks/competition/u8u16/lib/altivec_simd.h +0 -440
- package/deps/simdutf/benchmarks/competition/u8u16/lib/libgen/make_basic_ops.py +0 -121
- package/deps/simdutf/benchmarks/competition/u8u16/lib/libgen/make_half_operand_versions.py +0 -158
- package/deps/simdutf/benchmarks/competition/u8u16/lib/libgen/make_test.py +0 -270
- package/deps/simdutf/benchmarks/competition/u8u16/lib/mmx_simd.h +0 -141
- package/deps/simdutf/benchmarks/competition/u8u16/lib/mmx_simd_basic.h +0 -216
- package/deps/simdutf/benchmarks/competition/u8u16/lib/mmx_simd_built_in.h +0 -119
- package/deps/simdutf/benchmarks/competition/u8u16/lib/mmx_simd_modified.h +0 -2430
- package/deps/simdutf/benchmarks/competition/u8u16/lib/outline.txt +0 -39
- package/deps/simdutf/benchmarks/competition/u8u16/lib/spu_simd.h +0 -421
- package/deps/simdutf/benchmarks/competition/u8u16/lib/sse_simd.h +0 -836
- package/deps/simdutf/benchmarks/competition/u8u16/lib/stdint.h +0 -222
- package/deps/simdutf/benchmarks/competition/u8u16/libu8u16_BE.c +0 -4
- package/deps/simdutf/benchmarks/competition/u8u16/libu8u16_LE.c +0 -5
- package/deps/simdutf/benchmarks/competition/u8u16/proto/u8u16.py +0 -390
- package/deps/simdutf/benchmarks/competition/u8u16/src/Makefile +0 -18
- package/deps/simdutf/benchmarks/competition/u8u16/src/bytelex.h +0 -448
- package/deps/simdutf/benchmarks/competition/u8u16/src/charsets/ASCII_EBCDIC.h +0 -284
- package/deps/simdutf/benchmarks/competition/u8u16/src/libu8u16.c +0 -1975
- package/deps/simdutf/benchmarks/competition/u8u16/src/libu8u16.pdf +0 -0
- package/deps/simdutf/benchmarks/competition/u8u16/src/libu8u16.w +0 -2263
- package/deps/simdutf/benchmarks/competition/u8u16/src/multiliteral.h +0 -239
- package/deps/simdutf/benchmarks/competition/u8u16/src/u8u16.c +0 -232
- package/deps/simdutf/benchmarks/competition/u8u16/src/x8x16.c +0 -194
- package/deps/simdutf/benchmarks/competition/u8u16/src/xml_error.c +0 -193
- package/deps/simdutf/benchmarks/competition/u8u16/src/xml_error.h +0 -167
- package/deps/simdutf/benchmarks/competition/u8u16/src/xmldecl.c +0 -288
- package/deps/simdutf/benchmarks/competition/u8u16/src/xmldecl.h +0 -117
- package/deps/simdutf/benchmarks/competition/u8u16/u8u16_g4.c +0 -2
- package/deps/simdutf/benchmarks/competition/u8u16/u8u16_mmx.c +0 -2
- package/deps/simdutf/benchmarks/competition/u8u16/u8u16_p4.c +0 -3
- package/deps/simdutf/benchmarks/competition/u8u16/u8u16_p4_ideal.c +0 -2
- package/deps/simdutf/benchmarks/competition/u8u16/u8u16_spu.c +0 -2
- package/deps/simdutf/benchmarks/competition/u8u16/u8u16_ssse3.c +0 -3
- package/deps/simdutf/benchmarks/competition/u8u16/x8x16_p4.c +0 -2
- package/deps/simdutf/benchmarks/competition/utf8lut/LICENSE +0 -23
- package/deps/simdutf/benchmarks/competition/utf8lut/data/test_minimal.txt +0 -44
- package/deps/simdutf/benchmarks/competition/utf8lut/readme.md +0 -106
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_clang_corr_tests.cmd +0 -11
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_clang_corr_tests.sh +0 -13
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_corr_tests.sh +0 -13
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_example.sh +0 -13
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_file_conv.sh +0 -14
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_iconv_lib.sh +0 -11
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_iconv_sample.sh +0 -8
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_corr_tests.cmd +0 -12
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_example.cmd +0 -13
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_file_conv.cmd +0 -14
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_iconv_lib.cmd +0 -11
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_iconv_sample.cmd +0 -8
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_corr_tests.cmd +0 -11
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_example.cmd +0 -12
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_file_conv.cmd +0 -13
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_iconv_lib.cmd +0 -10
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_iconv_sample.cmd +0 -9
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/html_table.py +0 -25
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/measure.py +0 -94
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/resize.py +0 -20
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/wipe_all.cmd +0 -2
- package/deps/simdutf/benchmarks/competition/utf8lut/scripts/wipe_interm.cmd +0 -1
- package/deps/simdutf/benchmarks/competition/utf8lut/src/base/CustomMemcpy.h +0 -75
- package/deps/simdutf/benchmarks/competition/utf8lut/src/base/PerfDefs.h +0 -47
- package/deps/simdutf/benchmarks/competition/utf8lut/src/base/Timing.cpp +0 -17
- package/deps/simdutf/benchmarks/competition/utf8lut/src/base/Timing.h +0 -76
- package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/AllProcessors.cpp +0 -35
- package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/BaseBufferProcessor.cpp +0 -117
- package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/BaseBufferProcessor.h +0 -210
- package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/BufferDecoder.h +0 -158
- package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/BufferEncoder.h +0 -104
- package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/ProcessorPlugins.h +0 -334
- package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/ProcessorSelector.h +0 -186
- package/deps/simdutf/benchmarks/competition/utf8lut/src/core/DecoderLut.cpp +0 -140
- package/deps/simdutf/benchmarks/competition/utf8lut/src/core/DecoderLut.h +0 -42
- package/deps/simdutf/benchmarks/competition/utf8lut/src/core/DecoderProcess.h +0 -100
- package/deps/simdutf/benchmarks/competition/utf8lut/src/core/Dfa.h +0 -57
- package/deps/simdutf/benchmarks/competition/utf8lut/src/core/EncoderLut.cpp +0 -85
- package/deps/simdutf/benchmarks/competition/utf8lut/src/core/EncoderLut.h +0 -27
- package/deps/simdutf/benchmarks/competition/utf8lut/src/core/EncoderProcess.h +0 -126
- package/deps/simdutf/benchmarks/competition/utf8lut/src/core/ProcessTrivial.h +0 -108
- package/deps/simdutf/benchmarks/competition/utf8lut/src/iconv/iconv.cpp +0 -139
- package/deps/simdutf/benchmarks/competition/utf8lut/src/iconv/iconv.h +0 -74
- package/deps/simdutf/benchmarks/competition/utf8lut/src/message/MessageConverter.cpp +0 -65
- package/deps/simdutf/benchmarks/competition/utf8lut/src/message/MessageConverter.h +0 -91
- package/deps/simdutf/benchmarks/competition/utf8lut/src/tests/CorrectnessTests.cpp +0 -772
- package/deps/simdutf/benchmarks/competition/utf8lut/src/tests/Example.cpp +0 -12
- package/deps/simdutf/benchmarks/competition/utf8lut/src/tests/FileConverter.cpp +0 -486
- package/deps/simdutf/benchmarks/competition/utf8lut/src/tests/iconv_sample.c +0 -162
- package/deps/simdutf/benchmarks/competition/utf8lut/src/utf8lut.h +0 -15
- package/deps/simdutf/benchmarks/competition/utf8sse4/fromutf8-sse.cpp +0 -292
- package/deps/simdutf/benchmarks/competition/utfcpp/LICENSE +0 -23
- package/deps/simdutf/benchmarks/competition/utfcpp/README.md +0 -1503
- package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/checked.h +0 -335
- package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/core.h +0 -338
- package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/cpp11.h +0 -103
- package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/cpp17.h +0 -103
- package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/unchecked.h +0 -274
- package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8.h +0 -34
- package/deps/simdutf/benchmarks/dataset/README.md +0 -155
- package/deps/simdutf/benchmarks/dataset/emoji.txt +0 -204
- package/deps/simdutf/benchmarks/dataset/scripts/utf8type.py +0 -40
- package/deps/simdutf/benchmarks/dataset/wikipedia_mars/Makefile +0 -80
- package/deps/simdutf/benchmarks/dataset/wikipedia_mars/convert_to_utf6.py +0 -20
- package/deps/simdutf/benchmarks/find/CMakeLists.txt +0 -6
- package/deps/simdutf/benchmarks/find/findbenchmark.cpp +0 -63
- package/deps/simdutf/benchmarks/find/findbenchmarker.h +0 -46
- package/deps/simdutf/benchmarks/shortbench.cpp +0 -555
- package/deps/simdutf/benchmarks/src/CMakeLists.txt +0 -52
- package/deps/simdutf/benchmarks/src/apple_arm_events.h +0 -1104
- package/deps/simdutf/benchmarks/src/benchmark.cpp +0 -3899
- package/deps/simdutf/benchmarks/src/benchmark.h +0 -317
- package/deps/simdutf/benchmarks/src/benchmark_base.cpp +0 -144
- package/deps/simdutf/benchmarks/src/benchmark_base.h +0 -98
- package/deps/simdutf/benchmarks/src/cmdline.cpp +0 -176
- package/deps/simdutf/benchmarks/src/cmdline.h +0 -35
- package/deps/simdutf/benchmarks/src/event_counter.h +0 -162
- package/deps/simdutf/benchmarks/src/linux-perf-events.h +0 -104
- package/deps/simdutf/benchmarks/stream.cpp +0 -209
- package/deps/simdutf/benchmarks/threaded.cpp +0 -123
- package/deps/simdutf/cmake/CPM.cmake +0 -1363
- package/deps/simdutf/cmake/JoinPaths.cmake +0 -23
- package/deps/simdutf/cmake/add_cpp_test.cmake +0 -68
- package/deps/simdutf/cmake/simdutf-config.cmake.in +0 -2
- package/deps/simdutf/cmake/simdutf-flags.cmake +0 -26
- package/deps/simdutf/cmake/toolchains-ci/riscv64-linux-gnu.cmake +0 -4
- package/deps/simdutf/cmake/toolchains-dev/README.md +0 -32
- package/deps/simdutf/cmake/toolchains-dev/aarch64.cmake +0 -14
- package/deps/simdutf/cmake/toolchains-dev/loongarch64.cmake +0 -22
- package/deps/simdutf/cmake/toolchains-dev/powerpc64.cmake +0 -16
- package/deps/simdutf/cmake/toolchains-dev/powerpc64le.cmake +0 -16
- package/deps/simdutf/cmake/toolchains-dev/riscv64.cmake +0 -16
- package/deps/simdutf/cmake/toolchains-dev/rvv-spike.cmake +0 -38
- package/deps/simdutf/doc/avx512.png +0 -0
- package/deps/simdutf/doc/logo.png +0 -0
- package/deps/simdutf/doc/logo.svg +0 -165
- package/deps/simdutf/doc/node2023.png +0 -0
- package/deps/simdutf/doc/shortinput.md +0 -78
- package/deps/simdutf/doc/utf16utf8.png +0 -0
- package/deps/simdutf/doc/utf8utf16.png +0 -0
- package/deps/simdutf/doc/widelogo.png +0 -0
- package/deps/simdutf/doxygen.py +0 -50
- package/deps/simdutf/fuzz/.clang-format +0 -9
- package/deps/simdutf/fuzz/CMakeLists.txt +0 -45
- package/deps/simdutf/fuzz/README.md +0 -168
- package/deps/simdutf/fuzz/atomic_base64.cpp +0 -448
- package/deps/simdutf/fuzz/base64.cpp +0 -278
- package/deps/simdutf/fuzz/build.sh +0 -83
- package/deps/simdutf/fuzz/conversion.cpp +0 -669
- package/deps/simdutf/fuzz/helpers/.clang-format-ignore +0 -1
- package/deps/simdutf/fuzz/helpers/common.h +0 -135
- package/deps/simdutf/fuzz/helpers/nameof.hpp +0 -1258
- package/deps/simdutf/fuzz/main.cpp +0 -72
- package/deps/simdutf/fuzz/minimize_and_cleanse.sh +0 -87
- package/deps/simdutf/fuzz/misc.cpp +0 -216
- package/deps/simdutf/fuzz/random_fuzz.sh +0 -154
- package/deps/simdutf/fuzz/roundtrip.cpp +0 -588
- package/deps/simdutf/fuzz/safe_conversion.cpp +0 -104
- package/deps/simdutf/riscv/Dockerfile +0 -16
- package/deps/simdutf/riscv/README.md +0 -24
- package/deps/simdutf/riscv/remove-docker-station +0 -8
- package/deps/simdutf/riscv/run-docker-station +0 -31
- package/deps/simdutf/scripts/.flake8 +0 -2
- package/deps/simdutf/scripts/Makefile +0 -2
- package/deps/simdutf/scripts/README_ADD_FUNCTION.md +0 -49
- package/deps/simdutf/scripts/add_function.py +0 -330
- package/deps/simdutf/scripts/amalgamation_tests.py +0 -156
- package/deps/simdutf/scripts/base64/Makefile +0 -2
- package/deps/simdutf/scripts/base64/README.md +0 -2
- package/deps/simdutf/scripts/base64/avx512.py +0 -76
- package/deps/simdutf/scripts/base64/neon_decode.py +0 -143
- package/deps/simdutf/scripts/base64/neon_generate_lut.py +0 -101
- package/deps/simdutf/scripts/base64/sse.py +0 -252
- package/deps/simdutf/scripts/base64/sseregular.py +0 -160
- package/deps/simdutf/scripts/base64/sseurl.py +0 -283
- package/deps/simdutf/scripts/base64/table.py +0 -59
- package/deps/simdutf/scripts/base64bench_print.py +0 -145
- package/deps/simdutf/scripts/benchmark-all.py +0 -119
- package/deps/simdutf/scripts/benchmark_print.py +0 -324
- package/deps/simdutf/scripts/check_feature_macros.py +0 -156
- package/deps/simdutf/scripts/check_typos.sh +0 -13
- package/deps/simdutf/scripts/clang_format.sh +0 -35
- package/deps/simdutf/scripts/clang_format_docker.sh +0 -38
- package/deps/simdutf/scripts/common.py +0 -24
- package/deps/simdutf/scripts/compilation_benchmark.py +0 -55
- package/deps/simdutf/scripts/compile_many_variations.sh +0 -64
- package/deps/simdutf/scripts/create_latex_table.py +0 -62
- package/deps/simdutf/scripts/docker/Dockerfile +0 -14
- package/deps/simdutf/scripts/docker/Makefile +0 -9
- package/deps/simdutf/scripts/docker/README.md +0 -30
- package/deps/simdutf/scripts/docker/llvm.gpg +0 -0
- package/deps/simdutf/scripts/ppc64_convert_utf16_to_utf8.py +0 -155
- package/deps/simdutf/scripts/prepare_doxygen.sh +0 -21
- package/deps/simdutf/scripts/release.py +0 -197
- package/deps/simdutf/scripts/shortinputplots.py +0 -97
- package/deps/simdutf/scripts/sse_convert_utf16_to_utf8.py +0 -422
- package/deps/simdutf/scripts/sse_convert_utf32_to_utf16.py +0 -105
- package/deps/simdutf/scripts/sse_utf8_utf16_decode.py +0 -186
- package/deps/simdutf/scripts/sse_validate_utf16le_proof.py +0 -137
- package/deps/simdutf/scripts/sse_validate_utf16le_testcases.py +0 -129
- package/deps/simdutf/scripts/table.py +0 -207
- package/deps/simdutf/scripts/tests/new.txt +0 -33
- package/deps/simdutf/scripts/tests/old.txt +0 -33
- package/deps/simdutf/scripts/tests/results.txt +0 -272
- package/deps/simdutf/simdutf.pc.in +0 -11
- package/deps/simdutf/singleheader/.flake8 +0 -2
- package/deps/simdutf/singleheader/CMakeLists.txt +0 -64
- package/deps/simdutf/singleheader/README-dev.md +0 -81
- package/deps/simdutf/singleheader/README.md +0 -19
- package/deps/simdutf/singleheader/amalgamate.py +0 -513
- package/deps/simdutf/singleheader/amalgamation_demo.c +0 -59
- package/deps/simdutf/singleheader/amalgamation_demo.cpp +0 -54
- package/deps/simdutf/singleheader/test-features.py +0 -262
- package/deps/simdutf/src/CMakeLists.txt +0 -78
- package/deps/simdutf/tests/CMakeLists.txt +0 -483
- package/deps/simdutf/tests/atomic_base64_tests.cpp +0 -2845
- package/deps/simdutf/tests/base64_tests.cpp +0 -3617
- package/deps/simdutf/tests/basic_fuzzer.cpp +0 -805
- package/deps/simdutf/tests/bele_tests.cpp +0 -182
- package/deps/simdutf/tests/constexpr_base64_tests.cpp +0 -387
- package/deps/simdutf/tests/convert_latin1_to_utf16be_tests.cpp +0 -52
- package/deps/simdutf/tests/convert_latin1_to_utf16le_tests.cpp +0 -80
- package/deps/simdutf/tests/convert_latin1_to_utf32_tests.cpp +0 -66
- package/deps/simdutf/tests/convert_latin1_to_utf8_tests.cpp +0 -120
- package/deps/simdutf/tests/convert_utf16_to_utf8_safe_tests.cpp +0 -203
- package/deps/simdutf/tests/convert_utf16_to_utf8_with_replacement_tests.cpp +0 -276
- package/deps/simdutf/tests/convert_utf16be_to_latin1_tests.cpp +0 -109
- package/deps/simdutf/tests/convert_utf16be_to_latin1_tests_with_errors.cpp +0 -136
- package/deps/simdutf/tests/convert_utf16be_to_utf32_tests.cpp +0 -193
- package/deps/simdutf/tests/convert_utf16be_to_utf32_with_errors_tests.cpp +0 -381
- package/deps/simdutf/tests/convert_utf16be_to_utf8_tests.cpp +0 -259
- package/deps/simdutf/tests/convert_utf16be_to_utf8_with_errors_tests.cpp +0 -266
- package/deps/simdutf/tests/convert_utf16le_to_latin1_tests.cpp +0 -148
- package/deps/simdutf/tests/convert_utf16le_to_latin1_tests_with_errors.cpp +0 -176
- package/deps/simdutf/tests/convert_utf16le_to_utf32_tests.cpp +0 -213
- package/deps/simdutf/tests/convert_utf16le_to_utf32_with_errors_tests.cpp +0 -318
- package/deps/simdutf/tests/convert_utf16le_to_utf8_tests.cpp +0 -343
- package/deps/simdutf/tests/convert_utf16le_to_utf8_with_errors_tests.cpp +0 -271
- package/deps/simdutf/tests/convert_utf32_to_latin1_tests.cpp +0 -111
- package/deps/simdutf/tests/convert_utf32_to_latin1_with_errors_tests.cpp +0 -96
- package/deps/simdutf/tests/convert_utf32_to_utf16be_tests.cpp +0 -148
- package/deps/simdutf/tests/convert_utf32_to_utf16be_with_errors_tests.cpp +0 -192
- package/deps/simdutf/tests/convert_utf32_to_utf16le_tests.cpp +0 -166
- package/deps/simdutf/tests/convert_utf32_to_utf16le_with_errors_tests.cpp +0 -215
- package/deps/simdutf/tests/convert_utf32_to_utf8_tests.cpp +0 -181
- package/deps/simdutf/tests/convert_utf32_to_utf8_with_errors_tests.cpp +0 -261
- package/deps/simdutf/tests/convert_utf8_to_latin1_tests.cpp +0 -516
- package/deps/simdutf/tests/convert_utf8_to_latin1_with_errors_tests.cpp +0 -579
- package/deps/simdutf/tests/convert_utf8_to_utf16be_tests.cpp +0 -412
- package/deps/simdutf/tests/convert_utf8_to_utf16be_with_errors_tests.cpp +0 -480
- package/deps/simdutf/tests/convert_utf8_to_utf16le_tests.cpp +0 -671
- package/deps/simdutf/tests/convert_utf8_to_utf16le_with_errors_tests.cpp +0 -455
- package/deps/simdutf/tests/convert_utf8_to_utf32_tests.cpp +0 -1204
- package/deps/simdutf/tests/convert_utf8_to_utf32_with_errors_tests.cpp +0 -337
- package/deps/simdutf/tests/convert_valid_utf16be_to_latin1_tests.cpp +0 -37
- package/deps/simdutf/tests/convert_valid_utf16be_to_utf32_tests.cpp +0 -97
- package/deps/simdutf/tests/convert_valid_utf16be_to_utf8_tests.cpp +0 -126
- package/deps/simdutf/tests/convert_valid_utf16le_to_latin1_tests.cpp +0 -71
- package/deps/simdutf/tests/convert_valid_utf16le_to_utf32_tests.cpp +0 -122
- package/deps/simdutf/tests/convert_valid_utf16le_to_utf8_tests.cpp +0 -244
- package/deps/simdutf/tests/convert_valid_utf32_to_latin1_tests.cpp +0 -49
- package/deps/simdutf/tests/convert_valid_utf32_to_utf16be_tests.cpp +0 -92
- package/deps/simdutf/tests/convert_valid_utf32_to_utf16le_tests.cpp +0 -114
- package/deps/simdutf/tests/convert_valid_utf32_to_utf8_tests.cpp +0 -109
- package/deps/simdutf/tests/convert_valid_utf8_to_latin1_tests.cpp +0 -84
- package/deps/simdutf/tests/convert_valid_utf8_to_utf16be_tests.cpp +0 -124
- package/deps/simdutf/tests/convert_valid_utf8_to_utf16le_tests.cpp +0 -221
- package/deps/simdutf/tests/convert_valid_utf8_to_utf32_tests.cpp +0 -155
- package/deps/simdutf/tests/count_utf16be.cpp +0 -64
- package/deps/simdutf/tests/count_utf16le.cpp +0 -61
- package/deps/simdutf/tests/count_utf8.cpp +0 -87
- package/deps/simdutf/tests/detect_encodings_tests.cpp +0 -312
- package/deps/simdutf/tests/embed/valid_utf8.txt +0 -1
- package/deps/simdutf/tests/embed_tests.cpp +0 -22
- package/deps/simdutf/tests/find_tests.cpp +0 -77
- package/deps/simdutf/tests/fixed_string_tests.cpp +0 -153
- package/deps/simdutf/tests/helpers/CMakeLists.txt +0 -25
- package/deps/simdutf/tests/helpers/compiletime_conversions.h +0 -222
- package/deps/simdutf/tests/helpers/fixed_string.h +0 -267
- package/deps/simdutf/tests/helpers/random_int.cpp +0 -30
- package/deps/simdutf/tests/helpers/random_int.h +0 -39
- package/deps/simdutf/tests/helpers/random_utf16.cpp +0 -123
- package/deps/simdutf/tests/helpers/random_utf16.h +0 -52
- package/deps/simdutf/tests/helpers/random_utf32.cpp +0 -41
- package/deps/simdutf/tests/helpers/random_utf32.h +0 -40
- package/deps/simdutf/tests/helpers/random_utf8.cpp +0 -93
- package/deps/simdutf/tests/helpers/random_utf8.h +0 -36
- package/deps/simdutf/tests/helpers/test.cpp +0 -231
- package/deps/simdutf/tests/helpers/test.h +0 -193
- package/deps/simdutf/tests/helpers/transcode_test_base.cpp +0 -1257
- package/deps/simdutf/tests/helpers/transcode_test_base.h +0 -683
- package/deps/simdutf/tests/helpers/utf16.h +0 -27
- package/deps/simdutf/tests/installation_tests/find/CMakeLists.txt +0 -43
- package/deps/simdutf/tests/installation_tests/from_fetch/CMakeLists.txt +0 -47
- package/deps/simdutf/tests/internal_tests.cpp +0 -27
- package/deps/simdutf/tests/null_safety_tests.cpp +0 -94
- package/deps/simdutf/tests/random_fuzzer.cpp +0 -779
- package/deps/simdutf/tests/readme_tests.cpp +0 -274
- package/deps/simdutf/tests/reference/CMakeLists.txt +0 -23
- package/deps/simdutf/tests/reference/decode_utf16.h +0 -81
- package/deps/simdutf/tests/reference/decode_utf32.h +0 -47
- package/deps/simdutf/tests/reference/encode_latin1.cpp +0 -1
- package/deps/simdutf/tests/reference/encode_latin1.h +0 -32
- package/deps/simdutf/tests/reference/encode_utf16.cpp +0 -49
- package/deps/simdutf/tests/reference/encode_utf16.h +0 -20
- package/deps/simdutf/tests/reference/encode_utf32.cpp +0 -1
- package/deps/simdutf/tests/reference/encode_utf32.h +0 -36
- package/deps/simdutf/tests/reference/encode_utf8.cpp +0 -1
- package/deps/simdutf/tests/reference/encode_utf8.h +0 -40
- package/deps/simdutf/tests/reference/validate_utf16.cpp +0 -60
- package/deps/simdutf/tests/reference/validate_utf16.h +0 -14
- package/deps/simdutf/tests/reference/validate_utf16_to_latin1.cpp +0 -35
- package/deps/simdutf/tests/reference/validate_utf16_to_latin1.h +0 -13
- package/deps/simdutf/tests/reference/validate_utf32.cpp +0 -27
- package/deps/simdutf/tests/reference/validate_utf32.h +0 -12
- package/deps/simdutf/tests/reference/validate_utf32_to_latin1.cpp +0 -27
- package/deps/simdutf/tests/reference/validate_utf32_to_latin1.h +0 -12
- package/deps/simdutf/tests/reference/validate_utf8.cpp +0 -82
- package/deps/simdutf/tests/reference/validate_utf8.h +0 -11
- package/deps/simdutf/tests/reference/validate_utf8_to_latin1.cpp +0 -43
- package/deps/simdutf/tests/reference/validate_utf8_to_latin1.h +0 -12
- package/deps/simdutf/tests/select_implementation.cpp +0 -43
- package/deps/simdutf/tests/simdutf_c_tests.cpp +0 -244
- package/deps/simdutf/tests/span_tests.cpp +0 -401
- package/deps/simdutf/tests/special_tests.cpp +0 -559
- package/deps/simdutf/tests/straight_c_test.c +0 -187
- package/deps/simdutf/tests/text_encoding_tests.cpp +0 -77
- package/deps/simdutf/tests/to_well_formed_utf16_tests.cpp +0 -377
- package/deps/simdutf/tests/utf8_length_from_utf16_tests.cpp +0 -202
- package/deps/simdutf/tests/validate_ascii_basic_tests.cpp +0 -165
- package/deps/simdutf/tests/validate_ascii_with_errors_tests.cpp +0 -77
- package/deps/simdutf/tests/validate_utf16be_basic_tests.cpp +0 -175
- package/deps/simdutf/tests/validate_utf16be_with_errors_tests.cpp +0 -188
- package/deps/simdutf/tests/validate_utf16le_basic_tests.cpp +0 -268
- package/deps/simdutf/tests/validate_utf16le_with_errors_tests.cpp +0 -274
- package/deps/simdutf/tests/validate_utf32_basic_tests.cpp +0 -92
- package/deps/simdutf/tests/validate_utf32_with_errors_tests.cpp +0 -114
- package/deps/simdutf/tests/validate_utf8_basic_tests.cpp +0 -178
- package/deps/simdutf/tests/validate_utf8_brute_force_tests.cpp +0 -88
- package/deps/simdutf/tests/validate_utf8_puzzler_tests.cpp +0 -33
- package/deps/simdutf/tests/validate_utf8_with_errors_tests.cpp +0 -228
- package/deps/simdutf/tools/CMakeLists.txt +0 -85
- package/deps/simdutf/tools/fastbase64.cpp +0 -250
- package/deps/simdutf/tools/sutf.cpp +0 -556
- package/deps/simdutf/tools/sutf.h +0 -40
- package/lib/tsconfig.tsbuildinfo +0 -1
package/src/subtle.ts
CHANGED
|
@@ -18,7 +18,8 @@ import type {
|
|
|
18
18
|
RsaOaepParams,
|
|
19
19
|
ChaCha20Poly1305Params,
|
|
20
20
|
} from './utils';
|
|
21
|
-
import { KFormatType, KeyEncoding, KeyType } from './utils';
|
|
21
|
+
import { KFormatType, KeyEncoding, KeyType, kNamedCurveAliases } from './utils';
|
|
22
|
+
import { Buffer } from '@craftzdog/react-native-buffer';
|
|
22
23
|
import {
|
|
23
24
|
CryptoKey,
|
|
24
25
|
KeyObject,
|
|
@@ -31,7 +32,10 @@ import { bufferLikeToArrayBuffer } from './utils/conversion';
|
|
|
31
32
|
import { argon2Sync } from './argon2';
|
|
32
33
|
import { lazyDOMException } from './utils/errors';
|
|
33
34
|
import { normalizeHashName, HashContext } from './utils/hashnames';
|
|
34
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
validateJwkStructure,
|
|
37
|
+
validateMaxBufferLength,
|
|
38
|
+
} from './utils/validation';
|
|
35
39
|
import { asyncDigest } from './hash';
|
|
36
40
|
import { createSecretKey, createPublicKey } from './keys';
|
|
37
41
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
@@ -58,6 +62,11 @@ import {
|
|
|
58
62
|
Ed,
|
|
59
63
|
} from './ed';
|
|
60
64
|
import { mldsa_generateKeyPairWebCrypto, type MlDsaVariant } from './mldsa';
|
|
65
|
+
import {
|
|
66
|
+
slhdsa_generateKeyPairWebCrypto,
|
|
67
|
+
SLH_DSA_VARIANTS,
|
|
68
|
+
type SlhDsaVariant,
|
|
69
|
+
} from './slhdsa';
|
|
61
70
|
import {
|
|
62
71
|
mlkem_generateKeyPairWebCrypto,
|
|
63
72
|
type MlKemVariant,
|
|
@@ -83,12 +92,55 @@ function hasAnyNotIn(usages: KeyUsage[], allowed: KeyUsage[]): boolean {
|
|
|
83
92
|
return usages.some(usage => !allowed.includes(usage));
|
|
84
93
|
}
|
|
85
94
|
|
|
95
|
+
// Mirrors webidl.requiredArguments. Node throws TypeError when a SubtleCrypto
|
|
96
|
+
// method is called with fewer than the spec-required number of arguments
|
|
97
|
+
// (webcrypto.js:866 etc.); we relied on TypeScript types alone, which apps
|
|
98
|
+
// catching `instanceof TypeError` could not see at runtime.
|
|
99
|
+
function requireArgs(actual: number, required: number, method: string): void {
|
|
100
|
+
if (actual < required) {
|
|
101
|
+
throw new TypeError(
|
|
102
|
+
`Failed to execute '${method}' on 'SubtleCrypto': ${required} arguments required, but only ${actual} present.`,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// WebCrypto §18.4.4: algorithm name lookup is case-insensitive, but the
|
|
108
|
+
// canonical mixed-case form is preserved in the resulting `name` field
|
|
109
|
+
// (e.g. "aes-gcm" → "AES-GCM"). This map is built lazily on first call so
|
|
110
|
+
// the registry of canonical names below can stay declared after the
|
|
111
|
+
// function. Without this, callers who pass lowercase strings bypass the
|
|
112
|
+
// downstream `SUPPORTED_ALGORITHMS` set comparisons silently.
|
|
113
|
+
//
|
|
114
|
+
// The map's value type is `AnyAlgorithm` so callers can use the lookup
|
|
115
|
+
// result directly without re-asserting. The `as AnyAlgorithm` at insertion
|
|
116
|
+
// is the single contract boundary: every name in `SUPPORTED_ALGORITHMS` is
|
|
117
|
+
// already a member of `AnyAlgorithm` by construction.
|
|
118
|
+
let _canonicalAlgorithmNames: Map<string, AnyAlgorithm> | null = null;
|
|
119
|
+
function getCanonicalAlgorithmNames(): Map<string, AnyAlgorithm> {
|
|
120
|
+
if (_canonicalAlgorithmNames === null) {
|
|
121
|
+
const map = new Map<string, AnyAlgorithm>();
|
|
122
|
+
for (const set of Object.values(SUPPORTED_ALGORITHMS)) {
|
|
123
|
+
if (!set) continue;
|
|
124
|
+
for (const name of set) {
|
|
125
|
+
map.set(name.toLowerCase(), name as AnyAlgorithm);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
_canonicalAlgorithmNames = map;
|
|
129
|
+
}
|
|
130
|
+
return _canonicalAlgorithmNames;
|
|
131
|
+
}
|
|
132
|
+
|
|
86
133
|
function normalizeAlgorithm(
|
|
87
134
|
algorithm: SubtleAlgorithm | AnyAlgorithm,
|
|
88
135
|
_operation: Operation,
|
|
89
136
|
): SubtleAlgorithm {
|
|
137
|
+
const map = getCanonicalAlgorithmNames();
|
|
90
138
|
if (typeof algorithm === 'string') {
|
|
91
|
-
return { name: algorithm };
|
|
139
|
+
return { name: map.get(algorithm.toLowerCase()) ?? algorithm };
|
|
140
|
+
}
|
|
141
|
+
if (typeof algorithm.name === 'string') {
|
|
142
|
+
const canonical = map.get(algorithm.name.toLowerCase()) ?? algorithm.name;
|
|
143
|
+
return { ...algorithm, name: canonical };
|
|
92
144
|
}
|
|
93
145
|
return algorithm as SubtleAlgorithm;
|
|
94
146
|
}
|
|
@@ -112,15 +164,70 @@ function getAlgorithmName(name: string, length: number): string {
|
|
|
112
164
|
}
|
|
113
165
|
}
|
|
114
166
|
|
|
115
|
-
//
|
|
167
|
+
// Mirrors Node's aliasKeyFormat (lib/internal/crypto/webcrypto.js): for
|
|
168
|
+
// algorithms whose import/export accepts both 'raw' and the disambiguated
|
|
169
|
+
// 'raw-secret' / 'raw-public', collapse the latter to 'raw'. Used per-algorithm
|
|
170
|
+
// — algorithms that demand the disambiguated form (KMAC, AES-OCB,
|
|
171
|
+
// ChaCha20-Poly1305, Argon2*, ML-DSA, ML-KEM) MUST NOT alias.
|
|
172
|
+
function aliasKeyFormat(format: ImportFormat): ImportFormat {
|
|
173
|
+
if (format === 'raw-secret' || format === 'raw-public') return 'raw';
|
|
174
|
+
return format;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const kUncompressedSpkiLength: Record<string, number> = {
|
|
178
|
+
'P-256': 91,
|
|
179
|
+
'P-384': 120,
|
|
180
|
+
'P-521': 158,
|
|
181
|
+
};
|
|
182
|
+
|
|
116
183
|
function ecExportKey(key: CryptoKey, format: KWebCryptoKeyFormat): ArrayBuffer {
|
|
117
184
|
const keyObject = key.keyObject;
|
|
118
185
|
|
|
119
186
|
if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatRaw) {
|
|
120
187
|
return bufferLikeToArrayBuffer(keyObject.handle.exportKey());
|
|
121
188
|
} else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI) {
|
|
122
|
-
const exported =
|
|
123
|
-
|
|
189
|
+
const exported = bufferLikeToArrayBuffer(
|
|
190
|
+
keyObject.export({ format: 'der', type: 'spki' }),
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
// WebCrypto requires uncompressed point format for SPKI exports.
|
|
194
|
+
// If the key was imported in compressed form, re-export as uncompressed
|
|
195
|
+
// by reconstructing the point from the JWK x,y coordinates and
|
|
196
|
+
// round-tripping through initECRaw.
|
|
197
|
+
const namedCurve = key.algorithm.namedCurve;
|
|
198
|
+
const expected =
|
|
199
|
+
namedCurve === undefined
|
|
200
|
+
? undefined
|
|
201
|
+
: kUncompressedSpkiLength[namedCurve];
|
|
202
|
+
if (expected !== undefined && exported.byteLength !== expected) {
|
|
203
|
+
const jwk = keyObject.handle.exportJwk({}, false);
|
|
204
|
+
if (!jwk.x || !jwk.y) {
|
|
205
|
+
throw lazyDOMException(
|
|
206
|
+
'Failed to re-export EC public key as uncompressed SPKI',
|
|
207
|
+
'OperationError',
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
const x = Buffer.from(jwk.x, 'base64url');
|
|
211
|
+
const y = Buffer.from(jwk.y, 'base64url');
|
|
212
|
+
const raw = new Uint8Array(1 + x.length + y.length);
|
|
213
|
+
raw[0] = 0x04;
|
|
214
|
+
raw.set(x, 1);
|
|
215
|
+
raw.set(y, 1 + x.length);
|
|
216
|
+
const tmp =
|
|
217
|
+
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
218
|
+
const curveAlias =
|
|
219
|
+
kNamedCurveAliases[namedCurve as keyof typeof kNamedCurveAliases];
|
|
220
|
+
if (!tmp.initECRaw(curveAlias, raw.buffer as ArrayBuffer)) {
|
|
221
|
+
throw lazyDOMException(
|
|
222
|
+
'Failed to re-export EC public key as uncompressed SPKI',
|
|
223
|
+
'OperationError',
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
return bufferLikeToArrayBuffer(
|
|
227
|
+
tmp.exportKey(KFormatType.DER, KeyEncoding.SPKI),
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
return exported;
|
|
124
231
|
} else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatPKCS8) {
|
|
125
232
|
const exported = keyObject.export({ format: 'der', type: 'pkcs8' });
|
|
126
233
|
return bufferLikeToArrayBuffer(exported);
|
|
@@ -749,13 +856,22 @@ function kmacSignVerify(
|
|
|
749
856
|
): ArrayBuffer | boolean {
|
|
750
857
|
const { name } = algorithm;
|
|
751
858
|
|
|
752
|
-
|
|
753
|
-
|
|
859
|
+
// KmacParams.outputLength is required per
|
|
860
|
+
// https://wicg.github.io/webcrypto-modern-algos/#KmacParams-dictionary
|
|
861
|
+
// and the rename from `length` (commit ab8dc2b84c2). Mirror Node's
|
|
862
|
+
// mac.js:213-223 by reading `outputLength` (in bits).
|
|
863
|
+
if (typeof algorithm.outputLength !== 'number') {
|
|
864
|
+
throw lazyDOMException(
|
|
865
|
+
`${name}Params.outputLength is required`,
|
|
866
|
+
'OperationError',
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
const outputLengthBits = algorithm.outputLength;
|
|
754
870
|
|
|
755
871
|
if (outputLengthBits % 8 !== 0) {
|
|
756
872
|
throw lazyDOMException(
|
|
757
|
-
|
|
758
|
-
'
|
|
873
|
+
`Unsupported ${name}Params outputLength`,
|
|
874
|
+
'NotSupportedError',
|
|
759
875
|
);
|
|
760
876
|
}
|
|
761
877
|
|
|
@@ -800,13 +916,6 @@ async function kmacImportKey(
|
|
|
800
916
|
): Promise<CryptoKey> {
|
|
801
917
|
const { name } = algorithm;
|
|
802
918
|
|
|
803
|
-
if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
|
|
804
|
-
throw lazyDOMException(
|
|
805
|
-
`Unsupported key usage for ${name} key`,
|
|
806
|
-
'SyntaxError',
|
|
807
|
-
);
|
|
808
|
-
}
|
|
809
|
-
|
|
810
919
|
let keyObject: KeyObject;
|
|
811
920
|
|
|
812
921
|
if (format === 'jwk') {
|
|
@@ -815,29 +924,51 @@ async function kmacImportKey(
|
|
|
815
924
|
if (!jwk || typeof jwk !== 'object') {
|
|
816
925
|
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
817
926
|
}
|
|
818
|
-
|
|
819
927
|
if (jwk.kty !== 'oct') {
|
|
820
|
-
throw lazyDOMException('Invalid JWK
|
|
928
|
+
throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
|
|
821
929
|
}
|
|
930
|
+
validateJwkStructure(jwk, extractable, keyUsages, 'sig');
|
|
822
931
|
|
|
823
932
|
const expectedAlg = name === 'KMAC128' ? 'K128' : 'K256';
|
|
824
933
|
if (jwk.alg !== undefined && jwk.alg !== expectedAlg) {
|
|
825
934
|
throw lazyDOMException(
|
|
826
|
-
'JWK "alg"
|
|
935
|
+
'JWK "alg" Parameter and algorithm name mismatch',
|
|
827
936
|
'DataError',
|
|
828
937
|
);
|
|
829
938
|
}
|
|
830
939
|
|
|
940
|
+
if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
|
|
941
|
+
throw lazyDOMException(
|
|
942
|
+
`Unsupported key usage for ${name} key`,
|
|
943
|
+
'SyntaxError',
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
|
|
831
947
|
const handle =
|
|
832
948
|
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
833
|
-
|
|
834
|
-
|
|
949
|
+
let keyType: KeyType | undefined;
|
|
950
|
+
try {
|
|
951
|
+
keyType = handle.initJwk(jwk, undefined);
|
|
952
|
+
} catch (err) {
|
|
953
|
+
throw lazyDOMException('Invalid keyData', {
|
|
954
|
+
name: 'DataError',
|
|
955
|
+
cause: err,
|
|
956
|
+
});
|
|
957
|
+
}
|
|
835
958
|
if (keyType === undefined || keyType !== 0) {
|
|
836
|
-
throw lazyDOMException('
|
|
959
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
837
960
|
}
|
|
838
961
|
|
|
839
962
|
keyObject = new SecretKeyObject(handle);
|
|
840
|
-
} else if (format === 'raw
|
|
963
|
+
} else if (format === 'raw-secret') {
|
|
964
|
+
// KMAC accepts only the disambiguated 'raw-secret' form (Node mac.js:141-145
|
|
965
|
+
// returns undefined for plain 'raw' when not HMAC).
|
|
966
|
+
if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
|
|
967
|
+
throw lazyDOMException(
|
|
968
|
+
`Unsupported key usage for ${name} key`,
|
|
969
|
+
'SyntaxError',
|
|
970
|
+
);
|
|
971
|
+
}
|
|
841
972
|
keyObject = createSecretKey(data as BinaryLike);
|
|
842
973
|
} else {
|
|
843
974
|
throw lazyDOMException(
|
|
@@ -874,7 +1005,6 @@ function rsaImportKey(
|
|
|
874
1005
|
): CryptoKey {
|
|
875
1006
|
const { name } = algorithm;
|
|
876
1007
|
|
|
877
|
-
// Validate usages
|
|
878
1008
|
let checkSet: KeyUsage[];
|
|
879
1009
|
switch (name) {
|
|
880
1010
|
case 'RSASSA-PKCS1-v1_5':
|
|
@@ -887,38 +1017,75 @@ function rsaImportKey(
|
|
|
887
1017
|
default:
|
|
888
1018
|
throw new Error(`Unsupported RSA algorithm: ${name}`);
|
|
889
1019
|
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1020
|
+
const checkUsages = (): void => {
|
|
1021
|
+
if (hasAnyNotIn(keyUsages, checkSet)) {
|
|
1022
|
+
throw lazyDOMException(
|
|
1023
|
+
`Unsupported key usage for ${name} key`,
|
|
1024
|
+
'SyntaxError',
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
894
1028
|
|
|
895
1029
|
let keyObject: KeyObject;
|
|
896
1030
|
|
|
897
1031
|
if (format === 'jwk') {
|
|
898
1032
|
const jwk = data as JWK;
|
|
899
1033
|
|
|
900
|
-
|
|
1034
|
+
if (!jwk || typeof jwk !== 'object') {
|
|
1035
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
1036
|
+
}
|
|
901
1037
|
if (jwk.kty !== 'RSA') {
|
|
902
|
-
throw
|
|
1038
|
+
throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
|
|
1039
|
+
}
|
|
1040
|
+
const expectedUse = name === 'RSA-OAEP' ? 'enc' : 'sig';
|
|
1041
|
+
validateJwkStructure(jwk, extractable, keyUsages, expectedUse);
|
|
1042
|
+
checkUsages();
|
|
1043
|
+
|
|
1044
|
+
if (jwk.alg !== undefined) {
|
|
1045
|
+
let jwkContext: HashContext;
|
|
1046
|
+
switch (name) {
|
|
1047
|
+
case 'RSASSA-PKCS1-v1_5':
|
|
1048
|
+
jwkContext = HashContext.JwkRsa;
|
|
1049
|
+
break;
|
|
1050
|
+
case 'RSA-PSS':
|
|
1051
|
+
jwkContext = HashContext.JwkRsaPss;
|
|
1052
|
+
break;
|
|
1053
|
+
default:
|
|
1054
|
+
jwkContext = HashContext.JwkRsaOaep;
|
|
1055
|
+
}
|
|
1056
|
+
const expectedAlg = normalizeHashName(algorithm.hash, jwkContext);
|
|
1057
|
+
if (jwk.alg !== expectedAlg) {
|
|
1058
|
+
throw lazyDOMException(
|
|
1059
|
+
'JWK "alg" does not match the requested algorithm',
|
|
1060
|
+
'DataError',
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
903
1063
|
}
|
|
904
1064
|
|
|
905
1065
|
const handle =
|
|
906
1066
|
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
907
|
-
|
|
908
|
-
|
|
1067
|
+
let keyType: KeyType | undefined;
|
|
1068
|
+
try {
|
|
1069
|
+
keyType = handle.initJwk(jwk, undefined);
|
|
1070
|
+
} catch (err) {
|
|
1071
|
+
throw lazyDOMException('Invalid keyData', {
|
|
1072
|
+
name: 'DataError',
|
|
1073
|
+
cause: err,
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
909
1076
|
if (keyType === undefined) {
|
|
910
|
-
throw
|
|
1077
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
911
1078
|
}
|
|
912
1079
|
|
|
913
|
-
|
|
914
|
-
if (keyType === 1) {
|
|
1080
|
+
if (keyType === KeyType.PUBLIC) {
|
|
915
1081
|
keyObject = new PublicKeyObject(handle);
|
|
916
|
-
} else if (keyType ===
|
|
1082
|
+
} else if (keyType === KeyType.PRIVATE) {
|
|
917
1083
|
keyObject = new PrivateKeyObject(handle);
|
|
918
1084
|
} else {
|
|
919
|
-
throw
|
|
1085
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
920
1086
|
}
|
|
921
1087
|
} else if (format === 'spki') {
|
|
1088
|
+
checkUsages();
|
|
922
1089
|
const keyData = bufferLikeToArrayBuffer(data as BufferLike);
|
|
923
1090
|
keyObject = KeyObject.createKeyObject(
|
|
924
1091
|
'public',
|
|
@@ -927,6 +1094,7 @@ function rsaImportKey(
|
|
|
927
1094
|
KeyEncoding.SPKI,
|
|
928
1095
|
);
|
|
929
1096
|
} else if (format === 'pkcs8') {
|
|
1097
|
+
checkUsages();
|
|
930
1098
|
const keyData = bufferLikeToArrayBuffer(data as BufferLike);
|
|
931
1099
|
keyObject = KeyObject.createKeyObject(
|
|
932
1100
|
'private',
|
|
@@ -935,7 +1103,10 @@ function rsaImportKey(
|
|
|
935
1103
|
KeyEncoding.PKCS8,
|
|
936
1104
|
);
|
|
937
1105
|
} else {
|
|
938
|
-
throw
|
|
1106
|
+
throw lazyDOMException(
|
|
1107
|
+
`Unsupported format for ${name} import: ${format}`,
|
|
1108
|
+
'NotSupportedError',
|
|
1109
|
+
);
|
|
939
1110
|
}
|
|
940
1111
|
|
|
941
1112
|
// Get the modulus length from the key and add it to the algorithm
|
|
@@ -977,31 +1148,30 @@ async function hmacImportKey(
|
|
|
977
1148
|
extractable: boolean,
|
|
978
1149
|
keyUsages: KeyUsage[],
|
|
979
1150
|
): Promise<CryptoKey> {
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1151
|
+
const checkUsages = (): void => {
|
|
1152
|
+
if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
|
|
1153
|
+
throw new Error('Unsupported key usage for an HMAC key');
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
984
1156
|
|
|
985
1157
|
let keyObject: KeyObject;
|
|
986
1158
|
|
|
987
1159
|
if (format === 'jwk') {
|
|
988
1160
|
const jwk = data as JWK;
|
|
989
1161
|
|
|
990
|
-
// Validate JWK
|
|
991
1162
|
if (!jwk || typeof jwk !== 'object') {
|
|
992
1163
|
throw new Error('Invalid keyData');
|
|
993
1164
|
}
|
|
994
|
-
|
|
995
1165
|
if (jwk.kty !== 'oct') {
|
|
996
1166
|
throw new Error('Invalid JWK format for HMAC key');
|
|
997
1167
|
}
|
|
1168
|
+
validateJwkStructure(jwk, extractable, keyUsages, 'sig');
|
|
1169
|
+
checkUsages();
|
|
998
1170
|
|
|
999
|
-
// Validate key length if specified
|
|
1000
1171
|
if (algorithm.length !== undefined) {
|
|
1001
1172
|
if (!jwk.k) {
|
|
1002
1173
|
throw new Error('JWK missing key data');
|
|
1003
1174
|
}
|
|
1004
|
-
// Decode to check length
|
|
1005
1175
|
const decoded = SBuffer.from(jwk.k, 'base64');
|
|
1006
1176
|
const keyBitLength = decoded.length * 8;
|
|
1007
1177
|
if (algorithm.length === 0) {
|
|
@@ -1014,17 +1184,29 @@ async function hmacImportKey(
|
|
|
1014
1184
|
|
|
1015
1185
|
const handle =
|
|
1016
1186
|
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1017
|
-
|
|
1018
|
-
|
|
1187
|
+
let keyType: KeyType | undefined;
|
|
1188
|
+
try {
|
|
1189
|
+
keyType = handle.initJwk(jwk, undefined);
|
|
1190
|
+
} catch (err) {
|
|
1191
|
+
throw lazyDOMException('Invalid keyData', {
|
|
1192
|
+
name: 'DataError',
|
|
1193
|
+
cause: err,
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1019
1196
|
if (keyType === undefined || keyType !== 0) {
|
|
1020
|
-
throw
|
|
1197
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
1021
1198
|
}
|
|
1022
1199
|
|
|
1023
1200
|
keyObject = new SecretKeyObject(handle);
|
|
1024
|
-
} else if (format === 'raw') {
|
|
1201
|
+
} else if (format === 'raw' || format === 'raw-secret') {
|
|
1202
|
+
// HMAC accepts both 'raw' and 'raw-secret' (Node mac.js:141-145).
|
|
1203
|
+
checkUsages();
|
|
1025
1204
|
keyObject = createSecretKey(data as BinaryLike);
|
|
1026
1205
|
} else {
|
|
1027
|
-
throw
|
|
1206
|
+
throw lazyDOMException(
|
|
1207
|
+
`Unable to import HMAC key with format ${format}`,
|
|
1208
|
+
'NotSupportedError',
|
|
1209
|
+
);
|
|
1028
1210
|
}
|
|
1029
1211
|
|
|
1030
1212
|
// Normalize hash to { name: string } format per WebCrypto spec
|
|
@@ -1047,16 +1229,24 @@ async function aesImportKey(
|
|
|
1047
1229
|
): Promise<CryptoKey> {
|
|
1048
1230
|
const { name, length } = algorithm;
|
|
1049
1231
|
|
|
1050
|
-
// Validate usages
|
|
1051
1232
|
const validUsages: KeyUsage[] = [
|
|
1052
1233
|
'encrypt',
|
|
1053
1234
|
'decrypt',
|
|
1054
1235
|
'wrapKey',
|
|
1055
1236
|
'unwrapKey',
|
|
1056
1237
|
];
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1238
|
+
const checkUsages = (): void => {
|
|
1239
|
+
if (hasAnyNotIn(keyUsages, validUsages)) {
|
|
1240
|
+
throw new Error(`Unsupported key usage for ${name}`);
|
|
1241
|
+
}
|
|
1242
|
+
};
|
|
1243
|
+
|
|
1244
|
+
// AES-OCB and ChaCha20-Poly1305 require the disambiguated 'raw-secret' form
|
|
1245
|
+
// and reject 'raw' (Node aes.js:243-249, chacha20_poly1305.js:104-134).
|
|
1246
|
+
// Other AES variants accept both 'raw' and 'raw-secret'.
|
|
1247
|
+
const requiresRawSecret = name === 'AES-OCB' || name === 'ChaCha20-Poly1305';
|
|
1248
|
+
const acceptsRaw =
|
|
1249
|
+
format === 'raw-secret' || (format === 'raw' && !requiresRawSecret);
|
|
1060
1250
|
|
|
1061
1251
|
let keyObject: KeyObject;
|
|
1062
1252
|
let actualLength: number;
|
|
@@ -1064,36 +1254,53 @@ async function aesImportKey(
|
|
|
1064
1254
|
if (format === 'jwk') {
|
|
1065
1255
|
const jwk = data as JWK;
|
|
1066
1256
|
|
|
1067
|
-
// Validate JWK
|
|
1068
1257
|
if (jwk.kty !== 'oct') {
|
|
1069
1258
|
throw new Error('Invalid JWK format for AES key');
|
|
1070
1259
|
}
|
|
1260
|
+
validateJwkStructure(jwk, extractable, keyUsages, 'enc');
|
|
1261
|
+
checkUsages();
|
|
1071
1262
|
|
|
1072
1263
|
const handle =
|
|
1073
1264
|
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1074
|
-
|
|
1075
|
-
|
|
1265
|
+
let keyType: KeyType | undefined;
|
|
1266
|
+
try {
|
|
1267
|
+
keyType = handle.initJwk(jwk, undefined);
|
|
1268
|
+
} catch (err) {
|
|
1269
|
+
throw lazyDOMException('Invalid keyData', {
|
|
1270
|
+
name: 'DataError',
|
|
1271
|
+
cause: err,
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1076
1274
|
if (keyType === undefined || keyType !== 0) {
|
|
1077
|
-
throw
|
|
1275
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
1078
1276
|
}
|
|
1079
1277
|
|
|
1080
1278
|
keyObject = new SecretKeyObject(handle);
|
|
1081
1279
|
|
|
1082
|
-
// Get actual key length from imported key
|
|
1083
1280
|
const exported = keyObject.export();
|
|
1084
1281
|
actualLength = exported.byteLength * 8;
|
|
1085
|
-
} else if (
|
|
1282
|
+
} else if (acceptsRaw) {
|
|
1283
|
+
checkUsages();
|
|
1086
1284
|
const keyData = bufferLikeToArrayBuffer(data as BufferLike);
|
|
1087
1285
|
actualLength = keyData.byteLength * 8;
|
|
1088
1286
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1287
|
+
if (name === 'ChaCha20-Poly1305') {
|
|
1288
|
+
if (actualLength !== 256) {
|
|
1289
|
+
throw lazyDOMException(
|
|
1290
|
+
'Invalid ChaCha20-Poly1305 key length',
|
|
1291
|
+
'DataError',
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1294
|
+
} else if (![128, 192, 256].includes(actualLength)) {
|
|
1091
1295
|
throw new Error('Invalid AES key length');
|
|
1092
1296
|
}
|
|
1093
1297
|
|
|
1094
1298
|
keyObject = createSecretKey(keyData);
|
|
1095
1299
|
} else {
|
|
1096
|
-
throw
|
|
1300
|
+
throw lazyDOMException(
|
|
1301
|
+
`Unable to import ${name} key with format ${format}`,
|
|
1302
|
+
'NotSupportedError',
|
|
1303
|
+
);
|
|
1097
1304
|
}
|
|
1098
1305
|
|
|
1099
1306
|
// Validate length if specified
|
|
@@ -1120,23 +1327,23 @@ function edImportKey(
|
|
|
1120
1327
|
): CryptoKey {
|
|
1121
1328
|
const { name } = algorithm;
|
|
1122
1329
|
|
|
1123
|
-
// Validate usages
|
|
1124
1330
|
const isX = name === 'X25519' || name === 'X448';
|
|
1125
1331
|
const allowedUsages: KeyUsage[] = isX
|
|
1126
1332
|
? ['deriveKey', 'deriveBits']
|
|
1127
1333
|
: ['sign', 'verify'];
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1334
|
+
const checkUsages = (): void => {
|
|
1335
|
+
if (hasAnyNotIn(keyUsages, allowedUsages)) {
|
|
1336
|
+
throw lazyDOMException(
|
|
1337
|
+
`Unsupported key usage for ${name} key`,
|
|
1338
|
+
'SyntaxError',
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1135
1342
|
|
|
1136
1343
|
let keyObject: KeyObject;
|
|
1137
1344
|
|
|
1138
1345
|
if (format === 'spki') {
|
|
1139
|
-
|
|
1346
|
+
checkUsages();
|
|
1140
1347
|
const keyData = bufferLikeToArrayBuffer(data as BufferLike);
|
|
1141
1348
|
keyObject = KeyObject.createKeyObject(
|
|
1142
1349
|
'public',
|
|
@@ -1145,7 +1352,7 @@ function edImportKey(
|
|
|
1145
1352
|
KeyEncoding.SPKI,
|
|
1146
1353
|
);
|
|
1147
1354
|
} else if (format === 'pkcs8') {
|
|
1148
|
-
|
|
1355
|
+
checkUsages();
|
|
1149
1356
|
const keyData = bufferLikeToArrayBuffer(data as BufferLike);
|
|
1150
1357
|
keyObject = KeyObject.createKeyObject(
|
|
1151
1358
|
'private',
|
|
@@ -1154,19 +1361,51 @@ function edImportKey(
|
|
|
1154
1361
|
KeyEncoding.PKCS8,
|
|
1155
1362
|
);
|
|
1156
1363
|
} else if (format === 'raw') {
|
|
1157
|
-
|
|
1364
|
+
checkUsages();
|
|
1158
1365
|
const keyData = bufferLikeToArrayBuffer(data as BufferLike);
|
|
1159
1366
|
const handle =
|
|
1160
1367
|
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1161
|
-
|
|
1162
|
-
// Raw public keys are just the key bytes
|
|
1163
|
-
handle.init(1, keyData); // 1 = public key type
|
|
1368
|
+
handle.init(1, keyData);
|
|
1164
1369
|
keyObject = new PublicKeyObject(handle);
|
|
1165
1370
|
} else if (format === 'jwk') {
|
|
1166
1371
|
const jwkData = data as JWK;
|
|
1372
|
+
if (!jwkData || typeof jwkData !== 'object') {
|
|
1373
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
1374
|
+
}
|
|
1375
|
+
if (jwkData.kty !== 'OKP') {
|
|
1376
|
+
throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
|
|
1377
|
+
}
|
|
1378
|
+
const expectedUse = isX ? 'enc' : 'sig';
|
|
1379
|
+
validateJwkStructure(jwkData, extractable, keyUsages, expectedUse);
|
|
1380
|
+
|
|
1381
|
+
if (jwkData.crv !== name) {
|
|
1382
|
+
throw lazyDOMException(
|
|
1383
|
+
'JWK "crv" Parameter and algorithm name mismatch',
|
|
1384
|
+
'DataError',
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
if (!isX && jwkData.alg !== undefined) {
|
|
1389
|
+
if (jwkData.alg !== name && jwkData.alg !== 'EdDSA') {
|
|
1390
|
+
throw lazyDOMException(
|
|
1391
|
+
'JWK "alg" does not match the requested algorithm',
|
|
1392
|
+
'DataError',
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
checkUsages();
|
|
1167
1398
|
const handle =
|
|
1168
1399
|
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1169
|
-
|
|
1400
|
+
let keyType: KeyType | undefined;
|
|
1401
|
+
try {
|
|
1402
|
+
keyType = handle.initJwk(jwkData);
|
|
1403
|
+
} catch (err) {
|
|
1404
|
+
throw lazyDOMException('Invalid JWK data', {
|
|
1405
|
+
name: 'DataError',
|
|
1406
|
+
cause: err,
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1170
1409
|
if (keyType === undefined) {
|
|
1171
1410
|
throw lazyDOMException('Invalid JWK data', 'DataError');
|
|
1172
1411
|
}
|
|
@@ -1185,42 +1424,133 @@ function edImportKey(
|
|
|
1185
1424
|
return new CryptoKey(keyObject, { name }, keyUsages, extractable);
|
|
1186
1425
|
}
|
|
1187
1426
|
|
|
1427
|
+
// Lengths (in bytes) of seedless ML-DSA / ML-KEM PKCS#8 encodings. A PKCS#8
|
|
1428
|
+
// blob of exactly this length contains only the expanded private key with no
|
|
1429
|
+
// seed; Node rejects these to keep cross-implementation interop intact.
|
|
1430
|
+
// Refs: node lib/internal/crypto/ml_dsa.js (mlDsaImportKey, pkcs8 case)
|
|
1431
|
+
// node lib/internal/crypto/ml_kem.js (mlKemImportKey, pkcs8 case)
|
|
1432
|
+
export const PQC_SEEDLESS_PKCS8_LENGTHS: Readonly<Record<string, number>> = {
|
|
1433
|
+
'ML-DSA-44': 2588,
|
|
1434
|
+
'ML-DSA-65': 4060,
|
|
1435
|
+
'ML-DSA-87': 4924,
|
|
1436
|
+
'ML-KEM-512': 1660,
|
|
1437
|
+
'ML-KEM-768': 2428,
|
|
1438
|
+
'ML-KEM-1024': 3196,
|
|
1439
|
+
};
|
|
1440
|
+
|
|
1441
|
+
// Map from PQC algorithm name to display family. Used to render the
|
|
1442
|
+
// import-rejection error message in the same form Node emits.
|
|
1443
|
+
const PQC_FAMILY: Readonly<Record<string, 'ML-DSA' | 'ML-KEM' | 'SLH-DSA'>> = {
|
|
1444
|
+
'ML-DSA-44': 'ML-DSA',
|
|
1445
|
+
'ML-DSA-65': 'ML-DSA',
|
|
1446
|
+
'ML-DSA-87': 'ML-DSA',
|
|
1447
|
+
'ML-KEM-512': 'ML-KEM',
|
|
1448
|
+
'ML-KEM-768': 'ML-KEM',
|
|
1449
|
+
'ML-KEM-1024': 'ML-KEM',
|
|
1450
|
+
'SLH-DSA-SHA2-128s': 'SLH-DSA',
|
|
1451
|
+
'SLH-DSA-SHA2-128f': 'SLH-DSA',
|
|
1452
|
+
'SLH-DSA-SHA2-192s': 'SLH-DSA',
|
|
1453
|
+
'SLH-DSA-SHA2-192f': 'SLH-DSA',
|
|
1454
|
+
'SLH-DSA-SHA2-256s': 'SLH-DSA',
|
|
1455
|
+
'SLH-DSA-SHA2-256f': 'SLH-DSA',
|
|
1456
|
+
'SLH-DSA-SHAKE-128s': 'SLH-DSA',
|
|
1457
|
+
'SLH-DSA-SHAKE-128f': 'SLH-DSA',
|
|
1458
|
+
'SLH-DSA-SHAKE-192s': 'SLH-DSA',
|
|
1459
|
+
'SLH-DSA-SHAKE-192f': 'SLH-DSA',
|
|
1460
|
+
'SLH-DSA-SHAKE-256s': 'SLH-DSA',
|
|
1461
|
+
'SLH-DSA-SHAKE-256f': 'SLH-DSA',
|
|
1462
|
+
};
|
|
1463
|
+
|
|
1188
1464
|
function pqcImportKeyObject(
|
|
1189
1465
|
format: ImportFormat,
|
|
1190
|
-
data: BufferLike,
|
|
1466
|
+
data: BufferLike | JWK,
|
|
1191
1467
|
name: string,
|
|
1192
|
-
): KeyObject {
|
|
1468
|
+
): { keyObject: KeyObject; isPublic: boolean } {
|
|
1193
1469
|
if (format === 'spki') {
|
|
1194
|
-
return
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1470
|
+
return {
|
|
1471
|
+
keyObject: KeyObject.createKeyObject(
|
|
1472
|
+
'public',
|
|
1473
|
+
bufferLikeToArrayBuffer(data as BufferLike),
|
|
1474
|
+
KFormatType.DER,
|
|
1475
|
+
KeyEncoding.SPKI,
|
|
1476
|
+
),
|
|
1477
|
+
isPublic: true,
|
|
1478
|
+
};
|
|
1200
1479
|
} else if (format === 'pkcs8') {
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
)
|
|
1207
|
-
|
|
1480
|
+
const ab = bufferLikeToArrayBuffer(data as BufferLike);
|
|
1481
|
+
const family = PQC_FAMILY[name];
|
|
1482
|
+
if (
|
|
1483
|
+
family !== undefined &&
|
|
1484
|
+
ab.byteLength === PQC_SEEDLESS_PKCS8_LENGTHS[name]
|
|
1485
|
+
) {
|
|
1486
|
+
throw lazyDOMException(
|
|
1487
|
+
`Importing an ${family} PKCS#8 key without a seed is not supported`,
|
|
1488
|
+
'NotSupportedError',
|
|
1489
|
+
);
|
|
1490
|
+
}
|
|
1491
|
+
return {
|
|
1492
|
+
keyObject: KeyObject.createKeyObject(
|
|
1493
|
+
'private',
|
|
1494
|
+
ab,
|
|
1495
|
+
KFormatType.DER,
|
|
1496
|
+
KeyEncoding.PKCS8,
|
|
1497
|
+
),
|
|
1498
|
+
isPublic: false,
|
|
1499
|
+
};
|
|
1500
|
+
} else if (format === 'raw-public') {
|
|
1501
|
+
// ML-DSA / ML-KEM reject plain 'raw' — only 'raw-public' is accepted for
|
|
1502
|
+
// public-key import (Node webcrypto.js:493-499, 506-511).
|
|
1208
1503
|
const handle =
|
|
1209
1504
|
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1210
|
-
if (
|
|
1505
|
+
if (
|
|
1506
|
+
!handle.initPqcRaw(
|
|
1507
|
+
name,
|
|
1508
|
+
bufferLikeToArrayBuffer(data as BufferLike),
|
|
1509
|
+
true,
|
|
1510
|
+
)
|
|
1511
|
+
) {
|
|
1211
1512
|
throw lazyDOMException(
|
|
1212
1513
|
`Failed to import ${name} raw public key`,
|
|
1213
1514
|
'DataError',
|
|
1214
1515
|
);
|
|
1215
1516
|
}
|
|
1216
|
-
return new PublicKeyObject(handle);
|
|
1517
|
+
return { keyObject: new PublicKeyObject(handle), isPublic: true };
|
|
1217
1518
|
} else if (format === 'raw-seed') {
|
|
1218
1519
|
const handle =
|
|
1219
1520
|
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1220
|
-
if (
|
|
1521
|
+
if (
|
|
1522
|
+
!handle.initPqcRaw(
|
|
1523
|
+
name,
|
|
1524
|
+
bufferLikeToArrayBuffer(data as BufferLike),
|
|
1525
|
+
false,
|
|
1526
|
+
)
|
|
1527
|
+
) {
|
|
1221
1528
|
throw lazyDOMException(`Failed to import ${name} raw seed`, 'DataError');
|
|
1222
1529
|
}
|
|
1223
|
-
return new PrivateKeyObject(handle);
|
|
1530
|
+
return { keyObject: new PrivateKeyObject(handle), isPublic: false };
|
|
1531
|
+
} else if (format === 'jwk') {
|
|
1532
|
+
const jwkData = data as JWK;
|
|
1533
|
+
const isPublic = jwkData.priv === undefined;
|
|
1534
|
+
const handle =
|
|
1535
|
+
NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
|
|
1536
|
+
let keyType: KeyType | undefined;
|
|
1537
|
+
try {
|
|
1538
|
+
keyType = handle.initJwk(jwkData);
|
|
1539
|
+
} catch (err) {
|
|
1540
|
+
throw lazyDOMException('Invalid JWK data', {
|
|
1541
|
+
name: 'DataError',
|
|
1542
|
+
cause: err,
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
if (keyType === undefined) {
|
|
1546
|
+
throw lazyDOMException('Invalid JWK data', 'DataError');
|
|
1547
|
+
}
|
|
1548
|
+
return {
|
|
1549
|
+
keyObject: isPublic
|
|
1550
|
+
? new PublicKeyObject(handle)
|
|
1551
|
+
: new PrivateKeyObject(handle),
|
|
1552
|
+
isPublic,
|
|
1553
|
+
};
|
|
1224
1554
|
}
|
|
1225
1555
|
throw lazyDOMException(
|
|
1226
1556
|
`Unsupported format for ${name} import: ${format}`,
|
|
@@ -1228,39 +1558,109 @@ function pqcImportKeyObject(
|
|
|
1228
1558
|
);
|
|
1229
1559
|
}
|
|
1230
1560
|
|
|
1561
|
+
// Per WebCrypto AKP JWK rules, public-vs-private is determined by the presence
|
|
1562
|
+
// of `priv`. For binary formats it follows from the format itself.
|
|
1563
|
+
function pqcIsPublicImport(
|
|
1564
|
+
format: ImportFormat,
|
|
1565
|
+
data: BufferLike | JWK,
|
|
1566
|
+
): boolean {
|
|
1567
|
+
if (format === 'jwk') {
|
|
1568
|
+
return (
|
|
1569
|
+
typeof data === 'object' &&
|
|
1570
|
+
data !== null &&
|
|
1571
|
+
(data as JWK).priv === undefined
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
return format === 'spki' || format === 'raw-public';
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
function validatePqcJwk(
|
|
1578
|
+
data: BufferLike | JWK,
|
|
1579
|
+
name: string,
|
|
1580
|
+
extractable: boolean,
|
|
1581
|
+
keyUsages: KeyUsage[],
|
|
1582
|
+
expectedUse: 'sig' | 'enc',
|
|
1583
|
+
): void {
|
|
1584
|
+
if (typeof data !== 'object' || data === null) {
|
|
1585
|
+
throw lazyDOMException('Invalid keyData', 'DataError');
|
|
1586
|
+
}
|
|
1587
|
+
const jwk = data as JWK;
|
|
1588
|
+
if (jwk.kty !== 'AKP') {
|
|
1589
|
+
throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
|
|
1590
|
+
}
|
|
1591
|
+
validateJwkStructure(jwk, extractable, keyUsages, expectedUse);
|
|
1592
|
+
if (jwk.alg !== name) {
|
|
1593
|
+
throw lazyDOMException(
|
|
1594
|
+
'JWK "alg" Parameter and algorithm name mismatch',
|
|
1595
|
+
'DataError',
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
// Validates that `format` is one of the formats PQC algorithms accept; rejects
|
|
1601
|
+
// plain 'raw' early so the format error wins over usage-based errors.
|
|
1602
|
+
function validatePqcFormat(format: ImportFormat, name: string): void {
|
|
1603
|
+
if (
|
|
1604
|
+
format !== 'spki' &&
|
|
1605
|
+
format !== 'pkcs8' &&
|
|
1606
|
+
format !== 'raw-public' &&
|
|
1607
|
+
format !== 'raw-seed' &&
|
|
1608
|
+
format !== 'jwk'
|
|
1609
|
+
) {
|
|
1610
|
+
throw lazyDOMException(
|
|
1611
|
+
`Unsupported format for ${name} import: ${format}`,
|
|
1612
|
+
'NotSupportedError',
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1231
1617
|
function mldsaImportKey(
|
|
1232
1618
|
format: ImportFormat,
|
|
1233
|
-
data: BufferLike,
|
|
1619
|
+
data: BufferLike | JWK,
|
|
1234
1620
|
algorithm: SubtleAlgorithm,
|
|
1235
1621
|
extractable: boolean,
|
|
1236
1622
|
keyUsages: KeyUsage[],
|
|
1237
1623
|
): CryptoKey {
|
|
1238
1624
|
const { name } = algorithm;
|
|
1239
|
-
|
|
1240
|
-
if (
|
|
1625
|
+
validatePqcFormat(format, name);
|
|
1626
|
+
if (format === 'jwk') {
|
|
1627
|
+
validatePqcJwk(data, name, extractable, keyUsages, 'sig');
|
|
1628
|
+
}
|
|
1629
|
+
const isPublic = pqcIsPublicImport(format, data);
|
|
1630
|
+
if (hasAnyNotIn(keyUsages, isPublic ? ['verify'] : ['sign'])) {
|
|
1241
1631
|
throw lazyDOMException(
|
|
1242
1632
|
`Unsupported key usage for ${name} key`,
|
|
1243
1633
|
'SyntaxError',
|
|
1244
1634
|
);
|
|
1245
1635
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1636
|
+
const { keyObject } = pqcImportKeyObject(format, data, name);
|
|
1637
|
+
return new CryptoKey(keyObject, { name }, keyUsages, extractable);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
function slhdsaImportKey(
|
|
1641
|
+
format: ImportFormat,
|
|
1642
|
+
data: BufferLike | JWK,
|
|
1643
|
+
algorithm: SubtleAlgorithm,
|
|
1644
|
+
extractable: boolean,
|
|
1645
|
+
keyUsages: KeyUsage[],
|
|
1646
|
+
): CryptoKey {
|
|
1647
|
+
return mldsaImportKey(format, data, algorithm, extractable, keyUsages);
|
|
1252
1648
|
}
|
|
1253
1649
|
|
|
1254
1650
|
function mlkemImportKey(
|
|
1255
1651
|
format: ImportFormat,
|
|
1256
|
-
data: BufferLike,
|
|
1652
|
+
data: BufferLike | JWK,
|
|
1257
1653
|
algorithm: SubtleAlgorithm,
|
|
1258
1654
|
extractable: boolean,
|
|
1259
1655
|
keyUsages: KeyUsage[],
|
|
1260
1656
|
): CryptoKey {
|
|
1261
1657
|
const { name } = algorithm;
|
|
1262
|
-
|
|
1263
|
-
|
|
1658
|
+
validatePqcFormat(format, name);
|
|
1659
|
+
if (format === 'jwk') {
|
|
1660
|
+
validatePqcJwk(data, name, extractable, keyUsages, 'enc');
|
|
1661
|
+
}
|
|
1662
|
+
const isPublic = pqcIsPublicImport(format, data);
|
|
1663
|
+
const allowedUsages: KeyUsage[] = isPublic
|
|
1264
1664
|
? ['encapsulateBits', 'encapsulateKey']
|
|
1265
1665
|
: ['decapsulateBits', 'decapsulateKey'];
|
|
1266
1666
|
if (hasAnyNotIn(keyUsages, allowedUsages)) {
|
|
@@ -1269,12 +1669,8 @@ function mlkemImportKey(
|
|
|
1269
1669
|
'SyntaxError',
|
|
1270
1670
|
);
|
|
1271
1671
|
}
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
{ name },
|
|
1275
|
-
keyUsages,
|
|
1276
|
-
extractable,
|
|
1277
|
-
);
|
|
1672
|
+
const { keyObject } = pqcImportKeyObject(format, data, name);
|
|
1673
|
+
return new CryptoKey(keyObject, { name }, keyUsages, extractable);
|
|
1278
1674
|
}
|
|
1279
1675
|
|
|
1280
1676
|
const exportKeySpki = async (
|
|
@@ -1316,8 +1712,21 @@ const exportKeySpki = async (
|
|
|
1316
1712
|
case 'ML-DSA-65':
|
|
1317
1713
|
// Fall through
|
|
1318
1714
|
case 'ML-DSA-87':
|
|
1715
|
+
// Fall through
|
|
1716
|
+
case 'SLH-DSA-SHA2-128s':
|
|
1717
|
+
case 'SLH-DSA-SHA2-128f':
|
|
1718
|
+
case 'SLH-DSA-SHA2-192s':
|
|
1719
|
+
case 'SLH-DSA-SHA2-192f':
|
|
1720
|
+
case 'SLH-DSA-SHA2-256s':
|
|
1721
|
+
case 'SLH-DSA-SHA2-256f':
|
|
1722
|
+
case 'SLH-DSA-SHAKE-128s':
|
|
1723
|
+
case 'SLH-DSA-SHAKE-128f':
|
|
1724
|
+
case 'SLH-DSA-SHAKE-192s':
|
|
1725
|
+
case 'SLH-DSA-SHAKE-192f':
|
|
1726
|
+
case 'SLH-DSA-SHAKE-256s':
|
|
1727
|
+
case 'SLH-DSA-SHAKE-256f':
|
|
1319
1728
|
if (key.type === 'public') {
|
|
1320
|
-
// Export ML-DSA key in SPKI DER format
|
|
1729
|
+
// Export ML-DSA / SLH-DSA key in SPKI DER format
|
|
1321
1730
|
return bufferLikeToArrayBuffer(
|
|
1322
1731
|
key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.SPKI),
|
|
1323
1732
|
);
|
|
@@ -1380,18 +1789,40 @@ const exportKeyPkcs8 = async (
|
|
|
1380
1789
|
case 'ML-DSA-65':
|
|
1381
1790
|
// Fall through
|
|
1382
1791
|
case 'ML-DSA-87':
|
|
1383
|
-
|
|
1384
|
-
// Export ML-DSA key in PKCS8 DER format
|
|
1385
|
-
return bufferLikeToArrayBuffer(
|
|
1386
|
-
key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
|
|
1387
|
-
);
|
|
1388
|
-
}
|
|
1389
|
-
break;
|
|
1792
|
+
// Fall through
|
|
1390
1793
|
case 'ML-KEM-512':
|
|
1391
1794
|
// Fall through
|
|
1392
1795
|
case 'ML-KEM-768':
|
|
1393
1796
|
// Fall through
|
|
1394
1797
|
case 'ML-KEM-1024':
|
|
1798
|
+
if (key.type === 'private') {
|
|
1799
|
+
const ab = bufferLikeToArrayBuffer(
|
|
1800
|
+
key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
|
|
1801
|
+
);
|
|
1802
|
+
// 22 bytes of PKCS#8 ASN.1 + seed (32 ML-DSA, 64 ML-KEM). Guards
|
|
1803
|
+
// against a seedless KeyObject that was wrapped via toCryptoKey.
|
|
1804
|
+
const expected = key.algorithm.name.startsWith('ML-DSA') ? 54 : 86;
|
|
1805
|
+
if (ab.byteLength !== expected) {
|
|
1806
|
+
throw lazyDOMException(
|
|
1807
|
+
'The operation failed for an operation-specific reason',
|
|
1808
|
+
'OperationError',
|
|
1809
|
+
);
|
|
1810
|
+
}
|
|
1811
|
+
return ab;
|
|
1812
|
+
}
|
|
1813
|
+
break;
|
|
1814
|
+
case 'SLH-DSA-SHA2-128s':
|
|
1815
|
+
case 'SLH-DSA-SHA2-128f':
|
|
1816
|
+
case 'SLH-DSA-SHA2-192s':
|
|
1817
|
+
case 'SLH-DSA-SHA2-192f':
|
|
1818
|
+
case 'SLH-DSA-SHA2-256s':
|
|
1819
|
+
case 'SLH-DSA-SHA2-256f':
|
|
1820
|
+
case 'SLH-DSA-SHAKE-128s':
|
|
1821
|
+
case 'SLH-DSA-SHAKE-128f':
|
|
1822
|
+
case 'SLH-DSA-SHAKE-192s':
|
|
1823
|
+
case 'SLH-DSA-SHAKE-192f':
|
|
1824
|
+
case 'SLH-DSA-SHAKE-256s':
|
|
1825
|
+
case 'SLH-DSA-SHAKE-256f':
|
|
1395
1826
|
if (key.type === 'private') {
|
|
1396
1827
|
return bufferLikeToArrayBuffer(
|
|
1397
1828
|
key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
|
|
@@ -1405,79 +1836,101 @@ const exportKeyPkcs8 = async (
|
|
|
1405
1836
|
);
|
|
1406
1837
|
};
|
|
1407
1838
|
|
|
1408
|
-
|
|
1409
|
-
|
|
1839
|
+
// Mirrors Node's export key matrix (lib/internal/crypto/webcrypto.js
|
|
1840
|
+
// exportKeyRawSecret / exportKeyRawPublic, lines 472-563):
|
|
1841
|
+
//
|
|
1842
|
+
// raw — AES-CTR/CBC/GCM/KW + HMAC (secret); ECDSA/ECDH/Ed/X (public)
|
|
1843
|
+
// raw-secret — AES-CTR/CBC/GCM/KW + HMAC + AES-OCB + KMAC + ChaCha20-Poly1305
|
|
1844
|
+
// raw-public — ECDSA/ECDH + Ed/X + ML-DSA + ML-KEM (public)
|
|
1845
|
+
const exportKeyRaw = (
|
|
1846
|
+
key: CryptoKey,
|
|
1847
|
+
format: 'raw' | 'raw-secret' | 'raw-public',
|
|
1848
|
+
): ArrayBuffer => {
|
|
1849
|
+
const name = key.algorithm.name;
|
|
1850
|
+
const isPublic = key.type === 'public';
|
|
1851
|
+
const isSecret = key.type === 'secret';
|
|
1852
|
+
|
|
1853
|
+
const exportSecret = (): ArrayBuffer => {
|
|
1854
|
+
const exported = key.keyObject.export();
|
|
1855
|
+
return exported.buffer.slice(
|
|
1856
|
+
exported.byteOffset,
|
|
1857
|
+
exported.byteOffset + exported.byteLength,
|
|
1858
|
+
) as ArrayBuffer;
|
|
1859
|
+
};
|
|
1860
|
+
const exportRawPublic = (): ArrayBuffer =>
|
|
1861
|
+
bufferLikeToArrayBuffer(key.keyObject.handle.exportKey());
|
|
1862
|
+
|
|
1863
|
+
const fail = (): never => {
|
|
1864
|
+
throw lazyDOMException(
|
|
1865
|
+
`Unable to export ${name} ${key.type} key using ${format} format`,
|
|
1866
|
+
'NotSupportedError',
|
|
1867
|
+
);
|
|
1868
|
+
};
|
|
1869
|
+
|
|
1870
|
+
// Symmetric: AES-CTR/CBC/GCM/KW and HMAC accept both 'raw' and 'raw-secret';
|
|
1871
|
+
// AES-OCB / KMAC* / ChaCha20-Poly1305 only 'raw-secret'.
|
|
1872
|
+
switch (name) {
|
|
1873
|
+
case 'AES-CTR':
|
|
1874
|
+
case 'AES-CBC':
|
|
1875
|
+
case 'AES-GCM':
|
|
1876
|
+
case 'AES-KW':
|
|
1877
|
+
case 'HMAC':
|
|
1878
|
+
if (!isSecret) return fail();
|
|
1879
|
+
if (format === 'raw' || format === 'raw-secret') return exportSecret();
|
|
1880
|
+
return fail();
|
|
1881
|
+
case 'AES-OCB':
|
|
1882
|
+
case 'KMAC128':
|
|
1883
|
+
case 'KMAC256':
|
|
1884
|
+
case 'ChaCha20-Poly1305':
|
|
1885
|
+
if (!isSecret) return fail();
|
|
1886
|
+
if (format === 'raw-secret') return exportSecret();
|
|
1887
|
+
return fail();
|
|
1410
1888
|
case 'ECDSA':
|
|
1411
|
-
// Fall through
|
|
1412
1889
|
case 'ECDH':
|
|
1413
|
-
if (
|
|
1890
|
+
if (!isPublic) return fail();
|
|
1891
|
+
if (format === 'raw' || format === 'raw-public') {
|
|
1414
1892
|
return ecExportKey(key, KWebCryptoKeyFormat.kWebCryptoKeyFormatRaw);
|
|
1415
1893
|
}
|
|
1416
|
-
|
|
1894
|
+
return fail();
|
|
1417
1895
|
case 'Ed25519':
|
|
1418
|
-
// Fall through
|
|
1419
1896
|
case 'Ed448':
|
|
1420
|
-
// Fall through
|
|
1421
1897
|
case 'X25519':
|
|
1422
|
-
// Fall through
|
|
1423
1898
|
case 'X448':
|
|
1424
|
-
if (
|
|
1425
|
-
|
|
1426
|
-
|
|
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
|
|
1899
|
+
if (!isPublic) return fail();
|
|
1900
|
+
if (format === 'raw' || format === 'raw-public') return exportRawPublic();
|
|
1901
|
+
return fail();
|
|
1435
1902
|
case 'ML-DSA-44':
|
|
1436
|
-
// Fall through
|
|
1437
1903
|
case 'ML-DSA-65':
|
|
1438
|
-
// Fall through
|
|
1439
1904
|
case 'ML-DSA-87':
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
case '
|
|
1446
|
-
|
|
1447
|
-
case '
|
|
1448
|
-
|
|
1449
|
-
case '
|
|
1450
|
-
|
|
1451
|
-
case '
|
|
1452
|
-
|
|
1453
|
-
case '
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
// Convert Buffer to ArrayBuffer
|
|
1464
|
-
return exported.buffer.slice(
|
|
1465
|
-
exported.byteOffset,
|
|
1466
|
-
exported.byteOffset + exported.byteLength,
|
|
1467
|
-
);
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
throw lazyDOMException(
|
|
1472
|
-
`Unable to export a raw ${key.algorithm.name} ${key.type} key`,
|
|
1473
|
-
'InvalidAccessError',
|
|
1474
|
-
);
|
|
1905
|
+
case 'ML-KEM-512':
|
|
1906
|
+
case 'ML-KEM-768':
|
|
1907
|
+
case 'ML-KEM-1024':
|
|
1908
|
+
case 'SLH-DSA-SHA2-128s':
|
|
1909
|
+
case 'SLH-DSA-SHA2-128f':
|
|
1910
|
+
case 'SLH-DSA-SHA2-192s':
|
|
1911
|
+
case 'SLH-DSA-SHA2-192f':
|
|
1912
|
+
case 'SLH-DSA-SHA2-256s':
|
|
1913
|
+
case 'SLH-DSA-SHA2-256f':
|
|
1914
|
+
case 'SLH-DSA-SHAKE-128s':
|
|
1915
|
+
case 'SLH-DSA-SHAKE-128f':
|
|
1916
|
+
case 'SLH-DSA-SHAKE-192s':
|
|
1917
|
+
case 'SLH-DSA-SHAKE-192f':
|
|
1918
|
+
case 'SLH-DSA-SHAKE-256s':
|
|
1919
|
+
case 'SLH-DSA-SHAKE-256f':
|
|
1920
|
+
// ML-DSA / ML-KEM / SLH-DSA keys do not recognize plain 'raw' (Node
|
|
1921
|
+
// webcrypto.js lines 488-510).
|
|
1922
|
+
if (!isPublic) return fail();
|
|
1923
|
+
if (format === 'raw-public') return exportRawPublic();
|
|
1924
|
+
return fail();
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
return fail();
|
|
1475
1928
|
};
|
|
1476
1929
|
|
|
1477
1930
|
const exportKeyJWK = (key: CryptoKey): ArrayBuffer | unknown => {
|
|
1478
1931
|
const jwk = key.keyObject.handle.exportJwk(
|
|
1479
1932
|
{
|
|
1480
|
-
key_ops: key.usages,
|
|
1933
|
+
key_ops: [...key.usages],
|
|
1481
1934
|
ext: key.extractable,
|
|
1482
1935
|
},
|
|
1483
1936
|
true,
|
|
@@ -1503,16 +1956,41 @@ const exportKeyJWK = (key: CryptoKey): ArrayBuffer | unknown => {
|
|
|
1503
1956
|
return jwk;
|
|
1504
1957
|
case 'ECDSA':
|
|
1505
1958
|
// Fall through
|
|
1506
|
-
case 'ECDH':
|
|
1507
|
-
jwk.crv ||= key.algorithm.namedCurve;
|
|
1508
|
-
return jwk;
|
|
1509
|
-
case 'Ed25519':
|
|
1959
|
+
case 'ECDH':
|
|
1960
|
+
jwk.crv ||= key.algorithm.namedCurve;
|
|
1961
|
+
return jwk;
|
|
1962
|
+
case 'Ed25519':
|
|
1963
|
+
// Fall through
|
|
1964
|
+
case 'Ed448':
|
|
1965
|
+
// Fall through
|
|
1966
|
+
case 'X25519':
|
|
1967
|
+
// Fall through
|
|
1968
|
+
case 'X448':
|
|
1969
|
+
return jwk;
|
|
1970
|
+
case 'ML-DSA-44':
|
|
1971
|
+
// Fall through
|
|
1972
|
+
case 'ML-DSA-65':
|
|
1973
|
+
// Fall through
|
|
1974
|
+
case 'ML-DSA-87':
|
|
1510
1975
|
// Fall through
|
|
1511
|
-
case '
|
|
1976
|
+
case 'ML-KEM-512':
|
|
1512
1977
|
// Fall through
|
|
1513
|
-
case '
|
|
1978
|
+
case 'ML-KEM-768':
|
|
1514
1979
|
// Fall through
|
|
1515
|
-
case '
|
|
1980
|
+
case 'ML-KEM-1024':
|
|
1981
|
+
// Fall through
|
|
1982
|
+
case 'SLH-DSA-SHA2-128s':
|
|
1983
|
+
case 'SLH-DSA-SHA2-128f':
|
|
1984
|
+
case 'SLH-DSA-SHA2-192s':
|
|
1985
|
+
case 'SLH-DSA-SHA2-192f':
|
|
1986
|
+
case 'SLH-DSA-SHA2-256s':
|
|
1987
|
+
case 'SLH-DSA-SHA2-256f':
|
|
1988
|
+
case 'SLH-DSA-SHAKE-128s':
|
|
1989
|
+
case 'SLH-DSA-SHAKE-128f':
|
|
1990
|
+
case 'SLH-DSA-SHAKE-192s':
|
|
1991
|
+
case 'SLH-DSA-SHAKE-192f':
|
|
1992
|
+
case 'SLH-DSA-SHAKE-256s':
|
|
1993
|
+
case 'SLH-DSA-SHAKE-256f':
|
|
1516
1994
|
return jwk;
|
|
1517
1995
|
case 'AES-CTR':
|
|
1518
1996
|
// Fall through
|
|
@@ -1543,7 +2021,11 @@ const exportKeyJWK = (key: CryptoKey): ArrayBuffer | unknown => {
|
|
|
1543
2021
|
);
|
|
1544
2022
|
};
|
|
1545
2023
|
|
|
1546
|
-
|
|
2024
|
+
// PBKDF2 import. Mirrors Node's importGenericSecretKey ordering
|
|
2025
|
+
// (keys.js:945-971): extractable → usage → format → length. Callers pre-alias
|
|
2026
|
+
// 'raw-secret' / 'raw-public' to 'raw' via aliasKeyFormat
|
|
2027
|
+
// (webcrypto.js:798-808).
|
|
2028
|
+
const pbkdf2ImportKey = async (
|
|
1547
2029
|
{ name, length }: SubtleAlgorithm,
|
|
1548
2030
|
format: ImportFormat,
|
|
1549
2031
|
keyData: BufferLike | BinaryLike,
|
|
@@ -1551,33 +2033,70 @@ const importGenericSecretKey = async (
|
|
|
1551
2033
|
keyUsages: KeyUsage[],
|
|
1552
2034
|
): Promise<CryptoKey> => {
|
|
1553
2035
|
if (extractable) {
|
|
1554
|
-
throw
|
|
2036
|
+
throw lazyDOMException(`${name} keys are not extractable`, 'SyntaxError');
|
|
1555
2037
|
}
|
|
1556
2038
|
if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
|
|
1557
|
-
throw
|
|
2039
|
+
throw lazyDOMException(
|
|
2040
|
+
`Unsupported key usage for a ${name} key`,
|
|
2041
|
+
'SyntaxError',
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
2044
|
+
if (format !== 'raw') {
|
|
2045
|
+
throw lazyDOMException(
|
|
2046
|
+
`Unable to import ${name} key with format ${format}`,
|
|
2047
|
+
'NotSupportedError',
|
|
2048
|
+
);
|
|
1558
2049
|
}
|
|
1559
2050
|
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
2051
|
+
const checkLength =
|
|
2052
|
+
typeof keyData === 'string' || SBuffer.isBuffer(keyData)
|
|
2053
|
+
? keyData.length * 8
|
|
2054
|
+
: keyData.byteLength * 8;
|
|
2055
|
+
if (length !== undefined && length !== checkLength) {
|
|
2056
|
+
throw lazyDOMException('Invalid key length', 'DataError');
|
|
2057
|
+
}
|
|
1565
2058
|
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
: keyData.byteLength * 8;
|
|
2059
|
+
const keyObject = createSecretKey(keyData as BinaryLike);
|
|
2060
|
+
return new CryptoKey(keyObject, { name }, keyUsages, false);
|
|
2061
|
+
};
|
|
1570
2062
|
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
2063
|
+
// Argon2 import. Node gates the format at the dispatcher level — only
|
|
2064
|
+
// 'raw-secret' enters importGenericSecretKey (webcrypto.js:813-822). To match
|
|
2065
|
+
// that, format is the first check here; remaining ordering matches Node's
|
|
2066
|
+
// importGenericSecretKey.
|
|
2067
|
+
const argon2ImportKey = async (
|
|
2068
|
+
{ name, length }: SubtleAlgorithm,
|
|
2069
|
+
format: ImportFormat,
|
|
2070
|
+
keyData: BufferLike | BinaryLike,
|
|
2071
|
+
extractable: boolean,
|
|
2072
|
+
keyUsages: KeyUsage[],
|
|
2073
|
+
): Promise<CryptoKey> => {
|
|
2074
|
+
if (format !== 'raw-secret') {
|
|
2075
|
+
throw lazyDOMException(
|
|
2076
|
+
`Unable to import ${name} key with format ${format}`,
|
|
2077
|
+
'NotSupportedError',
|
|
2078
|
+
);
|
|
2079
|
+
}
|
|
2080
|
+
if (extractable) {
|
|
2081
|
+
throw lazyDOMException(`${name} keys are not extractable`, 'SyntaxError');
|
|
2082
|
+
}
|
|
2083
|
+
if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
|
|
2084
|
+
throw lazyDOMException(
|
|
2085
|
+
`Unsupported key usage for a ${name} key`,
|
|
2086
|
+
'SyntaxError',
|
|
2087
|
+
);
|
|
2088
|
+
}
|
|
1574
2089
|
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
2090
|
+
const checkLength =
|
|
2091
|
+
typeof keyData === 'string' || SBuffer.isBuffer(keyData)
|
|
2092
|
+
? keyData.length * 8
|
|
2093
|
+
: keyData.byteLength * 8;
|
|
2094
|
+
if (length !== undefined && length !== checkLength) {
|
|
2095
|
+
throw lazyDOMException('Invalid key length', 'DataError');
|
|
1578
2096
|
}
|
|
1579
2097
|
|
|
1580
|
-
|
|
2098
|
+
const keyObject = createSecretKey(keyData as BinaryLike);
|
|
2099
|
+
return new CryptoKey(keyObject, { name }, keyUsages, false);
|
|
1581
2100
|
};
|
|
1582
2101
|
|
|
1583
2102
|
const hkdfImportKey = async (
|
|
@@ -1588,6 +2107,13 @@ const hkdfImportKey = async (
|
|
|
1588
2107
|
keyUsages: KeyUsage[],
|
|
1589
2108
|
): Promise<CryptoKey> => {
|
|
1590
2109
|
const { name } = algorithm;
|
|
2110
|
+
// WebCrypto §28.7.6: HKDF keys are never extractable. The previous
|
|
2111
|
+
// implementation passed `extractable` through verbatim, allowing callers
|
|
2112
|
+
// to round-trip the input keying material via `exportKey` — defeating
|
|
2113
|
+
// the whole point of the deriveBits-only usage.
|
|
2114
|
+
if (extractable) {
|
|
2115
|
+
throw lazyDOMException(`${name} keys are not extractable`, 'SyntaxError');
|
|
2116
|
+
}
|
|
1591
2117
|
if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
|
|
1592
2118
|
throw new Error(`Unsupported key usage for a ${name} key`);
|
|
1593
2119
|
}
|
|
@@ -1595,7 +2121,7 @@ const hkdfImportKey = async (
|
|
|
1595
2121
|
switch (format) {
|
|
1596
2122
|
case 'raw': {
|
|
1597
2123
|
const keyObject = createSecretKey(keyData as BinaryLike);
|
|
1598
|
-
return new CryptoKey(keyObject, { name }, keyUsages,
|
|
2124
|
+
return new CryptoKey(keyObject, { name }, keyUsages, false);
|
|
1599
2125
|
}
|
|
1600
2126
|
default:
|
|
1601
2127
|
throw new Error(`Unable to import ${name} key with format ${format}`);
|
|
@@ -1820,7 +2346,11 @@ const signVerify = (
|
|
|
1820
2346
|
const usage: Operation = signature === undefined ? 'sign' : 'verify';
|
|
1821
2347
|
algorithm = normalizeAlgorithm(algorithm, usage);
|
|
1822
2348
|
|
|
1823
|
-
if (
|
|
2349
|
+
if (algorithm.name !== key.algorithm.name) {
|
|
2350
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
if (!key.usages.includes(usage)) {
|
|
1824
2354
|
throw lazyDOMException(
|
|
1825
2355
|
`Unable to use this key to ${usage}`,
|
|
1826
2356
|
'InvalidAccessError',
|
|
@@ -1842,6 +2372,18 @@ const signVerify = (
|
|
|
1842
2372
|
case 'ML-DSA-44':
|
|
1843
2373
|
case 'ML-DSA-65':
|
|
1844
2374
|
case 'ML-DSA-87':
|
|
2375
|
+
case 'SLH-DSA-SHA2-128s':
|
|
2376
|
+
case 'SLH-DSA-SHA2-128f':
|
|
2377
|
+
case 'SLH-DSA-SHA2-192s':
|
|
2378
|
+
case 'SLH-DSA-SHA2-192f':
|
|
2379
|
+
case 'SLH-DSA-SHA2-256s':
|
|
2380
|
+
case 'SLH-DSA-SHA2-256f':
|
|
2381
|
+
case 'SLH-DSA-SHAKE-128s':
|
|
2382
|
+
case 'SLH-DSA-SHAKE-128f':
|
|
2383
|
+
case 'SLH-DSA-SHAKE-192s':
|
|
2384
|
+
case 'SLH-DSA-SHAKE-192f':
|
|
2385
|
+
case 'SLH-DSA-SHAKE-256s':
|
|
2386
|
+
case 'SLH-DSA-SHAKE-256f':
|
|
1845
2387
|
return mldsaSignVerify(key, data, signature);
|
|
1846
2388
|
case 'KMAC128':
|
|
1847
2389
|
case 'KMAC256':
|
|
@@ -1853,23 +2395,16 @@ const signVerify = (
|
|
|
1853
2395
|
);
|
|
1854
2396
|
};
|
|
1855
2397
|
|
|
2398
|
+
// Algorithm-mismatch and usage checks live at the public-method call sites
|
|
2399
|
+
// (encrypt / decrypt / wrapKey / unwrapKey) so spec-mandated message and
|
|
2400
|
+
// ordering — algorithm-mismatch first, then usage — is preserved
|
|
2401
|
+
// (Node webcrypto.js, commit 4cb1f284136).
|
|
1856
2402
|
const cipherOrWrap = async (
|
|
1857
2403
|
mode: CipherOrWrapMode,
|
|
1858
2404
|
algorithm: EncryptDecryptParams,
|
|
1859
2405
|
key: CryptoKey,
|
|
1860
2406
|
data: ArrayBuffer,
|
|
1861
|
-
op: Operation,
|
|
1862
2407
|
): Promise<ArrayBuffer> => {
|
|
1863
|
-
if (
|
|
1864
|
-
key.algorithm.name !== algorithm.name ||
|
|
1865
|
-
!key.usages.includes(op as KeyUsage)
|
|
1866
|
-
) {
|
|
1867
|
-
throw lazyDOMException(
|
|
1868
|
-
'The requested operation is not valid for the provided key',
|
|
1869
|
-
'InvalidAccessError',
|
|
1870
|
-
);
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
2408
|
validateMaxBufferLength(data, 'data');
|
|
1874
2409
|
|
|
1875
2410
|
switch (algorithm.name) {
|
|
@@ -1924,6 +2459,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
|
|
|
1924
2459
|
'ML-DSA-44',
|
|
1925
2460
|
'ML-DSA-65',
|
|
1926
2461
|
'ML-DSA-87',
|
|
2462
|
+
...SLH_DSA_VARIANTS,
|
|
1927
2463
|
]),
|
|
1928
2464
|
verify: new Set([
|
|
1929
2465
|
'RSASSA-PKCS1-v1_5',
|
|
@@ -1937,6 +2473,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
|
|
|
1937
2473
|
'ML-DSA-44',
|
|
1938
2474
|
'ML-DSA-65',
|
|
1939
2475
|
'ML-DSA-87',
|
|
2476
|
+
...SLH_DSA_VARIANTS,
|
|
1940
2477
|
]),
|
|
1941
2478
|
digest: new Set([
|
|
1942
2479
|
'SHA-1',
|
|
@@ -1948,6 +2485,10 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
|
|
|
1948
2485
|
'SHA3-512',
|
|
1949
2486
|
'cSHAKE128',
|
|
1950
2487
|
'cSHAKE256',
|
|
2488
|
+
'TurboSHAKE128',
|
|
2489
|
+
'TurboSHAKE256',
|
|
2490
|
+
'KT128',
|
|
2491
|
+
'KT256',
|
|
1951
2492
|
]),
|
|
1952
2493
|
generateKey: new Set([
|
|
1953
2494
|
'RSASSA-PKCS1-v1_5',
|
|
@@ -1974,6 +2515,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
|
|
|
1974
2515
|
'ML-KEM-512',
|
|
1975
2516
|
'ML-KEM-768',
|
|
1976
2517
|
'ML-KEM-1024',
|
|
2518
|
+
...SLH_DSA_VARIANTS,
|
|
1977
2519
|
]),
|
|
1978
2520
|
importKey: new Set([
|
|
1979
2521
|
'RSASSA-PKCS1-v1_5',
|
|
@@ -2005,6 +2547,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
|
|
|
2005
2547
|
'ML-KEM-512',
|
|
2006
2548
|
'ML-KEM-768',
|
|
2007
2549
|
'ML-KEM-1024',
|
|
2550
|
+
...SLH_DSA_VARIANTS,
|
|
2008
2551
|
]),
|
|
2009
2552
|
exportKey: new Set([
|
|
2010
2553
|
'RSASSA-PKCS1-v1_5',
|
|
@@ -2031,6 +2574,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
|
|
|
2031
2574
|
'ML-KEM-512',
|
|
2032
2575
|
'ML-KEM-768',
|
|
2033
2576
|
'ML-KEM-1024',
|
|
2577
|
+
...SLH_DSA_VARIANTS,
|
|
2034
2578
|
]),
|
|
2035
2579
|
deriveBits: new Set([
|
|
2036
2580
|
'PBKDF2',
|
|
@@ -2066,7 +2610,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
|
|
|
2066
2610
|
decapsulateKey: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
|
|
2067
2611
|
};
|
|
2068
2612
|
|
|
2069
|
-
const ASYMMETRIC_ALGORITHMS = new Set([
|
|
2613
|
+
const ASYMMETRIC_ALGORITHMS = new Set<string>([
|
|
2070
2614
|
'RSASSA-PKCS1-v1_5',
|
|
2071
2615
|
'RSA-PSS',
|
|
2072
2616
|
'RSA-OAEP',
|
|
@@ -2082,52 +2626,230 @@ const ASYMMETRIC_ALGORITHMS = new Set([
|
|
|
2082
2626
|
'ML-KEM-512',
|
|
2083
2627
|
'ML-KEM-768',
|
|
2084
2628
|
'ML-KEM-1024',
|
|
2629
|
+
...SLH_DSA_VARIANTS,
|
|
2085
2630
|
]);
|
|
2086
2631
|
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2632
|
+
// Per-algorithm validators for deriveBits (mirrors Node's hkdf.js:141-149,
|
|
2633
|
+
// pbkdf2.js:96-105, argon2.js:194-209). Used by Subtle.supports to reject
|
|
2634
|
+
// length values that the actual deriveBits implementation would reject.
|
|
2635
|
+
function validateKdfDeriveBitsLength(
|
|
2636
|
+
length: number | null | undefined,
|
|
2637
|
+
algName: string,
|
|
2638
|
+
): void {
|
|
2639
|
+
if (length === null || length === undefined) {
|
|
2640
|
+
throw lazyDOMException('length cannot be null', 'OperationError');
|
|
2641
|
+
}
|
|
2642
|
+
if (length % 8) {
|
|
2643
|
+
throw lazyDOMException('length must be a multiple of 8', 'OperationError');
|
|
2644
|
+
}
|
|
2645
|
+
if (algName.startsWith('Argon2') && length < 32) {
|
|
2646
|
+
throw lazyDOMException('length must be >= 32', 'OperationError');
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
// Mirrors Node's webcrypto.js:1652-1731 `check`. Normalizes the algorithm,
|
|
2651
|
+
// looks it up in SUPPORTED_ALGORITHMS, and runs per-algorithm validation
|
|
2652
|
+
// (deriveBits length validators, HMAC+SHA3 generateKey rejection).
|
|
2653
|
+
// `op` is the operation key in SUPPORTED_ALGORITHMS — wrapKey/unwrapKey fall
|
|
2654
|
+
// back to encrypt/decrypt to mirror Node's normalize fallback.
|
|
2655
|
+
function supportsCheck(
|
|
2656
|
+
op: string,
|
|
2657
|
+
alg: SubtleAlgorithm | AnyAlgorithm,
|
|
2658
|
+
length?: number | null,
|
|
2659
|
+
): boolean {
|
|
2660
|
+
let normalizedAlgorithm: SubtleAlgorithm;
|
|
2661
|
+
try {
|
|
2662
|
+
normalizedAlgorithm = normalizeAlgorithm(alg, op as Operation);
|
|
2663
|
+
} catch {
|
|
2664
|
+
if (op === 'wrapKey') return supportsCheck('encrypt', alg);
|
|
2665
|
+
if (op === 'unwrapKey') return supportsCheck('decrypt', alg);
|
|
2666
|
+
return false;
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
const supported = SUPPORTED_ALGORITHMS[op];
|
|
2670
|
+
if (!supported || !supported.has(normalizedAlgorithm.name)) {
|
|
2671
|
+
if (op === 'wrapKey') return supportsCheck('encrypt', alg);
|
|
2672
|
+
if (op === 'unwrapKey') return supportsCheck('decrypt', alg);
|
|
2673
|
+
return false;
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
if (op === 'deriveBits') {
|
|
2677
|
+
const name = normalizedAlgorithm.name;
|
|
2678
|
+
if (name === 'HKDF' || name === 'PBKDF2' || name.startsWith('Argon2')) {
|
|
2679
|
+
try {
|
|
2680
|
+
validateKdfDeriveBitsLength(length, name);
|
|
2681
|
+
} catch {
|
|
2682
|
+
return false;
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
|
|
2687
|
+
if (op === 'generateKey' && normalizedAlgorithm.name === 'HMAC') {
|
|
2688
|
+
const hashName =
|
|
2689
|
+
typeof normalizedAlgorithm.hash === 'string'
|
|
2690
|
+
? normalizedAlgorithm.hash
|
|
2691
|
+
: (normalizedAlgorithm.hash as { name?: string } | undefined)?.name;
|
|
2692
|
+
if (
|
|
2693
|
+
normalizedAlgorithm.length === undefined &&
|
|
2694
|
+
typeof hashName === 'string' &&
|
|
2695
|
+
hashName.startsWith('SHA3-')
|
|
2696
|
+
) {
|
|
2100
2697
|
return false;
|
|
2101
2698
|
}
|
|
2699
|
+
}
|
|
2102
2700
|
|
|
2103
|
-
|
|
2701
|
+
return true;
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
function supportsImpl(
|
|
2705
|
+
operation: string,
|
|
2706
|
+
algorithm: SubtleAlgorithm | AnyAlgorithm,
|
|
2707
|
+
lengthOrAdditionalAlgorithm: unknown,
|
|
2708
|
+
): boolean {
|
|
2709
|
+
switch (operation) {
|
|
2710
|
+
case 'decapsulateBits':
|
|
2711
|
+
case 'decapsulateKey':
|
|
2712
|
+
case 'decrypt':
|
|
2713
|
+
case 'deriveBits':
|
|
2714
|
+
case 'deriveKey':
|
|
2715
|
+
case 'digest':
|
|
2716
|
+
case 'encapsulateBits':
|
|
2717
|
+
case 'encapsulateKey':
|
|
2718
|
+
case 'encrypt':
|
|
2719
|
+
case 'exportKey':
|
|
2720
|
+
case 'generateKey':
|
|
2721
|
+
case 'getPublicKey':
|
|
2722
|
+
case 'importKey':
|
|
2723
|
+
case 'sign':
|
|
2724
|
+
case 'unwrapKey':
|
|
2725
|
+
case 'verify':
|
|
2726
|
+
case 'wrapKey':
|
|
2727
|
+
break;
|
|
2728
|
+
default:
|
|
2729
|
+
return false;
|
|
2730
|
+
}
|
|
2104
2731
|
|
|
2105
|
-
|
|
2106
|
-
|
|
2732
|
+
let length: number | null | undefined;
|
|
2733
|
+
|
|
2734
|
+
if (operation === 'deriveKey') {
|
|
2735
|
+
// deriveKey decomposes to importKey of derived alg + deriveBits with that
|
|
2736
|
+
// alg's key length. Node webcrypto.js:1547-1563.
|
|
2737
|
+
if (lengthOrAdditionalAlgorithm != null) {
|
|
2738
|
+
const additional = lengthOrAdditionalAlgorithm as
|
|
2739
|
+
| SubtleAlgorithm
|
|
2740
|
+
| AnyAlgorithm;
|
|
2741
|
+
if (!supportsCheck('importKey', additional)) return false;
|
|
2742
|
+
try {
|
|
2743
|
+
length = getKeyLength(normalizeAlgorithm(additional, 'get key length'));
|
|
2744
|
+
} catch {
|
|
2745
|
+
return false;
|
|
2746
|
+
}
|
|
2747
|
+
return supportsCheck('deriveBits', algorithm, length);
|
|
2107
2748
|
}
|
|
2749
|
+
// No additional algorithm given — only check the deriveBits side.
|
|
2750
|
+
return supportsCheck('deriveBits', algorithm);
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
if (operation === 'wrapKey') {
|
|
2754
|
+
// wrapKey decomposes to encrypt of wrapping alg + exportKey of wrapped alg.
|
|
2755
|
+
// Node webcrypto.js:1564-1572.
|
|
2756
|
+
if (lengthOrAdditionalAlgorithm != null) {
|
|
2757
|
+
const additional = lengthOrAdditionalAlgorithm as
|
|
2758
|
+
| SubtleAlgorithm
|
|
2759
|
+
| AnyAlgorithm;
|
|
2760
|
+
if (!supportsCheck('exportKey', additional)) return false;
|
|
2761
|
+
}
|
|
2762
|
+
return supportsCheck('wrapKey', algorithm);
|
|
2763
|
+
}
|
|
2108
2764
|
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2765
|
+
if (operation === 'unwrapKey') {
|
|
2766
|
+
// unwrapKey decomposes to decrypt of wrapping alg + importKey of wrapped
|
|
2767
|
+
// alg. Node webcrypto.js:1573-1581.
|
|
2768
|
+
if (lengthOrAdditionalAlgorithm != null) {
|
|
2769
|
+
const additional = lengthOrAdditionalAlgorithm as
|
|
2770
|
+
| SubtleAlgorithm
|
|
2771
|
+
| AnyAlgorithm;
|
|
2772
|
+
if (!supportsCheck('importKey', additional)) return false;
|
|
2773
|
+
}
|
|
2774
|
+
return supportsCheck('unwrapKey', algorithm);
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
if (operation === 'deriveBits') {
|
|
2778
|
+
if (lengthOrAdditionalAlgorithm == null) {
|
|
2779
|
+
length = null;
|
|
2780
|
+
} else if (typeof lengthOrAdditionalAlgorithm === 'number') {
|
|
2781
|
+
length = lengthOrAdditionalAlgorithm;
|
|
2782
|
+
} else {
|
|
2783
|
+
return false;
|
|
2784
|
+
}
|
|
2785
|
+
return supportsCheck('deriveBits', algorithm, length);
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2788
|
+
if (operation === 'getPublicKey') {
|
|
2789
|
+
let normalized: SubtleAlgorithm;
|
|
2790
|
+
try {
|
|
2791
|
+
normalized = normalizeAlgorithm(algorithm, 'exportKey');
|
|
2792
|
+
} catch {
|
|
2793
|
+
return false;
|
|
2794
|
+
}
|
|
2795
|
+
return ASYMMETRIC_ALGORITHMS.has(normalized.name);
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
if (operation === 'encapsulateKey' || operation === 'decapsulateKey') {
|
|
2799
|
+
// sharedKeyAlgorithm must support importKey, with HMAC/KMAC limited to
|
|
2800
|
+
// length === undefined or 256 (Node webcrypto.js:1610-1645).
|
|
2801
|
+
const additional = lengthOrAdditionalAlgorithm as
|
|
2802
|
+
| SubtleAlgorithm
|
|
2803
|
+
| AnyAlgorithm;
|
|
2804
|
+
let normalizedAdd: SubtleAlgorithm;
|
|
2805
|
+
try {
|
|
2806
|
+
normalizedAdd = normalizeAlgorithm(additional, 'importKey');
|
|
2807
|
+
} catch {
|
|
2808
|
+
return false;
|
|
2809
|
+
}
|
|
2810
|
+
switch (normalizedAdd.name) {
|
|
2811
|
+
case 'AES-OCB':
|
|
2812
|
+
case 'AES-KW':
|
|
2813
|
+
case 'AES-GCM':
|
|
2814
|
+
case 'AES-CTR':
|
|
2815
|
+
case 'AES-CBC':
|
|
2816
|
+
case 'ChaCha20-Poly1305':
|
|
2817
|
+
case 'HKDF':
|
|
2818
|
+
case 'PBKDF2':
|
|
2819
|
+
case 'Argon2i':
|
|
2820
|
+
case 'Argon2d':
|
|
2821
|
+
case 'Argon2id':
|
|
2822
|
+
break;
|
|
2823
|
+
case 'HMAC':
|
|
2824
|
+
case 'KMAC128':
|
|
2825
|
+
case 'KMAC256': {
|
|
2826
|
+
const addLen = normalizedAdd.length;
|
|
2827
|
+
if (addLen !== undefined && addLen !== 256) return false;
|
|
2828
|
+
break;
|
|
2124
2829
|
}
|
|
2125
|
-
|
|
2830
|
+
default:
|
|
2831
|
+
return false;
|
|
2126
2832
|
}
|
|
2833
|
+
return supportsCheck(operation, algorithm);
|
|
2834
|
+
}
|
|
2127
2835
|
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2836
|
+
return supportsCheck(operation, algorithm);
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2839
|
+
export class Subtle {
|
|
2840
|
+
// Spec-compliant capability detector. Mirrors Node's webcrypto.js:1506-1649
|
|
2841
|
+
// `SubtleCrypto.supports`, including:
|
|
2842
|
+
// • composed-operation decomposition (deriveKey, wrapKey, unwrapKey,
|
|
2843
|
+
// encapsulateKey, decapsulateKey, getPublicKey)
|
|
2844
|
+
// • per-algorithm length validators for deriveBits (HKDF/PBKDF2/Argon2)
|
|
2845
|
+
// • HMAC + SHA3 generateKey with no length → false
|
|
2846
|
+
// Static-only per the WICG spec.
|
|
2847
|
+
static supports(
|
|
2848
|
+
operation: string,
|
|
2849
|
+
algorithm: SubtleAlgorithm | AnyAlgorithm,
|
|
2850
|
+
lengthOrAdditionalAlgorithm: unknown = null,
|
|
2851
|
+
): boolean {
|
|
2852
|
+
return supportsImpl(operation, algorithm, lengthOrAdditionalAlgorithm);
|
|
2131
2853
|
}
|
|
2132
2854
|
|
|
2133
2855
|
async decrypt(
|
|
@@ -2135,13 +2857,25 @@ export class Subtle {
|
|
|
2135
2857
|
key: CryptoKey,
|
|
2136
2858
|
data: BufferLike,
|
|
2137
2859
|
): Promise<ArrayBuffer> {
|
|
2138
|
-
|
|
2860
|
+
requireArgs(arguments.length, 3, 'decrypt');
|
|
2861
|
+
const normalizedAlgorithm = normalizeAlgorithm(
|
|
2862
|
+
algorithm,
|
|
2863
|
+
'decrypt',
|
|
2864
|
+
) as EncryptDecryptParams;
|
|
2865
|
+
if (normalizedAlgorithm.name !== key.algorithm.name) {
|
|
2866
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
2867
|
+
}
|
|
2868
|
+
if (!key.usages.includes('decrypt')) {
|
|
2869
|
+
throw lazyDOMException(
|
|
2870
|
+
'Unable to use this key to decrypt',
|
|
2871
|
+
'InvalidAccessError',
|
|
2872
|
+
);
|
|
2873
|
+
}
|
|
2139
2874
|
return cipherOrWrap(
|
|
2140
2875
|
CipherOrWrapMode.kWebCryptoCipherDecrypt,
|
|
2141
|
-
normalizedAlgorithm
|
|
2876
|
+
normalizedAlgorithm,
|
|
2142
2877
|
key,
|
|
2143
2878
|
bufferLikeToArrayBuffer(data),
|
|
2144
|
-
'decrypt',
|
|
2145
2879
|
);
|
|
2146
2880
|
}
|
|
2147
2881
|
|
|
@@ -2149,6 +2883,7 @@ export class Subtle {
|
|
|
2149
2883
|
algorithm: SubtleAlgorithm | AnyAlgorithm,
|
|
2150
2884
|
data: BufferLike,
|
|
2151
2885
|
): Promise<ArrayBuffer> {
|
|
2886
|
+
requireArgs(arguments.length, 2, 'digest');
|
|
2152
2887
|
const normalizedAlgorithm = normalizeAlgorithm(
|
|
2153
2888
|
algorithm,
|
|
2154
2889
|
'digest' as Operation,
|
|
@@ -2159,39 +2894,56 @@ export class Subtle {
|
|
|
2159
2894
|
async deriveBits(
|
|
2160
2895
|
algorithm: SubtleAlgorithm,
|
|
2161
2896
|
baseKey: CryptoKey,
|
|
2162
|
-
length: number,
|
|
2897
|
+
length: number | null = null,
|
|
2163
2898
|
): Promise<ArrayBuffer> {
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2899
|
+
requireArgs(arguments.length, 2, 'deriveBits');
|
|
2900
|
+
const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'deriveBits');
|
|
2901
|
+
// WebCrypto §SubtleCrypto.deriveBits step 11: throw InvalidAccessError
|
|
2902
|
+
// unless `baseKey.[[usages]]` contains "deriveBits" specifically. The
|
|
2903
|
+
// previous `deriveBits || deriveKey` accept-either branch silently
|
|
2904
|
+
// promoted deriveKey-only keys into deriveBits use, contradicting the
|
|
2905
|
+
// spec usage gate.
|
|
2906
|
+
if (!baseKey.usages.includes('deriveBits')) {
|
|
2907
|
+
throw lazyDOMException(
|
|
2908
|
+
'baseKey does not have deriveBits usage',
|
|
2909
|
+
'InvalidAccessError',
|
|
2910
|
+
);
|
|
2170
2911
|
}
|
|
2171
|
-
if (baseKey.algorithm.name !==
|
|
2172
|
-
throw
|
|
2173
|
-
|
|
2912
|
+
if (baseKey.algorithm.name !== normalizedAlgorithm.name) {
|
|
2913
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
2914
|
+
}
|
|
2915
|
+
switch (normalizedAlgorithm.name) {
|
|
2174
2916
|
case 'PBKDF2':
|
|
2175
|
-
|
|
2917
|
+
if (length === null) {
|
|
2918
|
+
throw lazyDOMException('length cannot be null', 'OperationError');
|
|
2919
|
+
}
|
|
2920
|
+
return pbkdf2DeriveBits(normalizedAlgorithm, baseKey, length);
|
|
2176
2921
|
case 'X25519':
|
|
2177
2922
|
// Fall through
|
|
2178
2923
|
case 'X448':
|
|
2179
|
-
return xDeriveBits(
|
|
2924
|
+
return xDeriveBits(normalizedAlgorithm, baseKey, length);
|
|
2180
2925
|
case 'ECDH':
|
|
2181
|
-
return ecDeriveBits(
|
|
2926
|
+
return ecDeriveBits(normalizedAlgorithm, baseKey, length);
|
|
2182
2927
|
case 'HKDF':
|
|
2928
|
+
if (length === null) {
|
|
2929
|
+
throw lazyDOMException('length cannot be null', 'OperationError');
|
|
2930
|
+
}
|
|
2183
2931
|
return hkdfDeriveBits(
|
|
2184
|
-
|
|
2932
|
+
normalizedAlgorithm as unknown as HkdfAlgorithm,
|
|
2185
2933
|
baseKey,
|
|
2186
2934
|
length,
|
|
2187
2935
|
);
|
|
2188
2936
|
case 'Argon2d':
|
|
2189
2937
|
case 'Argon2i':
|
|
2190
2938
|
case 'Argon2id':
|
|
2191
|
-
|
|
2939
|
+
if (length === null) {
|
|
2940
|
+
throw lazyDOMException('length cannot be null', 'OperationError');
|
|
2941
|
+
}
|
|
2942
|
+
return argon2DeriveBits(normalizedAlgorithm, baseKey, length);
|
|
2192
2943
|
}
|
|
2193
|
-
throw
|
|
2194
|
-
`'subtle.deriveBits()' for ${
|
|
2944
|
+
throw lazyDOMException(
|
|
2945
|
+
`'subtle.deriveBits()' for ${normalizedAlgorithm.name} is not implemented.`,
|
|
2946
|
+
'NotSupportedError',
|
|
2195
2947
|
);
|
|
2196
2948
|
}
|
|
2197
2949
|
|
|
@@ -2202,40 +2954,55 @@ export class Subtle {
|
|
|
2202
2954
|
extractable: boolean,
|
|
2203
2955
|
keyUsages: KeyUsage[],
|
|
2204
2956
|
): Promise<CryptoKey> {
|
|
2957
|
+
requireArgs(arguments.length, 5, 'deriveKey');
|
|
2958
|
+
const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'deriveBits');
|
|
2959
|
+
const normalizedDerivedKeyAlgorithm = normalizeAlgorithm(
|
|
2960
|
+
derivedKeyAlgorithm,
|
|
2961
|
+
'importKey',
|
|
2962
|
+
);
|
|
2963
|
+
|
|
2205
2964
|
// Validate baseKey usage
|
|
2206
|
-
if (
|
|
2207
|
-
!baseKey.usages.includes('deriveKey') &&
|
|
2208
|
-
!baseKey.usages.includes('deriveBits')
|
|
2209
|
-
) {
|
|
2965
|
+
if (!baseKey.usages.includes('deriveKey')) {
|
|
2210
2966
|
throw lazyDOMException(
|
|
2211
|
-
'baseKey does not have deriveKey
|
|
2967
|
+
'baseKey does not have deriveKey usage',
|
|
2212
2968
|
'InvalidAccessError',
|
|
2213
2969
|
);
|
|
2214
2970
|
}
|
|
2215
2971
|
|
|
2216
|
-
|
|
2217
|
-
|
|
2972
|
+
if (baseKey.algorithm.name !== normalizedAlgorithm.name) {
|
|
2973
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2976
|
+
// Calculate required key length (may be null for KDF-derived material).
|
|
2977
|
+
const length = getKeyLength(normalizedDerivedKeyAlgorithm);
|
|
2218
2978
|
|
|
2219
2979
|
// Step 1: Derive bits
|
|
2220
2980
|
let derivedBits: ArrayBuffer;
|
|
2221
|
-
|
|
2222
|
-
throw new Error('Key algorithm mismatch');
|
|
2223
|
-
|
|
2224
|
-
switch (algorithm.name) {
|
|
2981
|
+
switch (normalizedAlgorithm.name) {
|
|
2225
2982
|
case 'PBKDF2':
|
|
2226
|
-
|
|
2983
|
+
if (length === null) {
|
|
2984
|
+
throw lazyDOMException('length cannot be null', 'OperationError');
|
|
2985
|
+
}
|
|
2986
|
+
derivedBits = await pbkdf2DeriveBits(
|
|
2987
|
+
normalizedAlgorithm,
|
|
2988
|
+
baseKey,
|
|
2989
|
+
length,
|
|
2990
|
+
);
|
|
2227
2991
|
break;
|
|
2228
2992
|
case 'X25519':
|
|
2229
2993
|
// Fall through
|
|
2230
2994
|
case 'X448':
|
|
2231
|
-
derivedBits = await xDeriveBits(
|
|
2995
|
+
derivedBits = await xDeriveBits(normalizedAlgorithm, baseKey, length);
|
|
2232
2996
|
break;
|
|
2233
2997
|
case 'ECDH':
|
|
2234
|
-
derivedBits = await ecDeriveBits(
|
|
2998
|
+
derivedBits = await ecDeriveBits(normalizedAlgorithm, baseKey, length);
|
|
2235
2999
|
break;
|
|
2236
3000
|
case 'HKDF':
|
|
3001
|
+
if (length === null) {
|
|
3002
|
+
throw lazyDOMException('length cannot be null', 'OperationError');
|
|
3003
|
+
}
|
|
2237
3004
|
derivedBits = hkdfDeriveBits(
|
|
2238
|
-
|
|
3005
|
+
normalizedAlgorithm as unknown as HkdfAlgorithm,
|
|
2239
3006
|
baseKey,
|
|
2240
3007
|
length,
|
|
2241
3008
|
);
|
|
@@ -2243,17 +3010,22 @@ export class Subtle {
|
|
|
2243
3010
|
case 'Argon2d':
|
|
2244
3011
|
case 'Argon2i':
|
|
2245
3012
|
case 'Argon2id':
|
|
2246
|
-
|
|
3013
|
+
if (length === null) {
|
|
3014
|
+
throw lazyDOMException('length cannot be null', 'OperationError');
|
|
3015
|
+
}
|
|
3016
|
+
derivedBits = argon2DeriveBits(normalizedAlgorithm, baseKey, length);
|
|
2247
3017
|
break;
|
|
2248
3018
|
default:
|
|
2249
|
-
throw
|
|
2250
|
-
`'subtle.deriveKey()' for ${
|
|
3019
|
+
throw lazyDOMException(
|
|
3020
|
+
`'subtle.deriveKey()' for ${normalizedAlgorithm.name} is not implemented.`,
|
|
3021
|
+
'NotSupportedError',
|
|
2251
3022
|
);
|
|
2252
3023
|
}
|
|
2253
3024
|
|
|
2254
|
-
// Step 2: Import as key
|
|
3025
|
+
// Step 2: Import as key. Use 'raw-secret' so derived material flows into
|
|
3026
|
+
// AEADs / KMAC correctly — they reject plain 'raw' (Node webcrypto.js:381-385).
|
|
2255
3027
|
return this.importKey(
|
|
2256
|
-
'raw',
|
|
3028
|
+
'raw-secret',
|
|
2257
3029
|
derivedBits,
|
|
2258
3030
|
derivedKeyAlgorithm,
|
|
2259
3031
|
extractable,
|
|
@@ -2266,13 +3038,25 @@ export class Subtle {
|
|
|
2266
3038
|
key: CryptoKey,
|
|
2267
3039
|
data: BufferLike,
|
|
2268
3040
|
): Promise<ArrayBuffer> {
|
|
2269
|
-
|
|
3041
|
+
requireArgs(arguments.length, 3, 'encrypt');
|
|
3042
|
+
const normalizedAlgorithm = normalizeAlgorithm(
|
|
3043
|
+
algorithm,
|
|
3044
|
+
'encrypt',
|
|
3045
|
+
) as EncryptDecryptParams;
|
|
3046
|
+
if (normalizedAlgorithm.name !== key.algorithm.name) {
|
|
3047
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
3048
|
+
}
|
|
3049
|
+
if (!key.usages.includes('encrypt')) {
|
|
3050
|
+
throw lazyDOMException(
|
|
3051
|
+
'Unable to use this key to encrypt',
|
|
3052
|
+
'InvalidAccessError',
|
|
3053
|
+
);
|
|
3054
|
+
}
|
|
2270
3055
|
return cipherOrWrap(
|
|
2271
3056
|
CipherOrWrapMode.kWebCryptoCipherEncrypt,
|
|
2272
|
-
normalizedAlgorithm
|
|
3057
|
+
normalizedAlgorithm,
|
|
2273
3058
|
key,
|
|
2274
3059
|
bufferLikeToArrayBuffer(data),
|
|
2275
|
-
'encrypt',
|
|
2276
3060
|
);
|
|
2277
3061
|
}
|
|
2278
3062
|
|
|
@@ -2280,16 +3064,19 @@ export class Subtle {
|
|
|
2280
3064
|
format: ImportFormat,
|
|
2281
3065
|
key: CryptoKey,
|
|
2282
3066
|
): Promise<ArrayBuffer | JWK> {
|
|
2283
|
-
|
|
3067
|
+
requireArgs(arguments.length, 2, 'exportKey');
|
|
3068
|
+
if (!key.extractable)
|
|
3069
|
+
throw lazyDOMException('key is not extractable', 'InvalidAccessError');
|
|
2284
3070
|
|
|
2285
3071
|
if (format === 'raw-seed') {
|
|
2286
|
-
const pqcAlgos = [
|
|
3072
|
+
const pqcAlgos: string[] = [
|
|
2287
3073
|
'ML-KEM-512',
|
|
2288
3074
|
'ML-KEM-768',
|
|
2289
3075
|
'ML-KEM-1024',
|
|
2290
3076
|
'ML-DSA-44',
|
|
2291
3077
|
'ML-DSA-65',
|
|
2292
3078
|
'ML-DSA-87',
|
|
3079
|
+
...SLH_DSA_VARIANTS,
|
|
2293
3080
|
];
|
|
2294
3081
|
if (!pqcAlgos.includes(key.algorithm.name)) {
|
|
2295
3082
|
throw lazyDOMException(
|
|
@@ -2306,9 +3093,6 @@ export class Subtle {
|
|
|
2306
3093
|
return bufferLikeToArrayBuffer(key.keyObject.handle.exportKey());
|
|
2307
3094
|
}
|
|
2308
3095
|
|
|
2309
|
-
// Note: 'raw-seed' is handled above; do NOT normalize it here
|
|
2310
|
-
if (format === 'raw-secret' || format === 'raw-public') format = 'raw';
|
|
2311
|
-
|
|
2312
3096
|
switch (format) {
|
|
2313
3097
|
case 'spki':
|
|
2314
3098
|
return (await exportKeySpki(key)) as ArrayBuffer;
|
|
@@ -2317,7 +3101,9 @@ export class Subtle {
|
|
|
2317
3101
|
case 'jwk':
|
|
2318
3102
|
return exportKeyJWK(key) as JWK;
|
|
2319
3103
|
case 'raw':
|
|
2320
|
-
|
|
3104
|
+
case 'raw-secret':
|
|
3105
|
+
case 'raw-public':
|
|
3106
|
+
return exportKeyRaw(key, format) as ArrayBuffer;
|
|
2321
3107
|
}
|
|
2322
3108
|
}
|
|
2323
3109
|
|
|
@@ -2327,10 +3113,18 @@ export class Subtle {
|
|
|
2327
3113
|
wrappingKey: CryptoKey,
|
|
2328
3114
|
wrapAlgorithm: EncryptDecryptParams,
|
|
2329
3115
|
): Promise<ArrayBuffer> {
|
|
2330
|
-
|
|
3116
|
+
requireArgs(arguments.length, 4, 'wrapKey');
|
|
3117
|
+
const normalizedWrapAlgorithm = normalizeAlgorithm(
|
|
3118
|
+
wrapAlgorithm,
|
|
3119
|
+
'wrapKey',
|
|
3120
|
+
) as EncryptDecryptParams;
|
|
3121
|
+
|
|
3122
|
+
if (normalizedWrapAlgorithm.name !== wrappingKey.algorithm.name) {
|
|
3123
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
3124
|
+
}
|
|
2331
3125
|
if (!wrappingKey.usages.includes('wrapKey')) {
|
|
2332
3126
|
throw lazyDOMException(
|
|
2333
|
-
'
|
|
3127
|
+
'Unable to use this key to wrapKey',
|
|
2334
3128
|
'InvalidAccessError',
|
|
2335
3129
|
);
|
|
2336
3130
|
}
|
|
@@ -2345,7 +3139,7 @@ export class Subtle {
|
|
|
2345
3139
|
const buffer = SBuffer.from(jwkString, 'utf8');
|
|
2346
3140
|
|
|
2347
3141
|
// For AES-KW, pad to multiple of 8 bytes (accounting for null terminator)
|
|
2348
|
-
if (
|
|
3142
|
+
if (normalizedWrapAlgorithm.name === 'AES-KW') {
|
|
2349
3143
|
const length = buffer.length;
|
|
2350
3144
|
// Add 1 for null terminator, then pad to multiple of 8
|
|
2351
3145
|
const paddedLength = Math.ceil((length + 1) / 8) * 8;
|
|
@@ -2364,10 +3158,9 @@ export class Subtle {
|
|
|
2364
3158
|
// Step 3: Encrypt the exported key
|
|
2365
3159
|
return cipherOrWrap(
|
|
2366
3160
|
CipherOrWrapMode.kWebCryptoCipherEncrypt,
|
|
2367
|
-
|
|
3161
|
+
normalizedWrapAlgorithm,
|
|
2368
3162
|
wrappingKey,
|
|
2369
3163
|
keyData,
|
|
2370
|
-
'wrapKey',
|
|
2371
3164
|
);
|
|
2372
3165
|
}
|
|
2373
3166
|
|
|
@@ -2380,10 +3173,18 @@ export class Subtle {
|
|
|
2380
3173
|
extractable: boolean,
|
|
2381
3174
|
keyUsages: KeyUsage[],
|
|
2382
3175
|
): Promise<CryptoKey> {
|
|
2383
|
-
|
|
3176
|
+
requireArgs(arguments.length, 7, 'unwrapKey');
|
|
3177
|
+
const normalizedUnwrapAlgorithm = normalizeAlgorithm(
|
|
3178
|
+
unwrapAlgorithm,
|
|
3179
|
+
'unwrapKey',
|
|
3180
|
+
) as EncryptDecryptParams;
|
|
3181
|
+
|
|
3182
|
+
if (normalizedUnwrapAlgorithm.name !== unwrappingKey.algorithm.name) {
|
|
3183
|
+
throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
|
|
3184
|
+
}
|
|
2384
3185
|
if (!unwrappingKey.usages.includes('unwrapKey')) {
|
|
2385
3186
|
throw lazyDOMException(
|
|
2386
|
-
'
|
|
3187
|
+
'Unable to use this key to unwrapKey',
|
|
2387
3188
|
'InvalidAccessError',
|
|
2388
3189
|
);
|
|
2389
3190
|
}
|
|
@@ -2391,10 +3192,9 @@ export class Subtle {
|
|
|
2391
3192
|
// Step 1: Decrypt the wrapped key
|
|
2392
3193
|
const decrypted = await cipherOrWrap(
|
|
2393
3194
|
CipherOrWrapMode.kWebCryptoCipherDecrypt,
|
|
2394
|
-
|
|
3195
|
+
normalizedUnwrapAlgorithm,
|
|
2395
3196
|
unwrappingKey,
|
|
2396
3197
|
bufferLikeToArrayBuffer(wrappedKey),
|
|
2397
|
-
'unwrapKey',
|
|
2398
3198
|
);
|
|
2399
3199
|
|
|
2400
3200
|
// Step 2: Convert to appropriate format
|
|
@@ -2403,7 +3203,7 @@ export class Subtle {
|
|
|
2403
3203
|
const buffer = SBuffer.from(decrypted);
|
|
2404
3204
|
// For AES-KW, the data may be padded - find the null terminator
|
|
2405
3205
|
let jwkString: string;
|
|
2406
|
-
if (
|
|
3206
|
+
if (normalizedUnwrapAlgorithm.name === 'AES-KW') {
|
|
2407
3207
|
// Find the null terminator (if present) to get the original string
|
|
2408
3208
|
const nullIndex = buffer.indexOf(0);
|
|
2409
3209
|
if (nullIndex !== -1) {
|
|
@@ -2435,6 +3235,7 @@ export class Subtle {
|
|
|
2435
3235
|
extractable: boolean,
|
|
2436
3236
|
keyUsages: KeyUsage[],
|
|
2437
3237
|
): Promise<CryptoKey | CryptoKeyPair> {
|
|
3238
|
+
requireArgs(arguments.length, 3, 'generateKey');
|
|
2438
3239
|
algorithm = normalizeAlgorithm(algorithm, 'generateKey');
|
|
2439
3240
|
let result: CryptoKey | CryptoKeyPair;
|
|
2440
3241
|
switch (algorithm.name) {
|
|
@@ -2521,6 +3322,25 @@ export class Subtle {
|
|
|
2521
3322
|
);
|
|
2522
3323
|
checkCryptoKeyPairUsages(result as CryptoKeyPair);
|
|
2523
3324
|
break;
|
|
3325
|
+
case 'SLH-DSA-SHA2-128s':
|
|
3326
|
+
case 'SLH-DSA-SHA2-128f':
|
|
3327
|
+
case 'SLH-DSA-SHA2-192s':
|
|
3328
|
+
case 'SLH-DSA-SHA2-192f':
|
|
3329
|
+
case 'SLH-DSA-SHA2-256s':
|
|
3330
|
+
case 'SLH-DSA-SHA2-256f':
|
|
3331
|
+
case 'SLH-DSA-SHAKE-128s':
|
|
3332
|
+
case 'SLH-DSA-SHAKE-128f':
|
|
3333
|
+
case 'SLH-DSA-SHAKE-192s':
|
|
3334
|
+
case 'SLH-DSA-SHAKE-192f':
|
|
3335
|
+
case 'SLH-DSA-SHAKE-256s':
|
|
3336
|
+
case 'SLH-DSA-SHAKE-256f':
|
|
3337
|
+
result = await slhdsa_generateKeyPairWebCrypto(
|
|
3338
|
+
algorithm.name as SlhDsaVariant,
|
|
3339
|
+
extractable,
|
|
3340
|
+
keyUsages,
|
|
3341
|
+
);
|
|
3342
|
+
checkCryptoKeyPairUsages(result as CryptoKeyPair);
|
|
3343
|
+
break;
|
|
2524
3344
|
case 'X25519':
|
|
2525
3345
|
// Fall through
|
|
2526
3346
|
case 'X448':
|
|
@@ -2557,6 +3377,7 @@ export class Subtle {
|
|
|
2557
3377
|
key: CryptoKey,
|
|
2558
3378
|
keyUsages: KeyUsage[],
|
|
2559
3379
|
): Promise<CryptoKey> {
|
|
3380
|
+
requireArgs(arguments.length, 2, 'getPublicKey');
|
|
2560
3381
|
if (key.type === 'secret') {
|
|
2561
3382
|
throw lazyDOMException('key must be a private key', 'NotSupportedError');
|
|
2562
3383
|
}
|
|
@@ -2575,8 +3396,11 @@ export class Subtle {
|
|
|
2575
3396
|
extractable: boolean,
|
|
2576
3397
|
keyUsages: KeyUsage[],
|
|
2577
3398
|
): Promise<CryptoKey> {
|
|
2578
|
-
|
|
2579
|
-
|
|
3399
|
+
requireArgs(arguments.length, 5, 'importKey');
|
|
3400
|
+
// Per-algorithm format handling. Some algorithms alias raw-secret/raw-public
|
|
3401
|
+
// to 'raw' (RSA, EC, Ed/X, HMAC, HKDF, PBKDF2); others demand the
|
|
3402
|
+
// disambiguated form (KMAC, AES-OCB, ChaCha20-Poly1305, Argon2, ML-DSA,
|
|
3403
|
+
// ML-KEM). 'raw-seed' is never normalized — PQC import handles it directly.
|
|
2580
3404
|
const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'importKey');
|
|
2581
3405
|
let result: CryptoKey;
|
|
2582
3406
|
switch (normalizedAlgorithm.name) {
|
|
@@ -2586,7 +3410,7 @@ export class Subtle {
|
|
|
2586
3410
|
// Fall through
|
|
2587
3411
|
case 'RSA-OAEP':
|
|
2588
3412
|
result = rsaImportKey(
|
|
2589
|
-
format,
|
|
3413
|
+
aliasKeyFormat(format),
|
|
2590
3414
|
data as BufferLike | JWK,
|
|
2591
3415
|
normalizedAlgorithm,
|
|
2592
3416
|
extractable,
|
|
@@ -2597,7 +3421,7 @@ export class Subtle {
|
|
|
2597
3421
|
// Fall through
|
|
2598
3422
|
case 'ECDH':
|
|
2599
3423
|
result = ecImportKey(
|
|
2600
|
-
format,
|
|
3424
|
+
aliasKeyFormat(format),
|
|
2601
3425
|
data,
|
|
2602
3426
|
normalizedAlgorithm,
|
|
2603
3427
|
extractable,
|
|
@@ -2605,6 +3429,9 @@ export class Subtle {
|
|
|
2605
3429
|
);
|
|
2606
3430
|
break;
|
|
2607
3431
|
case 'HMAC':
|
|
3432
|
+
// No aliasing — Node routes HMAC straight into mac.js, which accepts
|
|
3433
|
+
// 'raw' / 'raw-secret' / 'jwk' and rejects everything else
|
|
3434
|
+
// (webcrypto.js:774-781, mac.js:136-174).
|
|
2608
3435
|
result = await hmacImportKey(
|
|
2609
3436
|
normalizedAlgorithm,
|
|
2610
3437
|
format,
|
|
@@ -2644,10 +3471,18 @@ export class Subtle {
|
|
|
2644
3471
|
);
|
|
2645
3472
|
break;
|
|
2646
3473
|
case 'PBKDF2':
|
|
3474
|
+
result = await pbkdf2ImportKey(
|
|
3475
|
+
normalizedAlgorithm,
|
|
3476
|
+
aliasKeyFormat(format),
|
|
3477
|
+
data as BufferLike | BinaryLike,
|
|
3478
|
+
extractable,
|
|
3479
|
+
keyUsages,
|
|
3480
|
+
);
|
|
3481
|
+
break;
|
|
2647
3482
|
case 'Argon2d':
|
|
2648
3483
|
case 'Argon2i':
|
|
2649
3484
|
case 'Argon2id':
|
|
2650
|
-
result = await
|
|
3485
|
+
result = await argon2ImportKey(
|
|
2651
3486
|
normalizedAlgorithm,
|
|
2652
3487
|
format,
|
|
2653
3488
|
data as BufferLike | BinaryLike,
|
|
@@ -2657,7 +3492,7 @@ export class Subtle {
|
|
|
2657
3492
|
break;
|
|
2658
3493
|
case 'HKDF':
|
|
2659
3494
|
result = await hkdfImportKey(
|
|
2660
|
-
format,
|
|
3495
|
+
aliasKeyFormat(format),
|
|
2661
3496
|
data as BufferLike | BinaryLike,
|
|
2662
3497
|
normalizedAlgorithm,
|
|
2663
3498
|
extractable,
|
|
@@ -2672,6 +3507,26 @@ export class Subtle {
|
|
|
2672
3507
|
// Fall through
|
|
2673
3508
|
case 'Ed448':
|
|
2674
3509
|
result = edImportKey(
|
|
3510
|
+
aliasKeyFormat(format),
|
|
3511
|
+
data as BufferLike | JWK,
|
|
3512
|
+
normalizedAlgorithm,
|
|
3513
|
+
extractable,
|
|
3514
|
+
keyUsages,
|
|
3515
|
+
);
|
|
3516
|
+
break;
|
|
3517
|
+
case 'SLH-DSA-SHA2-128s':
|
|
3518
|
+
case 'SLH-DSA-SHA2-128f':
|
|
3519
|
+
case 'SLH-DSA-SHA2-192s':
|
|
3520
|
+
case 'SLH-DSA-SHA2-192f':
|
|
3521
|
+
case 'SLH-DSA-SHA2-256s':
|
|
3522
|
+
case 'SLH-DSA-SHA2-256f':
|
|
3523
|
+
case 'SLH-DSA-SHAKE-128s':
|
|
3524
|
+
case 'SLH-DSA-SHAKE-128f':
|
|
3525
|
+
case 'SLH-DSA-SHAKE-192s':
|
|
3526
|
+
case 'SLH-DSA-SHAKE-192f':
|
|
3527
|
+
case 'SLH-DSA-SHAKE-256s':
|
|
3528
|
+
case 'SLH-DSA-SHAKE-256f':
|
|
3529
|
+
result = slhdsaImportKey(
|
|
2675
3530
|
format,
|
|
2676
3531
|
data as BufferLike | JWK,
|
|
2677
3532
|
normalizedAlgorithm,
|
|
@@ -2686,7 +3541,7 @@ export class Subtle {
|
|
|
2686
3541
|
case 'ML-DSA-87':
|
|
2687
3542
|
result = mldsaImportKey(
|
|
2688
3543
|
format,
|
|
2689
|
-
data as BufferLike,
|
|
3544
|
+
data as BufferLike | JWK,
|
|
2690
3545
|
normalizedAlgorithm,
|
|
2691
3546
|
extractable,
|
|
2692
3547
|
keyUsages,
|
|
@@ -2699,7 +3554,7 @@ export class Subtle {
|
|
|
2699
3554
|
case 'ML-KEM-1024':
|
|
2700
3555
|
result = mlkemImportKey(
|
|
2701
3556
|
format,
|
|
2702
|
-
data as BufferLike,
|
|
3557
|
+
data as BufferLike | JWK,
|
|
2703
3558
|
normalizedAlgorithm,
|
|
2704
3559
|
extractable,
|
|
2705
3560
|
keyUsages,
|
|
@@ -2728,6 +3583,7 @@ export class Subtle {
|
|
|
2728
3583
|
key: CryptoKey,
|
|
2729
3584
|
data: BufferLike,
|
|
2730
3585
|
): Promise<ArrayBuffer> {
|
|
3586
|
+
requireArgs(arguments.length, 3, 'sign');
|
|
2731
3587
|
return signVerify(
|
|
2732
3588
|
normalizeAlgorithm(algorithm, 'sign'),
|
|
2733
3589
|
key,
|
|
@@ -2741,6 +3597,7 @@ export class Subtle {
|
|
|
2741
3597
|
signature: BufferLike,
|
|
2742
3598
|
data: BufferLike,
|
|
2743
3599
|
): Promise<boolean> {
|
|
3600
|
+
requireArgs(arguments.length, 4, 'verify');
|
|
2744
3601
|
return signVerify(
|
|
2745
3602
|
normalizeAlgorithm(algorithm, 'verify'),
|
|
2746
3603
|
key,
|
|
@@ -2812,6 +3669,7 @@ export class Subtle {
|
|
|
2812
3669
|
algorithm: SubtleAlgorithm,
|
|
2813
3670
|
key: CryptoKey,
|
|
2814
3671
|
): Promise<EncapsulateResult> {
|
|
3672
|
+
requireArgs(arguments.length, 2, 'encapsulateBits');
|
|
2815
3673
|
if (!key.usages.includes('encapsulateBits')) {
|
|
2816
3674
|
throw lazyDOMException(
|
|
2817
3675
|
'Key does not have encapsulateBits usage',
|
|
@@ -2829,6 +3687,7 @@ export class Subtle {
|
|
|
2829
3687
|
extractable: boolean,
|
|
2830
3688
|
usages: KeyUsage[],
|
|
2831
3689
|
): Promise<{ key: CryptoKey; ciphertext: ArrayBuffer }> {
|
|
3690
|
+
requireArgs(arguments.length, 5, 'encapsulateKey');
|
|
2832
3691
|
if (!key.usages.includes('encapsulateKey')) {
|
|
2833
3692
|
throw lazyDOMException(
|
|
2834
3693
|
'Key does not have encapsulateKey usage',
|
|
@@ -2837,8 +3696,10 @@ export class Subtle {
|
|
|
2837
3696
|
}
|
|
2838
3697
|
|
|
2839
3698
|
const { sharedKey, ciphertext } = this._encapsulateCore(algorithm, key);
|
|
3699
|
+
// Node imports the encapsulated shared bits as 'raw-secret'
|
|
3700
|
+
// (webcrypto.js:1370-1374) so AEADs / KMAC accept the result.
|
|
2840
3701
|
const importedKey = await this.importKey(
|
|
2841
|
-
'raw',
|
|
3702
|
+
'raw-secret',
|
|
2842
3703
|
sharedKey,
|
|
2843
3704
|
sharedKeyAlgorithm,
|
|
2844
3705
|
extractable,
|
|
@@ -2853,6 +3714,7 @@ export class Subtle {
|
|
|
2853
3714
|
key: CryptoKey,
|
|
2854
3715
|
ciphertext: BufferLike,
|
|
2855
3716
|
): Promise<ArrayBuffer> {
|
|
3717
|
+
requireArgs(arguments.length, 3, 'decapsulateBits');
|
|
2856
3718
|
if (!key.usages.includes('decapsulateBits')) {
|
|
2857
3719
|
throw lazyDOMException(
|
|
2858
3720
|
'Key does not have decapsulateBits usage',
|
|
@@ -2871,6 +3733,7 @@ export class Subtle {
|
|
|
2871
3733
|
extractable: boolean,
|
|
2872
3734
|
usages: KeyUsage[],
|
|
2873
3735
|
): Promise<CryptoKey> {
|
|
3736
|
+
requireArgs(arguments.length, 6, 'decapsulateKey');
|
|
2874
3737
|
if (!key.usages.includes('decapsulateKey')) {
|
|
2875
3738
|
throw lazyDOMException(
|
|
2876
3739
|
'Key does not have decapsulateKey usage',
|
|
@@ -2879,8 +3742,10 @@ export class Subtle {
|
|
|
2879
3742
|
}
|
|
2880
3743
|
|
|
2881
3744
|
const sharedKey = this._decapsulateCore(algorithm, key, ciphertext);
|
|
3745
|
+
// Node imports the decapsulated shared bits as 'raw-secret'
|
|
3746
|
+
// (webcrypto.js:1490-1494).
|
|
2882
3747
|
return this.importKey(
|
|
2883
|
-
'raw',
|
|
3748
|
+
'raw-secret',
|
|
2884
3749
|
sharedKey,
|
|
2885
3750
|
sharedKeyAlgorithm,
|
|
2886
3751
|
extractable,
|
|
@@ -2891,8 +3756,14 @@ export class Subtle {
|
|
|
2891
3756
|
|
|
2892
3757
|
export const subtle = new Subtle();
|
|
2893
3758
|
|
|
2894
|
-
|
|
3759
|
+
// Returns the number of bits to derive for an `importKey` algorithm, mirroring
|
|
3760
|
+
// Node's webcrypto.js:269-306 `getKeyLength`. Returns null for KDF algorithms
|
|
3761
|
+
// (HKDF / PBKDF2 / Argon2) — those carry their full derived secret without a
|
|
3762
|
+
// fixed key length. Throws OperationError on invalid AES / HMAC inputs rather
|
|
3763
|
+
// than silently coercing to a default (Node commit 4cb1f284136 behavior).
|
|
3764
|
+
function getKeyLength(algorithm: SubtleAlgorithm): number | null {
|
|
2895
3765
|
const name = algorithm.name;
|
|
3766
|
+
const length = (algorithm as { length?: number }).length;
|
|
2896
3767
|
|
|
2897
3768
|
switch (name) {
|
|
2898
3769
|
case 'AES-CTR':
|
|
@@ -2900,18 +3771,38 @@ function getKeyLength(algorithm: SubtleAlgorithm): number {
|
|
|
2900
3771
|
case 'AES-GCM':
|
|
2901
3772
|
case 'AES-KW':
|
|
2902
3773
|
case 'AES-OCB':
|
|
2903
|
-
|
|
2904
|
-
|
|
3774
|
+
if (length !== 128 && length !== 192 && length !== 256) {
|
|
3775
|
+
throw lazyDOMException('Invalid key length', 'OperationError');
|
|
3776
|
+
}
|
|
3777
|
+
return length;
|
|
2905
3778
|
|
|
2906
3779
|
case 'HMAC': {
|
|
2907
|
-
|
|
2908
|
-
|
|
3780
|
+
if (length === undefined) {
|
|
3781
|
+
return getHmacBlockSize(
|
|
3782
|
+
(algorithm.hash as { name?: string } | undefined)?.name ??
|
|
3783
|
+
(algorithm.hash as string | undefined),
|
|
3784
|
+
);
|
|
3785
|
+
}
|
|
3786
|
+
if (typeof length === 'number' && length !== 0) {
|
|
3787
|
+
return length;
|
|
3788
|
+
}
|
|
3789
|
+
throw lazyDOMException('Invalid key length', 'OperationError');
|
|
2909
3790
|
}
|
|
2910
3791
|
|
|
2911
3792
|
case 'KMAC128':
|
|
2912
|
-
return
|
|
3793
|
+
return typeof length === 'number' ? length : 128;
|
|
2913
3794
|
case 'KMAC256':
|
|
2914
|
-
return
|
|
3795
|
+
return typeof length === 'number' ? length : 256;
|
|
3796
|
+
|
|
3797
|
+
case 'ChaCha20-Poly1305':
|
|
3798
|
+
return 256;
|
|
3799
|
+
|
|
3800
|
+
case 'HKDF':
|
|
3801
|
+
case 'PBKDF2':
|
|
3802
|
+
case 'Argon2d':
|
|
3803
|
+
case 'Argon2i':
|
|
3804
|
+
case 'Argon2id':
|
|
3805
|
+
return null;
|
|
2915
3806
|
|
|
2916
3807
|
default:
|
|
2917
3808
|
throw lazyDOMException(
|
|
@@ -2920,3 +3811,25 @@ function getKeyLength(algorithm: SubtleAlgorithm): number {
|
|
|
2920
3811
|
);
|
|
2921
3812
|
}
|
|
2922
3813
|
}
|
|
3814
|
+
|
|
3815
|
+
function getHmacBlockSize(name: string | undefined): number {
|
|
3816
|
+
switch (name) {
|
|
3817
|
+
case 'SHA-1':
|
|
3818
|
+
case 'SHA-256':
|
|
3819
|
+
return 512;
|
|
3820
|
+
case 'SHA-384':
|
|
3821
|
+
case 'SHA-512':
|
|
3822
|
+
return 1024;
|
|
3823
|
+
case 'SHA3-256':
|
|
3824
|
+
case 'SHA3-384':
|
|
3825
|
+
case 'SHA3-512':
|
|
3826
|
+
// SHA-3 / HMAC interaction undefined — Node throws here too
|
|
3827
|
+
// (webcrypto-modern-algos issue #23).
|
|
3828
|
+
throw lazyDOMException(
|
|
3829
|
+
'Explicit algorithm length member is required',
|
|
3830
|
+
'NotSupportedError',
|
|
3831
|
+
);
|
|
3832
|
+
default:
|
|
3833
|
+
throw lazyDOMException('Invalid key length', 'OperationError');
|
|
3834
|
+
}
|
|
3835
|
+
}
|