react-native-quick-crypto 0.7.0 → 0.7.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.
Files changed (133) hide show
  1. package/README.md +11 -63
  2. package/android/CMakeLists.txt +2 -0
  3. package/cpp/Cipher/MGLRsa.cpp +179 -3
  4. package/cpp/Cipher/MGLRsa.h +40 -0
  5. package/cpp/JSIUtils/MGLJSIUtils.h +8 -0
  6. package/cpp/MGLKeys.cpp +41 -43
  7. package/cpp/MGLKeys.h +9 -2
  8. package/cpp/MGLQuickCryptoHostObject.cpp +6 -6
  9. package/cpp/Sig/MGLSignHostObjects.cpp +22 -15
  10. package/cpp/Utils/MGLUtils.cpp +71 -1
  11. package/cpp/Utils/MGLUtils.h +55 -1
  12. package/cpp/webcrypto/MGLWebCrypto.cpp +89 -37
  13. package/cpp/webcrypto/MGLWebCrypto.h +5 -7
  14. package/cpp/webcrypto/crypto_aes.cpp +516 -0
  15. package/cpp/webcrypto/crypto_aes.h +79 -0
  16. package/cpp/webcrypto/crypto_ec.cpp +4 -20
  17. package/cpp/webcrypto/crypto_ec.h +0 -5
  18. package/cpp/webcrypto/crypto_keygen.cpp +86 -0
  19. package/cpp/webcrypto/crypto_keygen.h +38 -0
  20. package/lib/commonjs/Cipher.js +3 -1
  21. package/lib/commonjs/Cipher.js.map +1 -1
  22. package/lib/commonjs/Hashnames.js +20 -8
  23. package/lib/commonjs/Hashnames.js.map +1 -1
  24. package/lib/commonjs/NativeQuickCrypto/Cipher.js +13 -1
  25. package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -1
  26. package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  27. package/lib/commonjs/NativeQuickCrypto/aes.js +6 -0
  28. package/lib/commonjs/NativeQuickCrypto/aes.js.map +1 -0
  29. package/lib/commonjs/NativeQuickCrypto/keygen.js +6 -0
  30. package/lib/commonjs/NativeQuickCrypto/keygen.js.map +1 -0
  31. package/lib/commonjs/NativeQuickCrypto/rsa.js +6 -0
  32. package/lib/commonjs/NativeQuickCrypto/rsa.js.map +1 -0
  33. package/lib/commonjs/Utils.js +30 -6
  34. package/lib/commonjs/Utils.js.map +1 -1
  35. package/lib/commonjs/aes.js +184 -227
  36. package/lib/commonjs/aes.js.map +1 -1
  37. package/lib/commonjs/index.js +12 -2
  38. package/lib/commonjs/index.js.map +1 -1
  39. package/lib/commonjs/keygen.js +56 -0
  40. package/lib/commonjs/keygen.js.map +1 -0
  41. package/lib/commonjs/keys.js +74 -5
  42. package/lib/commonjs/keys.js.map +1 -1
  43. package/lib/commonjs/rsa.js +115 -196
  44. package/lib/commonjs/rsa.js.map +1 -1
  45. package/lib/commonjs/sig.js.map +1 -1
  46. package/lib/commonjs/subtle.js +140 -78
  47. package/lib/commonjs/subtle.js.map +1 -1
  48. package/lib/commonjs/webcrypto.js +14 -0
  49. package/lib/commonjs/webcrypto.js.map +1 -0
  50. package/lib/module/Cipher.js +3 -1
  51. package/lib/module/Cipher.js.map +1 -1
  52. package/lib/module/Hashnames.js +20 -8
  53. package/lib/module/Hashnames.js.map +1 -1
  54. package/lib/module/NativeQuickCrypto/Cipher.js +12 -0
  55. package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -1
  56. package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  57. package/lib/module/NativeQuickCrypto/aes.js +2 -0
  58. package/lib/module/NativeQuickCrypto/aes.js.map +1 -0
  59. package/lib/module/NativeQuickCrypto/keygen.js +2 -0
  60. package/lib/module/NativeQuickCrypto/keygen.js.map +1 -0
  61. package/lib/module/NativeQuickCrypto/rsa.js +2 -0
  62. package/lib/module/NativeQuickCrypto/rsa.js.map +1 -0
  63. package/lib/module/Utils.js +26 -5
  64. package/lib/module/Utils.js.map +1 -1
  65. package/lib/module/aes.js +183 -228
  66. package/lib/module/aes.js.map +1 -1
  67. package/lib/module/index.js +11 -2
  68. package/lib/module/index.js.map +1 -1
  69. package/lib/module/keygen.js +47 -0
  70. package/lib/module/keygen.js.map +1 -0
  71. package/lib/module/keys.js +68 -4
  72. package/lib/module/keys.js.map +1 -1
  73. package/lib/module/rsa.js +115 -198
  74. package/lib/module/rsa.js.map +1 -1
  75. package/lib/module/sig.js.map +1 -1
  76. package/lib/module/subtle.js +143 -82
  77. package/lib/module/subtle.js.map +1 -1
  78. package/lib/module/webcrypto.js +8 -0
  79. package/lib/module/webcrypto.js.map +1 -0
  80. package/lib/typescript/Cipher.d.ts +0 -1
  81. package/lib/typescript/Cipher.d.ts.map +1 -1
  82. package/lib/typescript/Hash.d.ts.map +1 -1
  83. package/lib/typescript/Hashnames.d.ts +2 -2
  84. package/lib/typescript/Hashnames.d.ts.map +1 -1
  85. package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +5 -0
  86. package/lib/typescript/NativeQuickCrypto/Cipher.d.ts.map +1 -1
  87. package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +4 -1
  88. package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts.map +1 -1
  89. package/lib/typescript/NativeQuickCrypto/aes.d.ts +5 -0
  90. package/lib/typescript/NativeQuickCrypto/aes.d.ts.map +1 -0
  91. package/lib/typescript/NativeQuickCrypto/keygen.d.ts +4 -0
  92. package/lib/typescript/NativeQuickCrypto/keygen.d.ts.map +1 -0
  93. package/lib/typescript/NativeQuickCrypto/rsa.d.ts +5 -0
  94. package/lib/typescript/NativeQuickCrypto/rsa.d.ts.map +1 -0
  95. package/lib/typescript/NativeQuickCrypto/webcrypto.d.ts +12 -2
  96. package/lib/typescript/NativeQuickCrypto/webcrypto.d.ts.map +1 -1
  97. package/lib/typescript/Utils.d.ts +4 -4
  98. package/lib/typescript/Utils.d.ts.map +1 -1
  99. package/lib/typescript/aes.d.ts +18 -1
  100. package/lib/typescript/aes.d.ts.map +1 -1
  101. package/lib/typescript/ec.d.ts.map +1 -1
  102. package/lib/typescript/index.d.ts +27 -24
  103. package/lib/typescript/index.d.ts.map +1 -1
  104. package/lib/typescript/keygen.d.ts +6 -0
  105. package/lib/typescript/keygen.d.ts.map +1 -0
  106. package/lib/typescript/keys.d.ts +58 -17
  107. package/lib/typescript/keys.d.ts.map +1 -1
  108. package/lib/typescript/rsa.d.ts +9 -1
  109. package/lib/typescript/rsa.d.ts.map +1 -1
  110. package/lib/typescript/sig.d.ts +3 -17
  111. package/lib/typescript/sig.d.ts.map +1 -1
  112. package/lib/typescript/subtle.d.ts +6 -5
  113. package/lib/typescript/subtle.d.ts.map +1 -1
  114. package/lib/typescript/webcrypto.d.ts +9 -0
  115. package/lib/typescript/webcrypto.d.ts.map +1 -0
  116. package/package.json +12 -12
  117. package/src/Cipher.ts +1 -1
  118. package/src/Hashnames.ts +23 -21
  119. package/src/NativeQuickCrypto/Cipher.ts +32 -0
  120. package/src/NativeQuickCrypto/NativeQuickCrypto.ts +6 -0
  121. package/src/NativeQuickCrypto/aes.ts +14 -0
  122. package/src/NativeQuickCrypto/keygen.ts +7 -0
  123. package/src/NativeQuickCrypto/rsa.ts +12 -0
  124. package/src/NativeQuickCrypto/webcrypto.ts +26 -2
  125. package/src/Utils.ts +37 -8
  126. package/src/aes.ts +259 -222
  127. package/src/index.ts +10 -1
  128. package/src/keygen.ts +80 -0
  129. package/src/keys.ts +143 -30
  130. package/src/rsa.ts +161 -187
  131. package/src/sig.ts +7 -23
  132. package/src/subtle.ts +211 -93
  133. package/src/webcrypto.ts +8 -0
@@ -0,0 +1,12 @@
1
+ import type { CipherOrWrapMode, DigestAlgorithm } from '../keys';
2
+ import type { RSAKeyVariant } from '../rsa';
3
+ import type { KeyObjectHandle } from './webcrypto';
4
+
5
+ export type RSACipher = (
6
+ mode: CipherOrWrapMode,
7
+ handle: KeyObjectHandle,
8
+ data: ArrayBuffer,
9
+ variant: RSAKeyVariant,
10
+ hash: DigestAlgorithm,
11
+ label?: ArrayBuffer
12
+ ) => Promise<ArrayBuffer>;
@@ -1,3 +1,4 @@
1
+ import type { AESCipher } from './aes';
1
2
  import type {
2
3
  AsymmetricKeyType,
3
4
  JWK,
@@ -8,6 +9,12 @@ import type {
8
9
  NamedCurve,
9
10
  } from '../keys';
10
11
  import type { SignVerify } from './sig';
12
+ import type {
13
+ GenerateSecretKeyMethod,
14
+ GenerateSecretKeySyncMethod,
15
+ } from './keygen';
16
+ import type { KeyVariant } from './Cipher';
17
+ import type { RSACipher } from './rsa';
11
18
 
12
19
  type KeyDetail = {
13
20
  length?: number;
@@ -24,6 +31,12 @@ type ECExportKey = (
24
31
  handle: KeyObjectHandle
25
32
  ) => ArrayBuffer;
26
33
 
34
+ type RSAExportKey = (
35
+ format: KWebCryptoKeyFormat,
36
+ handle: KeyObjectHandle,
37
+ variant: KeyVariant
38
+ ) => ArrayBuffer;
39
+
27
40
  export type KeyObjectHandle = {
28
41
  export(
29
42
  format?: KFormatType,
@@ -33,7 +46,13 @@ export type KeyObjectHandle = {
33
46
  ): ArrayBuffer;
34
47
  exportJwk(key: JWK, handleRsaPss: boolean): JWK;
35
48
  getAsymmetricKeyType(): AsymmetricKeyType;
36
- init(keyType: KeyType, key: any): boolean;
49
+ init(
50
+ keyType: KeyType,
51
+ key: any,
52
+ format?: KFormatType,
53
+ type?: KeyEncoding,
54
+ passphrase?: string | ArrayBuffer
55
+ ): boolean;
37
56
  initECRaw(curveName: string, keyData: ArrayBuffer): boolean;
38
57
  initJwk(keyData: JWK, namedCurve?: NamedCurve): KeyType | undefined;
39
58
  keyDetail(): KeyDetail;
@@ -42,7 +61,12 @@ export type KeyObjectHandle = {
42
61
  type CreateKeyObjectHandle = () => KeyObjectHandle;
43
62
 
44
63
  export type webcrypto = {
45
- ecExportKey: ECExportKey;
64
+ aesCipher: AESCipher;
46
65
  createKeyObjectHandle: CreateKeyObjectHandle;
66
+ ecExportKey: ECExportKey;
67
+ generateSecretKey: GenerateSecretKeyMethod;
68
+ generateSecretKeySync: GenerateSecretKeySyncMethod;
69
+ rsaCipher: RSACipher;
70
+ rsaExportKey: RSAExportKey;
47
71
  signVerify: SignVerify;
48
72
  };
package/src/Utils.ts CHANGED
@@ -2,8 +2,9 @@ import { Buffer } from '@craftzdog/react-native-buffer';
2
2
  import type {
3
3
  AnyAlgorithm,
4
4
  DeriveBitsAlgorithm,
5
+ DigestAlgorithm,
5
6
  EncryptDecryptAlgorithm,
6
- HashAlgorithm,
7
+ EncryptDecryptParams,
7
8
  KeyPairAlgorithm,
8
9
  KeyUsage,
9
10
  SecretKeyAlgorithm,
@@ -208,12 +209,16 @@ export function validateString(str: any, name?: string): str is string {
208
209
  return isString;
209
210
  }
210
211
 
211
- export function validateFunction(f: any): f is Function {
212
- return f != null && typeof f === 'function';
212
+ export function validateFunction(f: any): boolean {
213
+ return f !== null && typeof f === 'function';
213
214
  }
214
215
 
215
216
  export function isStringOrBuffer(val: any): val is string | ArrayBuffer {
216
- return typeof val === 'string' || ArrayBuffer.isView(val);
217
+ return (
218
+ typeof val === 'string' ||
219
+ ArrayBuffer.isView(val) ||
220
+ val instanceof ArrayBuffer
221
+ );
217
222
  }
218
223
 
219
224
  export function validateObject<T>(
@@ -329,7 +334,7 @@ type SupportedAlgorithm<Type extends string> = {
329
334
  };
330
335
 
331
336
  type SupportedAlgorithms = {
332
- 'digest': SupportedAlgorithm<HashAlgorithm>;
337
+ 'digest': SupportedAlgorithm<DigestAlgorithm>;
333
338
  'generateKey': SupportedAlgorithm<KeyPairAlgorithm | SecretKeyAlgorithm>;
334
339
  'sign': SupportedAlgorithm<SignVerifyAlgorithm>;
335
340
  'verify': SupportedAlgorithm<SignVerifyAlgorithm>;
@@ -491,11 +496,12 @@ export const validateMaxBufferLength = (
491
496
  // adapted for Node.js from Deno's implementation
492
497
  // https://github.com/denoland/deno/blob/v1.29.1/ext/crypto/00_crypto.js#L195
493
498
  export const normalizeAlgorithm = (
494
- algorithm: SubtleAlgorithm | AnyAlgorithm,
499
+ algorithm: SubtleAlgorithm | EncryptDecryptParams | AnyAlgorithm,
495
500
  op: Operation
496
- ): SubtleAlgorithm => {
497
- if (typeof algorithm === 'string')
501
+ ): SubtleAlgorithm | EncryptDecryptParams => {
502
+ if (typeof algorithm === 'string') {
498
503
  return normalizeAlgorithm({ name: algorithm }, op);
504
+ }
499
505
 
500
506
  // 1.
501
507
  const registeredAlgorithms = kSupportedAlgorithms[op];
@@ -663,6 +669,29 @@ export const validateKeyOps = (
663
669
  }
664
670
  };
665
671
 
672
+ // In WebCrypto, the publicExponent option in RSA is represented as a
673
+ // WebIDL "BigInteger"... that is, a Uint8Array that allows an arbitrary
674
+ // number of leading zero bits. Our conventional APIs for reading
675
+ // an unsigned int from a Buffer are not adequate. The implementation
676
+ // here is adapted from the chromium implementation here:
677
+ // https://github.com/chromium/chromium/blob/HEAD/third_party/blink/public/platform/web_crypto_algorithm_params.h, but ported to JavaScript
678
+ // Returns undefined if the conversion was unsuccessful.
679
+ export const bigIntArrayToUnsignedInt = (
680
+ input: Uint8Array
681
+ ): number | undefined => {
682
+ let result = 0;
683
+
684
+ for (let n = 0; n < input.length; ++n) {
685
+ const n_reversed = input.length - n - 1;
686
+ if (n_reversed >= 4 && input[n]) return; // Too large
687
+ // @ts-ignore
688
+ // eslint-disable-next-line no-bitwise
689
+ result |= input[n] << (8 * n_reversed);
690
+ }
691
+
692
+ return result;
693
+ };
694
+
666
695
  // TODO: these used to be shipped by crypto-browserify in quickcrypto v0.6
667
696
  // could instead fetch from OpenSSL if needed and handle breaking changes
668
697
  export const getHashes = () => [
package/src/aes.ts CHANGED
@@ -4,6 +4,9 @@ import {
4
4
  type BufferLike,
5
5
  hasAnyNotIn,
6
6
  validateKeyOps,
7
+ validateByteLength,
8
+ validateMaxBufferLength,
9
+ bufferLikeToArrayBuffer,
7
10
  } from './Utils';
8
11
  import {
9
12
  type ImportFormat,
@@ -13,70 +16,37 @@ import {
13
16
  createSecretKey,
14
17
  SecretKeyObject,
15
18
  type JWK,
19
+ type AESAlgorithm,
20
+ CipherOrWrapMode,
21
+ type EncryptDecryptParams,
22
+ type AesGcmParams,
23
+ type AesCbcParams,
24
+ type AesCtrParams,
25
+ type TagLength,
26
+ type AESLength,
27
+ type AesKeyGenParams,
16
28
  } from './keys';
29
+ import { generateKeyPromise } from './keygen';
30
+
31
+ // needs to match the values in cpp/webcrypto/crypto_aes.{h,cpp}
32
+ export enum AESKeyVariant {
33
+ AES_CTR_128,
34
+ AES_CTR_192,
35
+ AES_CTR_256,
36
+ AES_CBC_128,
37
+ AES_CBC_192,
38
+ AES_CBC_256,
39
+ AES_GCM_128,
40
+ AES_GCM_192,
41
+ AES_GCM_256,
42
+ AES_KW_128,
43
+ AES_KW_192,
44
+ AES_KW_256,
45
+ }
17
46
 
18
- // const {
19
- // ArrayBufferIsView,
20
- // ArrayBufferPrototypeSlice,
21
- // ArrayFrom,
22
- // ArrayPrototypeIncludes,
23
- // ArrayPrototypePush,
24
- // MathFloor,
25
- // SafeSet,
26
- // TypedArrayPrototypeSlice,
27
- // } = primordials;
28
-
29
- // const {
30
- // AESCipherJob,
31
- // KeyObjectHandle,
32
- // kCryptoJobAsync,
33
- // kKeyVariantAES_CTR_128,
34
- // kKeyVariantAES_CBC_128,
35
- // kKeyVariantAES_GCM_128,
36
- // kKeyVariantAES_KW_128,
37
- // kKeyVariantAES_CTR_192,
38
- // kKeyVariantAES_CBC_192,
39
- // kKeyVariantAES_GCM_192,
40
- // kKeyVariantAES_KW_192,
41
- // kKeyVariantAES_CTR_256,
42
- // kKeyVariantAES_CBC_256,
43
- // kKeyVariantAES_GCM_256,
44
- // kKeyVariantAES_KW_256,
45
- // kWebCryptoCipherDecrypt,
46
- // kWebCryptoCipherEncrypt,
47
- // } = internalBinding('crypto');
48
-
49
- // const {
50
- // hasAnyNotIn,
51
- // jobPromise,
52
- // validateByteLength,
53
- // validateKeyOps,
54
- // validateMaxBufferLength,
55
- // kAesKeyLengths,
56
- // kHandle,
57
- // kKeyObject,
58
- // } = require('internal/crypto/util');
59
-
60
- // const {
61
- // lazyDOMException,
62
- // promisify,
63
- // } = require('internal/util');
64
-
65
- // const { PromiseReject } = primordials;
66
-
67
- // const {
68
- // InternalCryptoKey,
69
- // SecretKeyObject,
70
- // createSecretKey,
71
- // } = require('internal/crypto/keys');
72
-
73
- // const {
74
- // generateKey: _generateKey,
75
- // } = require('internal/crypto/keygen');
76
-
77
- // const kMaxCounterLength = 128;
78
- // const kTagLengths = [32, 64, 96, 104, 112, 120, 128];
79
- // const generateKey = promisify(_generateKey);
47
+ const kMaxCounterLength = 128;
48
+ const kTagLengths: TagLength[] = [32, 64, 96, 104, 112, 120, 128];
49
+ export const kAesKeyLengths = [128, 192, 256];
80
50
 
81
51
  export const getAlgorithmName = (name: string, length?: number) => {
82
52
  if (length === undefined)
@@ -103,174 +73,241 @@ function validateKeyLength(length?: number) {
103
73
  throw lazyDOMException(`Invalid key length: ${length}`, 'DataError');
104
74
  }
105
75
 
106
- // function getVariant(name, length) {
107
- // switch (name) {
108
- // case 'AES-CBC':
109
- // switch (length) {
110
- // case 128: return kKeyVariantAES_CBC_128;
111
- // case 192: return kKeyVariantAES_CBC_192;
112
- // case 256: return kKeyVariantAES_CBC_256;
113
- // }
114
- // break;
115
- // case 'AES-CTR':
116
- // switch (length) {
117
- // case 128: return kKeyVariantAES_CTR_128;
118
- // case 192: return kKeyVariantAES_CTR_192;
119
- // case 256: return kKeyVariantAES_CTR_256;
120
- // }
121
- // break;
122
- // case 'AES-GCM':
123
- // switch (length) {
124
- // case 128: return kKeyVariantAES_GCM_128;
125
- // case 192: return kKeyVariantAES_GCM_192;
126
- // case 256: return kKeyVariantAES_GCM_256;
127
- // }
128
- // break;
129
- // case 'AES-KW':
130
- // switch (length) {
131
- // case 128: return kKeyVariantAES_KW_128;
132
- // case 192: return kKeyVariantAES_KW_192;
133
- // case 256: return kKeyVariantAES_KW_256;
134
- // }
135
- // break;
136
- // }
137
- // }
76
+ function getVariant(name: AESAlgorithm, length: AESLength): AESKeyVariant {
77
+ switch (name) {
78
+ case 'AES-CBC':
79
+ switch (length) {
80
+ case 128:
81
+ return AESKeyVariant.AES_CBC_128;
82
+ case 192:
83
+ return AESKeyVariant.AES_CBC_192;
84
+ case 256:
85
+ return AESKeyVariant.AES_CBC_256;
86
+ }
87
+ // @ts-ignore
88
+ break;
89
+ case 'AES-CTR':
90
+ switch (length) {
91
+ case 128:
92
+ return AESKeyVariant.AES_CTR_128;
93
+ case 192:
94
+ return AESKeyVariant.AES_CTR_192;
95
+ case 256:
96
+ return AESKeyVariant.AES_CTR_256;
97
+ }
98
+ // @ts-ignore
99
+ break;
100
+ case 'AES-GCM':
101
+ switch (length) {
102
+ case 128:
103
+ return AESKeyVariant.AES_GCM_128;
104
+ case 192:
105
+ return AESKeyVariant.AES_GCM_192;
106
+ case 256:
107
+ return AESKeyVariant.AES_GCM_256;
108
+ }
109
+ // @ts-ignore
110
+ break;
111
+ case 'AES-KW':
112
+ switch (length) {
113
+ case 128:
114
+ return AESKeyVariant.AES_KW_128;
115
+ case 192:
116
+ return AESKeyVariant.AES_KW_192;
117
+ case 256:
118
+ return AESKeyVariant.AES_KW_256;
119
+ }
120
+ // @ts-ignore
121
+ break;
122
+ }
138
123
 
139
- // function asyncAesCtrCipher(mode, key, data, { counter, length }) {
140
- // validateByteLength(counter, 'algorithm.counter', 16);
141
- // // The length must specify an integer between 1 and 128. While
142
- // // there is no default, this should typically be 64.
143
- // if (length === 0 || length > kMaxCounterLength) {
144
- // throw lazyDOMException(
145
- // 'AES-CTR algorithm.length must be between 1 and 128',
146
- // 'OperationError');
147
- // }
148
-
149
- // return jobPromise(() => new AESCipherJob(
150
- // kCryptoJobAsync,
151
- // mode,
152
- // key[kKeyObject][kHandle],
153
- // data,
154
- // getVariant('AES-CTR', key.algorithm.length),
155
- // counter,
156
- // length));
157
- // }
124
+ // @ts-ignore
125
+ throw lazyDOMException(
126
+ `Error getting variant ${name} at length: ${length}`,
127
+ 'DataError'
128
+ );
129
+ }
158
130
 
159
- // function asyncAesCbcCipher(mode, key, data, { iv }) {
160
- // validateByteLength(iv, 'algorithm.iv', 16);
161
- // return jobPromise(() => new AESCipherJob(
162
- // kCryptoJobAsync,
163
- // mode,
164
- // key[kKeyObject][kHandle],
165
- // data,
166
- // getVariant('AES-CBC', key.algorithm.length),
167
- // iv));
168
- // }
131
+ function asyncAesCtrCipher(
132
+ mode: CipherOrWrapMode,
133
+ key: CryptoKey,
134
+ data: ArrayBuffer,
135
+ { counter, length }: AesCtrParams
136
+ ): Promise<ArrayBuffer> {
137
+ validateByteLength(counter, 'algorithm.counter', 16);
138
+ // The length must specify an integer between 1 and 128. While
139
+ // there is no default, this should typically be 64.
140
+ if (length === 0 || length > kMaxCounterLength) {
141
+ throw lazyDOMException(
142
+ 'AES-CTR algorithm.length must be between 1 and 128',
143
+ 'OperationError'
144
+ );
145
+ }
169
146
 
170
- // function asyncAesKwCipher(mode, key, data) {
171
- // return jobPromise(() => new AESCipherJob(
172
- // kCryptoJobAsync,
173
- // mode,
174
- // key[kKeyObject][kHandle],
175
- // data,
176
- // getVariant('AES-KW', key.algorithm.length)));
177
- // }
147
+ return NativeQuickCrypto.webcrypto.aesCipher(
148
+ mode,
149
+ key.keyObject.handle,
150
+ data,
151
+ getVariant('AES-CTR', key.algorithm.length as AESLength),
152
+ bufferLikeToArrayBuffer(counter),
153
+ length
154
+ );
155
+ }
156
+
157
+ function asyncAesCbcCipher(
158
+ mode: CipherOrWrapMode,
159
+ key: CryptoKey,
160
+ data: ArrayBuffer,
161
+ { iv }: AesCbcParams
162
+ ): Promise<ArrayBuffer> {
163
+ validateByteLength(iv, 'algorithm.iv', 16);
164
+ return NativeQuickCrypto.webcrypto.aesCipher(
165
+ mode,
166
+ key.keyObject.handle,
167
+ data,
168
+ getVariant('AES-CBC', key.algorithm.length as AESLength),
169
+ bufferLikeToArrayBuffer(iv)
170
+ );
171
+ }
178
172
 
179
- // function asyncAesGcmCipher(
180
- // mode,
181
- // key,
182
- // data,
183
- // { iv, additionalData, tagLength = 128 }) {
184
- // if (!ArrayPrototypeIncludes(kTagLengths, tagLength)) {
185
- // return PromiseReject(lazyDOMException(
186
- // `${tagLength} is not a valid AES-GCM tag length`,
187
- // 'OperationError'));
188
- // }
189
-
190
- // validateMaxBufferLength(iv, 'algorithm.iv');
191
-
192
- // if (additionalData !== undefined) {
193
- // validateMaxBufferLength(additionalData, 'algorithm.additionalData');
194
- // }
195
-
196
- // const tagByteLength = MathFloor(tagLength / 8);
197
- // let tag;
198
- // switch (mode) {
199
- // case kWebCryptoCipherDecrypt: {
200
- // const slice = ArrayBufferIsView(data) ?
201
- // TypedArrayPrototypeSlice : ArrayBufferPrototypeSlice;
202
- // tag = slice(data, -tagByteLength);
203
-
204
- // // Refs: https://www.w3.org/TR/WebCryptoAPI/#aes-gcm-operations
205
- // //
206
- // // > If *plaintext* has a length less than *tagLength* bits, then `throw`
207
- // // > an `OperationError`.
208
- // if (tagByteLength > tag.byteLength) {
209
- // return PromiseReject(lazyDOMException(
210
- // 'The provided data is too small.',
211
- // 'OperationError'));
212
- // }
213
-
214
- // data = slice(data, 0, -tagByteLength);
215
- // break;
216
- // }
217
- // case kWebCryptoCipherEncrypt:
218
- // tag = tagByteLength;
219
- // break;
220
- // }
221
-
222
- // return jobPromise(() => new AESCipherJob(
223
- // kCryptoJobAsync,
173
+ // function asyncAesKwCipher(
174
+ // mode: CipherOrWrapMode,
175
+ // key: CryptoKey,
176
+ // data: BufferLike
177
+ // ): Promise<ArrayBuffer> {
178
+ // return NativeQuickCrypto.webcrypto.aesCipher(
224
179
  // mode,
225
- // key[kKeyObject][kHandle],
180
+ // key.keyObject.handle,
226
181
  // data,
227
- // getVariant('AES-GCM', key.algorithm.length),
228
- // iv,
229
- // tag,
230
- // additionalData));
182
+ // getVariant('AES-KW', key.algorithm.length)
183
+ // );
231
184
  // }
232
185
 
233
- // export const aesCipher = (mode, key, data, algorithm) => {
234
- // switch (algorithm.name) {
235
- // case 'AES-CTR': return asyncAesCtrCipher(mode, key, data, algorithm);
236
- // case 'AES-CBC': return asyncAesCbcCipher(mode, key, data, algorithm);
237
- // case 'AES-GCM': return asyncAesGcmCipher(mode, key, data, algorithm);
238
- // case 'AES-KW': return asyncAesKwCipher(mode, key, data);
239
- // }
240
- // };
241
-
242
- // export const aesGenerateKey = async (algorithm, extractable, keyUsages) => {
243
- // const { name, length } = algorithm;
244
- // if (!ArrayPrototypeIncludes(kAesKeyLengths, length)) {
245
- // throw lazyDOMException(
246
- // 'AES key length must be 128, 192, or 256 bits',
247
- // 'OperationError');
248
- // }
249
-
250
- // const checkUsages = ['wrapKey', 'unwrapKey'];
251
- // if (name !== 'AES-KW')
252
- // ArrayPrototypePush(checkUsages, 'encrypt', 'decrypt');
253
-
254
- // const usagesSet = new SafeSet(keyUsages);
255
- // if (hasAnyNotIn(usagesSet, checkUsages)) {
256
- // throw lazyDOMException(
257
- // 'Unsupported key usage for an AES key',
258
- // 'SyntaxError');
259
- // }
260
-
261
- // const key = await generateKey('aes', { length }).catch((err) => {
262
- // throw lazyDOMException(
263
- // 'The operation failed for an operation-specific reason' +
264
- // `[${err.message}]`,
265
- // { name: 'OperationError', cause: err });
266
- // });
267
-
268
- // return new InternalCryptoKey(
269
- // key,
270
- // { name, length },
271
- // ArrayFrom(usagesSet),
272
- // extractable);
273
- // };
186
+ function asyncAesGcmCipher(
187
+ mode: CipherOrWrapMode,
188
+ key: CryptoKey,
189
+ data: ArrayBuffer,
190
+ { iv, additionalData, tagLength = 128 }: AesGcmParams
191
+ ) {
192
+ if (!kTagLengths.includes(tagLength)) {
193
+ throw lazyDOMException(
194
+ `${tagLength} is not a valid AES-GCM tag length`,
195
+ 'OperationError'
196
+ );
197
+ }
198
+
199
+ validateMaxBufferLength(iv, 'algorithm.iv');
200
+
201
+ if (additionalData !== undefined) {
202
+ validateMaxBufferLength(additionalData, 'algorithm.additionalData');
203
+ }
204
+
205
+ const tagByteLength = Math.floor(tagLength / 8);
206
+ let length: number | undefined;
207
+ let tag = new ArrayBuffer(0);
208
+ switch (mode) {
209
+ case CipherOrWrapMode.kWebCryptoCipherDecrypt: {
210
+ // const slice = ArrayBuffer.isView(data)
211
+ // ? DataView.prototype.buffer.slice
212
+ // : ArrayBuffer.prototype.slice;
213
+ tag = data.slice(-tagByteLength);
214
+
215
+ // Refs: https://www.w3.org/TR/WebCryptoAPI/#aes-gcm-operations
216
+ //
217
+ // > If *plaintext* has a length less than *tagLength* bits, then `throw`
218
+ // > an `OperationError`.
219
+ if (tagByteLength > tag.byteLength) {
220
+ throw lazyDOMException(
221
+ 'The provided data is too small.',
222
+ 'OperationError'
223
+ );
224
+ }
225
+
226
+ data = data.slice(0, -tagByteLength);
227
+ break;
228
+ }
229
+ case CipherOrWrapMode.kWebCryptoCipherEncrypt:
230
+ length = tagByteLength;
231
+ break;
232
+ }
233
+
234
+ return NativeQuickCrypto.webcrypto.aesCipher(
235
+ mode,
236
+ key.keyObject.handle,
237
+ data,
238
+ getVariant('AES-GCM', key.algorithm.length as AESLength),
239
+ bufferLikeToArrayBuffer(iv),
240
+ length,
241
+ bufferLikeToArrayBuffer(tag),
242
+ bufferLikeToArrayBuffer(additionalData || new ArrayBuffer(0))
243
+ );
244
+ }
245
+
246
+ export const aesCipher = (
247
+ mode: CipherOrWrapMode,
248
+ key: CryptoKey,
249
+ data: ArrayBuffer,
250
+ algorithm: EncryptDecryptParams // | WrapUnwrapParams
251
+ ): Promise<ArrayBuffer> => {
252
+ switch (algorithm.name) {
253
+ case 'AES-CTR':
254
+ return asyncAesCtrCipher(mode, key, data, algorithm);
255
+ case 'AES-CBC':
256
+ return asyncAesCbcCipher(mode, key, data, algorithm);
257
+ case 'AES-GCM':
258
+ return asyncAesGcmCipher(mode, key, data, algorithm);
259
+ // case 'AES-KW':
260
+ // return asyncAesKwCipher(mode, key, data);
261
+ }
262
+ throw new Error(`aesCipher: Unknown algorithm ${algorithm.name}`);
263
+ };
264
+
265
+ export const aesGenerateKey = async (
266
+ algorithm: AesKeyGenParams,
267
+ extractable: boolean,
268
+ keyUsages: KeyUsage[]
269
+ ): Promise<CryptoKey> => {
270
+ const { name, length } = algorithm;
271
+ if (!name) {
272
+ throw lazyDOMException('Algorithm name is undefined', 'SyntaxError');
273
+ }
274
+ if (!kAesKeyLengths.includes(length)) {
275
+ throw lazyDOMException(
276
+ 'AES key length must be 128, 192, or 256 bits',
277
+ 'OperationError'
278
+ );
279
+ }
280
+
281
+ const checkUsages = ['wrapKey', 'unwrapKey'];
282
+ if (name !== 'AES-KW') {
283
+ checkUsages.push('encrypt', 'decrypt');
284
+ }
285
+ // const usagesSet = new SafeSet(keyUsages);
286
+ if (hasAnyNotIn(keyUsages, checkUsages)) {
287
+ throw lazyDOMException(
288
+ `Unsupported key usage for an AES key: ${keyUsages}`,
289
+ 'SyntaxError'
290
+ );
291
+ }
292
+
293
+ const [err, key] = await generateKeyPromise('aes', { length });
294
+ if (err) {
295
+ throw lazyDOMException(
296
+ `aesGenerateKey (generateKeyPromise) failed: [${err.message}]`,
297
+ {
298
+ name: 'OperationError',
299
+ cause: err,
300
+ }
301
+ );
302
+ }
303
+
304
+ return new CryptoKey(
305
+ key as SecretKeyObject,
306
+ { name, length },
307
+ Array.from(keyUsages),
308
+ extractable
309
+ );
310
+ };
274
311
 
275
312
  export const aesImportKey = async (
276
313
  algorithm: SubtleAlgorithm,