react-native-quick-crypto 1.0.0 → 1.0.1

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.
Files changed (81) hide show
  1. package/QuickCrypto.podspec +14 -5
  2. package/android/CMakeLists.txt +4 -2
  3. package/android/build.gradle +1 -1
  4. package/cpp/cipher/HybridCipher.cpp +3 -2
  5. package/cpp/cipher/HybridRsaCipher.cpp +20 -1
  6. package/cpp/keys/HybridKeyObjectHandle.cpp +8 -0
  7. package/cpp/keys/KeyObjectData.hpp +1 -1
  8. package/cpp/mldsa/HybridMlDsaKeyPair.cpp +264 -0
  9. package/cpp/mldsa/HybridMlDsaKeyPair.hpp +47 -0
  10. package/cpp/sign/HybridSignHandle.cpp +97 -22
  11. package/cpp/sign/HybridVerifyHandle.cpp +90 -21
  12. package/deps/ncrypto/.bazelignore +4 -0
  13. package/deps/ncrypto/.bazelrc +2 -0
  14. package/deps/ncrypto/.bazelversion +1 -0
  15. package/deps/ncrypto/.clang-format +111 -0
  16. package/deps/ncrypto/.github/workflows/bazel.yml +58 -0
  17. package/deps/ncrypto/.github/workflows/linter.yml +38 -0
  18. package/deps/ncrypto/.github/workflows/macos.yml +43 -0
  19. package/deps/ncrypto/.github/workflows/ubuntu.yml +46 -0
  20. package/deps/ncrypto/.github/workflows/visual-studio.yml +49 -0
  21. package/deps/ncrypto/.python-version +1 -0
  22. package/deps/ncrypto/BUILD.bazel +36 -0
  23. package/deps/ncrypto/CMakeLists.txt +55 -0
  24. package/deps/ncrypto/LICENSE +21 -0
  25. package/deps/ncrypto/MODULE.bazel +1 -0
  26. package/deps/ncrypto/MODULE.bazel.lock +280 -0
  27. package/deps/ncrypto/README.md +18 -0
  28. package/deps/ncrypto/WORKSPACE +15 -0
  29. package/deps/ncrypto/cmake/CPM.cmake +1225 -0
  30. package/deps/ncrypto/cmake/ncrypto-flags.cmake +16 -0
  31. package/deps/ncrypto/include/dh-primes.h +67 -0
  32. package/deps/ncrypto/{ncrypto.h → include/ncrypto.h} +361 -89
  33. package/deps/ncrypto/patches/0001-Expose-libdecrepit-so-NodeJS-can-use-it-for-ncrypto.patch +28 -0
  34. package/deps/ncrypto/pyproject.toml +38 -0
  35. package/deps/ncrypto/src/CMakeLists.txt +15 -0
  36. package/deps/ncrypto/src/engine.cpp +93 -0
  37. package/deps/ncrypto/{ncrypto.cc → src/ncrypto.cpp} +1168 -234
  38. package/deps/ncrypto/tests/BUILD.bazel +9 -0
  39. package/deps/ncrypto/tests/CMakeLists.txt +7 -0
  40. package/deps/ncrypto/tests/basic.cpp +86 -0
  41. package/deps/ncrypto/tools/run-clang-format.sh +42 -0
  42. package/lib/commonjs/keys/classes.js +6 -0
  43. package/lib/commonjs/keys/classes.js.map +1 -1
  44. package/lib/commonjs/mldsa.js +69 -0
  45. package/lib/commonjs/mldsa.js.map +1 -0
  46. package/lib/commonjs/specs/mlDsaKeyPair.nitro.js +6 -0
  47. package/lib/commonjs/specs/mlDsaKeyPair.nitro.js.map +1 -0
  48. package/lib/commonjs/subtle.js +111 -6
  49. package/lib/commonjs/subtle.js.map +1 -1
  50. package/lib/commonjs/utils/types.js.map +1 -1
  51. package/lib/module/keys/classes.js +6 -0
  52. package/lib/module/keys/classes.js.map +1 -1
  53. package/lib/module/mldsa.js +63 -0
  54. package/lib/module/mldsa.js.map +1 -0
  55. package/lib/module/specs/mlDsaKeyPair.nitro.js +4 -0
  56. package/lib/module/specs/mlDsaKeyPair.nitro.js.map +1 -0
  57. package/lib/module/subtle.js +111 -6
  58. package/lib/module/subtle.js.map +1 -1
  59. package/lib/module/utils/types.js.map +1 -1
  60. package/lib/tsconfig.tsbuildinfo +1 -1
  61. package/lib/typescript/keys/classes.d.ts +2 -0
  62. package/lib/typescript/keys/classes.d.ts.map +1 -1
  63. package/lib/typescript/mldsa.d.ts +18 -0
  64. package/lib/typescript/mldsa.d.ts.map +1 -0
  65. package/lib/typescript/specs/mlDsaKeyPair.nitro.d.ts +16 -0
  66. package/lib/typescript/specs/mlDsaKeyPair.nitro.d.ts.map +1 -0
  67. package/lib/typescript/subtle.d.ts.map +1 -1
  68. package/lib/typescript/utils/types.d.ts +5 -3
  69. package/lib/typescript/utils/types.d.ts.map +1 -1
  70. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +1 -0
  71. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +10 -0
  72. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +10 -0
  73. package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +12 -0
  74. package/nitrogen/generated/shared/c++/HybridMlDsaKeyPairSpec.cpp +29 -0
  75. package/nitrogen/generated/shared/c++/HybridMlDsaKeyPairSpec.hpp +73 -0
  76. package/package.json +7 -3
  77. package/src/keys/classes.ts +9 -0
  78. package/src/mldsa.ts +125 -0
  79. package/src/specs/mlDsaKeyPair.nitro.ts +29 -0
  80. package/src/subtle.ts +148 -8
  81. package/src/utils/types.ts +11 -3
package/src/subtle.ts CHANGED
@@ -42,6 +42,7 @@ import { getRandomValues } from './random';
42
42
  import { createHmac } from './hmac';
43
43
  import { createSign, createVerify } from './keys/signVerify';
44
44
  import { ed_generateKeyPairWebCrypto, Ed } from './ed';
45
+ import { mldsa_generateKeyPairWebCrypto, type MlDsaVariant } from './mldsa';
45
46
  // import { pbkdf2DeriveBits } from './pbkdf2';
46
47
  // import { aesCipher, aesGenerateKey, aesImportKey, getAlgorithmName } from './aes';
47
48
  // import { rsaCipher, rsaExportKey, rsaImportKey, rsaKeyGenerate } from './rsa';
@@ -469,10 +470,11 @@ async function hmacGenerateKey(
469
470
  // Create secret key
470
471
  const keyObject = createSecretKey(keyBytes);
471
472
 
472
- // Construct algorithm object
473
+ // Construct algorithm object with hash normalized to { name: string } format per WebCrypto spec
474
+ const webCryptoHashName = normalizeHashName(hash, HashContext.WebCrypto);
473
475
  const keyAlgorithm: SubtleAlgorithm = {
474
476
  name: 'HMAC',
475
- hash: hashName,
477
+ hash: { name: webCryptoHashName },
476
478
  length,
477
479
  };
478
480
 
@@ -570,10 +572,15 @@ function rsaImportKey(
570
572
  publicExponentBytes = new Uint8Array(bytes.length > 0 ? bytes : [0]);
571
573
  }
572
574
 
575
+ // Normalize hash to { name: string } format per WebCrypto spec
576
+ const hashName = normalizeHashName(algorithm.hash, HashContext.WebCrypto);
577
+ const normalizedHash = { name: hashName };
578
+
573
579
  const algorithmWithDetails = {
574
580
  ...algorithm,
575
581
  modulusLength: keyDetails?.modulusLength,
576
582
  publicExponent: publicExponentBytes,
583
+ hash: normalizedHash,
577
584
  };
578
585
 
579
586
  return new CryptoKey(keyObject, algorithmWithDetails, keyUsages, extractable);
@@ -636,12 +643,15 @@ async function hmacImportKey(
636
643
  throw new Error(`Unable to import HMAC key with format ${format}`);
637
644
  }
638
645
 
639
- return new CryptoKey(
640
- keyObject,
641
- { ...algorithm, name: 'HMAC' },
642
- keyUsages,
643
- extractable,
644
- );
646
+ // Normalize hash to { name: string } format per WebCrypto spec
647
+ const hashName = normalizeHashName(algorithm.hash, HashContext.WebCrypto);
648
+ const normalizedAlgorithm: SubtleAlgorithm = {
649
+ ...algorithm,
650
+ name: 'HMAC',
651
+ hash: { name: hashName },
652
+ };
653
+
654
+ return new CryptoKey(keyObject, normalizedAlgorithm, keyUsages, extractable);
645
655
  }
646
656
 
647
657
  async function aesImportKey(
@@ -773,6 +783,53 @@ function edImportKey(
773
783
  return new CryptoKey(keyObject, { name }, keyUsages, extractable);
774
784
  }
775
785
 
786
+ function mldsaImportKey(
787
+ format: ImportFormat,
788
+ data: BufferLike,
789
+ algorithm: SubtleAlgorithm,
790
+ extractable: boolean,
791
+ keyUsages: KeyUsage[],
792
+ ): CryptoKey {
793
+ const { name } = algorithm;
794
+
795
+ // Validate usages
796
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
797
+ throw lazyDOMException(
798
+ `Unsupported key usage for ${name} key`,
799
+ 'SyntaxError',
800
+ );
801
+ }
802
+
803
+ let keyObject: KeyObject;
804
+
805
+ if (format === 'spki') {
806
+ // Import public key
807
+ const keyData = bufferLikeToArrayBuffer(data);
808
+ keyObject = KeyObject.createKeyObject(
809
+ 'public',
810
+ keyData,
811
+ KFormatType.DER,
812
+ KeyEncoding.SPKI,
813
+ );
814
+ } else if (format === 'pkcs8') {
815
+ // Import private key
816
+ const keyData = bufferLikeToArrayBuffer(data);
817
+ keyObject = KeyObject.createKeyObject(
818
+ 'private',
819
+ keyData,
820
+ KFormatType.DER,
821
+ KeyEncoding.PKCS8,
822
+ );
823
+ } else {
824
+ throw lazyDOMException(
825
+ `Unsupported format for ${name} import: ${format}`,
826
+ 'NotSupportedError',
827
+ );
828
+ }
829
+
830
+ return new CryptoKey(keyObject, { name }, keyUsages, extractable);
831
+ }
832
+
776
833
  const exportKeySpki = async (
777
834
  key: CryptoKey,
778
835
  ): Promise<ArrayBuffer | unknown> => {
@@ -803,6 +860,18 @@ const exportKeySpki = async (
803
860
  );
804
861
  }
805
862
  break;
863
+ case 'ML-DSA-44':
864
+ // Fall through
865
+ case 'ML-DSA-65':
866
+ // Fall through
867
+ case 'ML-DSA-87':
868
+ if (key.type === 'public') {
869
+ // Export ML-DSA key in SPKI DER format
870
+ return bufferLikeToArrayBuffer(
871
+ key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.SPKI),
872
+ );
873
+ }
874
+ break;
806
875
  }
807
876
 
808
877
  throw new Error(
@@ -840,6 +909,18 @@ const exportKeyPkcs8 = async (
840
909
  );
841
910
  }
842
911
  break;
912
+ case 'ML-DSA-44':
913
+ // Fall through
914
+ case 'ML-DSA-65':
915
+ // Fall through
916
+ case 'ML-DSA-87':
917
+ if (key.type === 'private') {
918
+ // Export ML-DSA key in PKCS8 DER format
919
+ return bufferLikeToArrayBuffer(
920
+ key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
921
+ );
922
+ }
923
+ break;
843
924
  }
844
925
 
845
926
  throw new Error(
@@ -1112,6 +1193,36 @@ function edSignVerify(
1112
1193
  }
1113
1194
  }
1114
1195
 
1196
+ function mldsaSignVerify(
1197
+ key: CryptoKey,
1198
+ data: BufferLike,
1199
+ signature?: BufferLike,
1200
+ ): ArrayBuffer | boolean {
1201
+ const isSign = signature === undefined;
1202
+ const expectedKeyType = isSign ? 'private' : 'public';
1203
+
1204
+ if (key.type !== expectedKeyType) {
1205
+ throw lazyDOMException(
1206
+ `Key must be a ${expectedKeyType} key`,
1207
+ 'InvalidAccessError',
1208
+ );
1209
+ }
1210
+
1211
+ const dataBuffer = bufferLikeToArrayBuffer(data);
1212
+
1213
+ if (isSign) {
1214
+ const signer = createSign('');
1215
+ signer.update(dataBuffer);
1216
+ const sig = signer.sign({ key: key });
1217
+ return sig.buffer.slice(sig.byteOffset, sig.byteOffset + sig.byteLength);
1218
+ } else {
1219
+ const signatureBuffer = bufferLikeToArrayBuffer(signature!);
1220
+ const verifier = createVerify('');
1221
+ verifier.update(dataBuffer);
1222
+ return verifier.verify({ key: key }, signatureBuffer);
1223
+ }
1224
+ }
1225
+
1115
1226
  const signVerify = (
1116
1227
  algorithm: SubtleAlgorithm,
1117
1228
  key: CryptoKey,
@@ -1140,6 +1251,10 @@ const signVerify = (
1140
1251
  case 'Ed25519':
1141
1252
  case 'Ed448':
1142
1253
  return edSignVerify(key, data, signature);
1254
+ case 'ML-DSA-44':
1255
+ case 'ML-DSA-65':
1256
+ case 'ML-DSA-87':
1257
+ return mldsaSignVerify(key, data, signature);
1143
1258
  }
1144
1259
  throw lazyDOMException(
1145
1260
  `Unrecognized algorithm name '${algorithm.name}' for '${usage}'`,
@@ -1309,6 +1424,18 @@ export class Subtle {
1309
1424
  );
1310
1425
  checkCryptoKeyPairUsages(result as CryptoKeyPair);
1311
1426
  break;
1427
+ case 'ML-DSA-44':
1428
+ // Fall through
1429
+ case 'ML-DSA-65':
1430
+ // Fall through
1431
+ case 'ML-DSA-87':
1432
+ result = await mldsa_generateKeyPairWebCrypto(
1433
+ algorithm.name as MlDsaVariant,
1434
+ extractable,
1435
+ keyUsages,
1436
+ );
1437
+ checkCryptoKeyPairUsages(result as CryptoKeyPair);
1438
+ break;
1312
1439
  default:
1313
1440
  throw new Error(
1314
1441
  `'subtle.generateKey()' is not implemented for ${algorithm.name}.
@@ -1397,6 +1524,19 @@ export class Subtle {
1397
1524
  keyUsages,
1398
1525
  );
1399
1526
  break;
1527
+ case 'ML-DSA-44':
1528
+ // Fall through
1529
+ case 'ML-DSA-65':
1530
+ // Fall through
1531
+ case 'ML-DSA-87':
1532
+ result = mldsaImportKey(
1533
+ format,
1534
+ data as BufferLike,
1535
+ normalizedAlgorithm,
1536
+ extractable,
1537
+ keyUsages,
1538
+ );
1539
+ break;
1400
1540
  default:
1401
1541
  throw new Error(
1402
1542
  `"subtle.importKey()" is not implemented for ${normalizedAlgorithm.name}`,
@@ -65,6 +65,9 @@ export type ECKeyPairAlgorithm = 'ECDSA' | 'ECDH';
65
65
  export type CFRGKeyPairAlgorithm = 'Ed25519' | 'Ed448' | 'X25519' | 'X448';
66
66
  export type CFRGKeyPairType = 'ed25519' | 'ed448' | 'x25519' | 'x448';
67
67
 
68
+ export type PQCKeyPairAlgorithm = 'ML-DSA-44' | 'ML-DSA-65' | 'ML-DSA-87';
69
+ export type PQCKeyPairType = 'ml-dsa-44' | 'ml-dsa-65' | 'ml-dsa-87';
70
+
68
71
  // Node.js style key pair types (lowercase)
69
72
  export type RSAKeyPairType = 'rsa' | 'rsa-pss';
70
73
  export type ECKeyPairType = 'ec';
@@ -74,7 +77,8 @@ export type DHKeyPairType = 'dh';
74
77
  export type KeyPairAlgorithm =
75
78
  | RSAKeyPairAlgorithm
76
79
  | ECKeyPairAlgorithm
77
- | CFRGKeyPairAlgorithm;
80
+ | CFRGKeyPairAlgorithm
81
+ | PQCKeyPairAlgorithm;
78
82
 
79
83
  export type AESAlgorithm = 'AES-CTR' | 'AES-CBC' | 'AES-GCM' | 'AES-KW';
80
84
 
@@ -86,7 +90,10 @@ export type SignVerifyAlgorithm =
86
90
  | 'ECDSA'
87
91
  | 'HMAC'
88
92
  | 'Ed25519'
89
- | 'Ed448';
93
+ | 'Ed448'
94
+ | 'ML-DSA-44'
95
+ | 'ML-DSA-65'
96
+ | 'ML-DSA-87';
90
97
 
91
98
  export type DeriveBitsAlgorithm =
92
99
  | 'PBKDF2'
@@ -243,7 +250,8 @@ export type AsymmetricKeyType =
243
250
  | 'dsa'
244
251
  | 'ec'
245
252
  | 'dh'
246
- | CFRGKeyPairType;
253
+ | CFRGKeyPairType
254
+ | PQCKeyPairType;
247
255
 
248
256
  type JWKkty = 'AES' | 'RSA' | 'EC' | 'oct';
249
257
  type JWKuse = 'sig' | 'enc';