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.
- package/README.md +11 -63
- package/android/CMakeLists.txt +2 -0
- package/cpp/Cipher/MGLRsa.cpp +179 -3
- package/cpp/Cipher/MGLRsa.h +40 -0
- package/cpp/JSIUtils/MGLJSIUtils.h +8 -0
- package/cpp/MGLKeys.cpp +41 -43
- package/cpp/MGLKeys.h +9 -2
- package/cpp/MGLQuickCryptoHostObject.cpp +6 -6
- package/cpp/Sig/MGLSignHostObjects.cpp +22 -15
- package/cpp/Utils/MGLUtils.cpp +71 -1
- package/cpp/Utils/MGLUtils.h +55 -1
- package/cpp/webcrypto/MGLWebCrypto.cpp +89 -37
- package/cpp/webcrypto/MGLWebCrypto.h +5 -7
- package/cpp/webcrypto/crypto_aes.cpp +516 -0
- package/cpp/webcrypto/crypto_aes.h +79 -0
- package/cpp/webcrypto/crypto_ec.cpp +4 -20
- package/cpp/webcrypto/crypto_ec.h +0 -5
- package/cpp/webcrypto/crypto_keygen.cpp +86 -0
- package/cpp/webcrypto/crypto_keygen.h +38 -0
- package/lib/commonjs/Cipher.js +3 -1
- package/lib/commonjs/Cipher.js.map +1 -1
- package/lib/commonjs/Hashnames.js +20 -8
- package/lib/commonjs/Hashnames.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/Cipher.js +13 -1
- package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/aes.js +6 -0
- package/lib/commonjs/NativeQuickCrypto/aes.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/keygen.js +6 -0
- package/lib/commonjs/NativeQuickCrypto/keygen.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/rsa.js +6 -0
- package/lib/commonjs/NativeQuickCrypto/rsa.js.map +1 -0
- package/lib/commonjs/Utils.js +30 -6
- package/lib/commonjs/Utils.js.map +1 -1
- package/lib/commonjs/aes.js +184 -227
- package/lib/commonjs/aes.js.map +1 -1
- package/lib/commonjs/index.js +12 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/keygen.js +56 -0
- package/lib/commonjs/keygen.js.map +1 -0
- package/lib/commonjs/keys.js +74 -5
- package/lib/commonjs/keys.js.map +1 -1
- package/lib/commonjs/rsa.js +115 -196
- package/lib/commonjs/rsa.js.map +1 -1
- package/lib/commonjs/sig.js.map +1 -1
- package/lib/commonjs/subtle.js +140 -78
- package/lib/commonjs/subtle.js.map +1 -1
- package/lib/commonjs/webcrypto.js +14 -0
- package/lib/commonjs/webcrypto.js.map +1 -0
- package/lib/module/Cipher.js +3 -1
- package/lib/module/Cipher.js.map +1 -1
- package/lib/module/Hashnames.js +20 -8
- package/lib/module/Hashnames.js.map +1 -1
- package/lib/module/NativeQuickCrypto/Cipher.js +12 -0
- package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -1
- package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
- package/lib/module/NativeQuickCrypto/aes.js +2 -0
- package/lib/module/NativeQuickCrypto/aes.js.map +1 -0
- package/lib/module/NativeQuickCrypto/keygen.js +2 -0
- package/lib/module/NativeQuickCrypto/keygen.js.map +1 -0
- package/lib/module/NativeQuickCrypto/rsa.js +2 -0
- package/lib/module/NativeQuickCrypto/rsa.js.map +1 -0
- package/lib/module/Utils.js +26 -5
- package/lib/module/Utils.js.map +1 -1
- package/lib/module/aes.js +183 -228
- package/lib/module/aes.js.map +1 -1
- package/lib/module/index.js +11 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/keygen.js +47 -0
- package/lib/module/keygen.js.map +1 -0
- package/lib/module/keys.js +68 -4
- package/lib/module/keys.js.map +1 -1
- package/lib/module/rsa.js +115 -198
- package/lib/module/rsa.js.map +1 -1
- package/lib/module/sig.js.map +1 -1
- package/lib/module/subtle.js +143 -82
- package/lib/module/subtle.js.map +1 -1
- package/lib/module/webcrypto.js +8 -0
- package/lib/module/webcrypto.js.map +1 -0
- package/lib/typescript/Cipher.d.ts +0 -1
- package/lib/typescript/Cipher.d.ts.map +1 -1
- package/lib/typescript/Hash.d.ts.map +1 -1
- package/lib/typescript/Hashnames.d.ts +2 -2
- package/lib/typescript/Hashnames.d.ts.map +1 -1
- package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +5 -0
- package/lib/typescript/NativeQuickCrypto/Cipher.d.ts.map +1 -1
- package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +4 -1
- package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts.map +1 -1
- package/lib/typescript/NativeQuickCrypto/aes.d.ts +5 -0
- package/lib/typescript/NativeQuickCrypto/aes.d.ts.map +1 -0
- package/lib/typescript/NativeQuickCrypto/keygen.d.ts +4 -0
- package/lib/typescript/NativeQuickCrypto/keygen.d.ts.map +1 -0
- package/lib/typescript/NativeQuickCrypto/rsa.d.ts +5 -0
- package/lib/typescript/NativeQuickCrypto/rsa.d.ts.map +1 -0
- package/lib/typescript/NativeQuickCrypto/webcrypto.d.ts +12 -2
- package/lib/typescript/NativeQuickCrypto/webcrypto.d.ts.map +1 -1
- package/lib/typescript/Utils.d.ts +4 -4
- package/lib/typescript/Utils.d.ts.map +1 -1
- package/lib/typescript/aes.d.ts +18 -1
- package/lib/typescript/aes.d.ts.map +1 -1
- package/lib/typescript/ec.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +27 -24
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/keygen.d.ts +6 -0
- package/lib/typescript/keygen.d.ts.map +1 -0
- package/lib/typescript/keys.d.ts +58 -17
- package/lib/typescript/keys.d.ts.map +1 -1
- package/lib/typescript/rsa.d.ts +9 -1
- package/lib/typescript/rsa.d.ts.map +1 -1
- package/lib/typescript/sig.d.ts +3 -17
- package/lib/typescript/sig.d.ts.map +1 -1
- package/lib/typescript/subtle.d.ts +6 -5
- package/lib/typescript/subtle.d.ts.map +1 -1
- package/lib/typescript/webcrypto.d.ts +9 -0
- package/lib/typescript/webcrypto.d.ts.map +1 -0
- package/package.json +12 -12
- package/src/Cipher.ts +1 -1
- package/src/Hashnames.ts +23 -21
- package/src/NativeQuickCrypto/Cipher.ts +32 -0
- package/src/NativeQuickCrypto/NativeQuickCrypto.ts +6 -0
- package/src/NativeQuickCrypto/aes.ts +14 -0
- package/src/NativeQuickCrypto/keygen.ts +7 -0
- package/src/NativeQuickCrypto/rsa.ts +12 -0
- package/src/NativeQuickCrypto/webcrypto.ts +26 -2
- package/src/Utils.ts +37 -8
- package/src/aes.ts +259 -222
- package/src/index.ts +10 -1
- package/src/keygen.ts +80 -0
- package/src/keys.ts +143 -30
- package/src/rsa.ts +161 -187
- package/src/sig.ts +7 -23
- package/src/subtle.ts +211 -93
- 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(
|
|
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
|
-
|
|
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
|
-
|
|
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):
|
|
212
|
-
return f
|
|
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
|
|
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<
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
//
|
|
167
|
-
//
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
|
180
|
-
// mode,
|
|
181
|
-
// key,
|
|
182
|
-
// data
|
|
183
|
-
//
|
|
184
|
-
//
|
|
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
|
|
180
|
+
// key.keyObject.handle,
|
|
226
181
|
// data,
|
|
227
|
-
// getVariant('AES-
|
|
228
|
-
//
|
|
229
|
-
// tag,
|
|
230
|
-
// additionalData));
|
|
182
|
+
// getVariant('AES-KW', key.algorithm.length)
|
|
183
|
+
// );
|
|
231
184
|
// }
|
|
232
185
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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,
|