react-native-quick-crypto 1.0.2 → 1.0.3

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 (57) hide show
  1. package/QuickCrypto.podspec +1 -0
  2. package/README.md +1 -1
  3. package/android/CMakeLists.txt +4 -0
  4. package/cpp/hkdf/HybridHkdf.cpp +96 -0
  5. package/cpp/hkdf/HybridHkdf.hpp +28 -0
  6. package/cpp/scrypt/HybridScrypt.cpp +62 -0
  7. package/cpp/scrypt/HybridScrypt.hpp +28 -0
  8. package/lib/commonjs/hkdf.js +81 -0
  9. package/lib/commonjs/hkdf.js.map +1 -0
  10. package/lib/commonjs/index.js +33 -1
  11. package/lib/commonjs/index.js.map +1 -1
  12. package/lib/commonjs/scrypt.js +98 -0
  13. package/lib/commonjs/scrypt.js.map +1 -0
  14. package/lib/commonjs/specs/hkdf.nitro.js +6 -0
  15. package/lib/commonjs/specs/hkdf.nitro.js.map +1 -0
  16. package/lib/commonjs/specs/scrypt.nitro.js +6 -0
  17. package/lib/commonjs/specs/scrypt.nitro.js.map +1 -0
  18. package/lib/commonjs/subtle.js +28 -0
  19. package/lib/commonjs/subtle.js.map +1 -1
  20. package/lib/module/hkdf.js +75 -0
  21. package/lib/module/hkdf.js.map +1 -0
  22. package/lib/module/index.js +13 -1
  23. package/lib/module/index.js.map +1 -1
  24. package/lib/module/scrypt.js +93 -0
  25. package/lib/module/scrypt.js.map +1 -0
  26. package/lib/module/specs/hkdf.nitro.js +4 -0
  27. package/lib/module/specs/hkdf.nitro.js.map +1 -0
  28. package/lib/module/specs/scrypt.nitro.js +4 -0
  29. package/lib/module/specs/scrypt.nitro.js.map +1 -0
  30. package/lib/module/subtle.js +28 -0
  31. package/lib/module/subtle.js.map +1 -1
  32. package/lib/tsconfig.tsbuildinfo +1 -1
  33. package/lib/typescript/hkdf.d.ts +26 -0
  34. package/lib/typescript/hkdf.d.ts.map +1 -0
  35. package/lib/typescript/index.d.ts +9 -0
  36. package/lib/typescript/index.d.ts.map +1 -1
  37. package/lib/typescript/scrypt.d.ts +18 -0
  38. package/lib/typescript/scrypt.d.ts.map +1 -0
  39. package/lib/typescript/specs/hkdf.nitro.d.ts +9 -0
  40. package/lib/typescript/specs/hkdf.nitro.d.ts.map +1 -0
  41. package/lib/typescript/specs/scrypt.nitro.d.ts +9 -0
  42. package/lib/typescript/specs/scrypt.nitro.d.ts.map +1 -0
  43. package/lib/typescript/subtle.d.ts.map +1 -1
  44. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +2 -0
  45. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +20 -0
  46. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +20 -0
  47. package/nitrogen/generated/shared/c++/HybridHkdfSpec.cpp +22 -0
  48. package/nitrogen/generated/shared/c++/HybridHkdfSpec.hpp +66 -0
  49. package/nitrogen/generated/shared/c++/HybridScryptSpec.cpp +22 -0
  50. package/nitrogen/generated/shared/c++/HybridScryptSpec.hpp +65 -0
  51. package/package.json +1 -1
  52. package/src/hkdf.ts +152 -0
  53. package/src/index.ts +13 -1
  54. package/src/scrypt.ts +134 -0
  55. package/src/specs/hkdf.nitro.ts +19 -0
  56. package/src/specs/scrypt.nitro.ts +23 -0
  57. package/src/subtle.ts +45 -0
package/src/scrypt.ts ADDED
@@ -0,0 +1,134 @@
1
+ import { Buffer } from '@craftzdog/react-native-buffer';
2
+ import { NitroModules } from 'react-native-nitro-modules';
3
+ import type { Scrypt as NativeScrypt } from './specs/scrypt.nitro';
4
+ import { binaryLikeToArrayBuffer } from './utils';
5
+ import type { BinaryLike } from './utils';
6
+
7
+ type Password = BinaryLike;
8
+ type Salt = BinaryLike;
9
+
10
+ export interface ScryptOptions {
11
+ N?: number;
12
+ r?: number;
13
+ p?: number;
14
+ cost?: number;
15
+ blockSize?: number;
16
+ parallelization?: number;
17
+ maxmem?: number;
18
+ }
19
+
20
+ type ScryptCallback = (err: Error | null, derivedKey?: Buffer) => void;
21
+
22
+ // Lazy load native module
23
+ let native: NativeScrypt;
24
+ function getNative(): NativeScrypt {
25
+ if (native == null) {
26
+ native = NitroModules.createHybridObject<NativeScrypt>('Scrypt');
27
+ }
28
+ return native;
29
+ }
30
+
31
+ const defaults = {
32
+ N: 16384,
33
+ r: 8,
34
+ p: 1,
35
+ maxmem: 32 * 1024 * 1024,
36
+ };
37
+
38
+ function getScryptParams(options?: ScryptOptions) {
39
+ const N = options?.N ?? options?.cost ?? defaults.N;
40
+ const r = options?.r ?? options?.blockSize ?? defaults.r;
41
+ const p = options?.p ?? options?.parallelization ?? defaults.p;
42
+ const maxmem = options?.maxmem ?? defaults.maxmem;
43
+
44
+ return { N, r, p, maxmem };
45
+ }
46
+
47
+ function validateCallback(callback: ScryptCallback) {
48
+ if (callback === undefined || typeof callback !== 'function') {
49
+ throw new Error('No callback provided to scrypt');
50
+ }
51
+ }
52
+
53
+ function sanitizeInput(input: BinaryLike, name: string): ArrayBuffer {
54
+ try {
55
+ return binaryLikeToArrayBuffer(input);
56
+ } catch {
57
+ throw new Error(
58
+ `${name} must be a string, a Buffer, a typed array, or a DataView`,
59
+ );
60
+ }
61
+ }
62
+
63
+ export function scrypt(
64
+ password: Password,
65
+ salt: Salt,
66
+ keylen: number,
67
+ options?: ScryptOptions | ScryptCallback,
68
+ callback?: ScryptCallback,
69
+ ): void {
70
+ let cb: ScryptCallback;
71
+ let opts: ScryptOptions | undefined;
72
+
73
+ if (typeof options === 'function') {
74
+ cb = options;
75
+ opts = undefined;
76
+ } else {
77
+ cb = callback!;
78
+ opts = options;
79
+ }
80
+
81
+ validateCallback(cb);
82
+
83
+ try {
84
+ const { N, r, p, maxmem } = getScryptParams(opts);
85
+ const sanitizedPassword = sanitizeInput(password, 'Password');
86
+ const sanitizedSalt = sanitizeInput(salt, 'Salt');
87
+
88
+ if (keylen < 0) {
89
+ throw new TypeError('Bad key length');
90
+ }
91
+
92
+ const nativeMod = getNative();
93
+ nativeMod
94
+ .deriveKey(sanitizedPassword, sanitizedSalt, N, r, p, maxmem, keylen)
95
+ .then(
96
+ res => {
97
+ cb(null, Buffer.from(res));
98
+ },
99
+ err => {
100
+ cb(err);
101
+ },
102
+ );
103
+ } catch (err) {
104
+ cb(err as Error);
105
+ }
106
+ }
107
+
108
+ export function scryptSync(
109
+ password: Password,
110
+ salt: Salt,
111
+ keylen: number,
112
+ options?: ScryptOptions,
113
+ ): Buffer {
114
+ const { N, r, p, maxmem } = getScryptParams(options);
115
+ const sanitizedPassword = sanitizeInput(password, 'Password');
116
+ const sanitizedSalt = sanitizeInput(salt, 'Salt');
117
+
118
+ if (keylen < 0) {
119
+ throw new TypeError('Bad key length');
120
+ }
121
+
122
+ const nativeMod = getNative();
123
+ const result = nativeMod.deriveKeySync(
124
+ sanitizedPassword,
125
+ sanitizedSalt,
126
+ N,
127
+ r,
128
+ p,
129
+ maxmem,
130
+ keylen,
131
+ );
132
+
133
+ return Buffer.from(result);
134
+ }
@@ -0,0 +1,19 @@
1
+ import type { HybridObject } from 'react-native-nitro-modules';
2
+
3
+ export interface Hkdf extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
4
+ deriveKeySync(
5
+ algorithm: string,
6
+ key: ArrayBuffer,
7
+ salt: ArrayBuffer,
8
+ info: ArrayBuffer,
9
+ length: number,
10
+ ): ArrayBuffer;
11
+
12
+ deriveKey(
13
+ algorithm: string,
14
+ key: ArrayBuffer,
15
+ salt: ArrayBuffer,
16
+ info: ArrayBuffer,
17
+ length: number,
18
+ ): Promise<ArrayBuffer>;
19
+ }
@@ -0,0 +1,23 @@
1
+ import type { HybridObject } from 'react-native-nitro-modules';
2
+
3
+ export interface Scrypt extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
4
+ deriveKey(
5
+ password: ArrayBuffer,
6
+ salt: ArrayBuffer,
7
+ N: number,
8
+ r: number,
9
+ p: number,
10
+ maxmem: number,
11
+ keylen: number,
12
+ ): Promise<ArrayBuffer>;
13
+
14
+ deriveKeySync(
15
+ password: ArrayBuffer,
16
+ salt: ArrayBuffer,
17
+ N: number,
18
+ r: number,
19
+ p: number,
20
+ maxmem: number,
21
+ keylen: number,
22
+ ): ArrayBuffer;
23
+ }
package/src/subtle.ts CHANGED
@@ -49,6 +49,7 @@ import {
49
49
  Ed,
50
50
  } from './ed';
51
51
  import { mldsa_generateKeyPairWebCrypto, type MlDsaVariant } from './mldsa';
52
+ import { hkdfDeriveBits, type HkdfAlgorithm } from './hkdf';
52
53
  // import { pbkdf2DeriveBits } from './pbkdf2';
53
54
  // import { aesCipher, aesGenerateKey, aesImportKey, getAlgorithmName } from './aes';
54
55
  // import { rsaCipher, rsaExportKey, rsaImportKey, rsaKeyGenerate } from './rsa';
@@ -1235,6 +1236,28 @@ const importGenericSecretKey = async (
1235
1236
  throw new Error(`Unable to import ${name} key with format ${format}`);
1236
1237
  };
1237
1238
 
1239
+ const hkdfImportKey = async (
1240
+ format: ImportFormat,
1241
+ keyData: BufferLike | BinaryLike,
1242
+ algorithm: SubtleAlgorithm,
1243
+ extractable: boolean,
1244
+ keyUsages: KeyUsage[],
1245
+ ): Promise<CryptoKey> => {
1246
+ const { name } = algorithm;
1247
+ if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
1248
+ throw new Error(`Unsupported key usage for a ${name} key`);
1249
+ }
1250
+
1251
+ switch (format) {
1252
+ case 'raw': {
1253
+ const keyObject = createSecretKey(keyData as BinaryLike);
1254
+ return new CryptoKey(keyObject, { name }, keyUsages, extractable);
1255
+ }
1256
+ default:
1257
+ throw new Error(`Unable to import ${name} key with format ${format}`);
1258
+ }
1259
+ };
1260
+
1238
1261
  const checkCryptoKeyPairUsages = (pair: CryptoKeyPair) => {
1239
1262
  if (
1240
1263
  pair.privateKey &&
@@ -1536,6 +1559,12 @@ export class Subtle {
1536
1559
  // Fall through
1537
1560
  case 'X448':
1538
1561
  return xDeriveBits(algorithm, baseKey, length);
1562
+ case 'HKDF':
1563
+ return hkdfDeriveBits(
1564
+ algorithm as unknown as HkdfAlgorithm,
1565
+ baseKey,
1566
+ length,
1567
+ );
1539
1568
  }
1540
1569
  throw new Error(
1541
1570
  `'subtle.deriveBits()' for ${algorithm.name} is not implemented.`,
@@ -1577,6 +1606,13 @@ export class Subtle {
1577
1606
  case 'X448':
1578
1607
  derivedBits = await xDeriveBits(algorithm, baseKey, length);
1579
1608
  break;
1609
+ case 'HKDF':
1610
+ derivedBits = hkdfDeriveBits(
1611
+ algorithm as unknown as HkdfAlgorithm,
1612
+ baseKey,
1613
+ length,
1614
+ );
1615
+ break;
1580
1616
  default:
1581
1617
  throw new Error(
1582
1618
  `'subtle.deriveKey()' for ${algorithm.name} is not implemented.`,
@@ -1908,6 +1944,15 @@ export class Subtle {
1908
1944
  keyUsages,
1909
1945
  );
1910
1946
  break;
1947
+ case 'HKDF':
1948
+ result = await hkdfImportKey(
1949
+ format,
1950
+ data as BufferLike | BinaryLike,
1951
+ normalizedAlgorithm,
1952
+ extractable,
1953
+ keyUsages,
1954
+ );
1955
+ break;
1911
1956
  case 'X25519':
1912
1957
  // Fall through
1913
1958
  case 'X448':