react-native-quick-crypto 0.2.0 → 0.3.0

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 (69) hide show
  1. package/README.md +23 -6
  2. package/cpp/Cipher/MGLCipherHostObject.cpp +64 -48
  3. package/cpp/Cipher/MGLCipherKeys.cpp +1469 -0
  4. package/cpp/Cipher/MGLCipherKeys.h +124 -0
  5. package/cpp/Cipher/MGLCreateCipherInstaller.cpp +56 -53
  6. package/cpp/Cipher/MGLCreateCipherInstaller.h +5 -0
  7. package/cpp/Cipher/MGLCreateDecipherInstaller.cpp +56 -53
  8. package/cpp/Cipher/MGLGenerateKeyPairInstaller.cpp +107 -0
  9. package/cpp/Cipher/MGLGenerateKeyPairInstaller.h +32 -0
  10. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.cpp +60 -0
  11. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.h +35 -0
  12. package/cpp/Cipher/MGLPublicCipher.h +120 -0
  13. package/cpp/Cipher/MGLPublicCipherInstaller.h +113 -0
  14. package/cpp/Cipher/MGLRsa.cpp +188 -0
  15. package/cpp/Cipher/MGLRsa.h +61 -0
  16. package/cpp/JSIUtils/MGLJSIUtils.h +24 -0
  17. package/cpp/JSIUtils/MGLThreadAwareHostObject.h +1 -1
  18. package/cpp/MGLQuickCryptoHostObject.cpp +42 -3
  19. package/cpp/Utils/MGLUtils.cpp +156 -0
  20. package/cpp/Utils/MGLUtils.h +254 -0
  21. package/lib/commonjs/Cipher.js +307 -0
  22. package/lib/commonjs/Cipher.js.map +1 -1
  23. package/lib/commonjs/NativeQuickCrypto/Cipher.js +11 -0
  24. package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -1
  25. package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  26. package/lib/commonjs/QuickCrypto.js +8 -0
  27. package/lib/commonjs/QuickCrypto.js.map +1 -1
  28. package/lib/commonjs/Utils.js +82 -1
  29. package/lib/commonjs/Utils.js.map +1 -1
  30. package/lib/commonjs/constants.js +86 -0
  31. package/lib/commonjs/constants.js.map +1 -0
  32. package/lib/commonjs/index.js +5 -0
  33. package/lib/commonjs/index.js.map +1 -1
  34. package/lib/commonjs/keys.js +207 -0
  35. package/lib/commonjs/keys.js.map +1 -0
  36. package/lib/module/Cipher.js +296 -3
  37. package/lib/module/Cipher.js.map +1 -1
  38. package/lib/module/NativeQuickCrypto/Cipher.js +9 -1
  39. package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -1
  40. package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  41. package/lib/module/QuickCrypto.js +8 -1
  42. package/lib/module/QuickCrypto.js.map +1 -1
  43. package/lib/module/Utils.js +67 -1
  44. package/lib/module/Utils.js.map +1 -1
  45. package/lib/module/constants.js +79 -0
  46. package/lib/module/constants.js.map +1 -0
  47. package/lib/module/index.js +2 -0
  48. package/lib/module/index.js.map +1 -1
  49. package/lib/module/keys.js +193 -0
  50. package/lib/module/keys.js.map +1 -0
  51. package/lib/typescript/Cipher.d.ts +58 -1
  52. package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +10 -0
  53. package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +6 -1
  54. package/lib/typescript/QuickCrypto.d.ts +105 -1
  55. package/lib/typescript/Utils.d.ts +11 -0
  56. package/lib/typescript/constants.d.ts +75 -0
  57. package/lib/typescript/index.d.ts +2 -0
  58. package/lib/typescript/keys.d.ts +60 -0
  59. package/package.json +5 -5
  60. package/react-native-quick-crypto.podspec +1 -1
  61. package/src/.DS_Store +0 -0
  62. package/src/Cipher.ts +444 -3
  63. package/src/NativeQuickCrypto/Cipher.ts +44 -0
  64. package/src/NativeQuickCrypto/NativeQuickCrypto.ts +13 -1
  65. package/src/QuickCrypto.ts +12 -0
  66. package/src/Utils.ts +91 -0
  67. package/src/constants.ts +79 -0
  68. package/src/index.ts +4 -0
  69. package/src/keys.ts +297 -0
@@ -1,4 +1,13 @@
1
1
  import type { BinaryLike } from 'src/Utils';
2
+ import type { Buffer } from '@craftzdog/react-native-buffer';
3
+
4
+ // TODO(osp) on node this is defined on the native side
5
+ // Need to do the same so that values are always in sync
6
+ export enum RSAKeyVariant {
7
+ kKeyVariantRSA_SSA_PKCS1_v1_5,
8
+ kKeyVariantRSA_PSS,
9
+ kKeyVariantRSA_OAEP,
10
+ }
2
11
 
3
12
  export type InternalCipher = {
4
13
  update: (data: BinaryLike | ArrayBufferView) => ArrayBuffer;
@@ -23,3 +32,38 @@ export type CreateDecipherMethod = (params: {
23
32
  cipher_key: ArrayBuffer;
24
33
  auth_tag_len: number;
25
34
  }) => InternalCipher;
35
+
36
+ export type PublicEncryptMethod = (
37
+ data: ArrayBuffer,
38
+ format: number,
39
+ type: any,
40
+ passphrase: any,
41
+ buffer: ArrayBuffer,
42
+ padding: number,
43
+ oaepHash: any,
44
+ oaepLabel: any
45
+ ) => Buffer;
46
+ export type PrivateDecryptMethod = (
47
+ data: ArrayBuffer,
48
+ format: number,
49
+ type: any,
50
+ passphrase: any,
51
+ buffer: ArrayBuffer,
52
+ padding: number,
53
+ oaepHash: any,
54
+ oaepLabel: any
55
+ ) => Buffer;
56
+
57
+ export type GenerateKeyPairMethod = (
58
+ keyVariant: RSAKeyVariant,
59
+ modulusLength: number,
60
+ publicExponent: number,
61
+ ...rest: any[]
62
+ ) => Promise<[error: unknown, publicBuffer: any, privateBuffer: any]>;
63
+
64
+ export type GenerateKeyPairSyncMethod = (
65
+ keyVariant: RSAKeyVariant,
66
+ modulusLength: number,
67
+ publicExponent: number,
68
+ ...rest: any[]
69
+ ) => [error: unknown, publicBuffer: any, privateBuffer: any];
@@ -3,7 +3,14 @@ import type { CreateHmacMethod } from './hmac';
3
3
  import type { CreateHashMethod } from './hash';
4
4
  import type { Pbkdf2Object } from './pbkdf2';
5
5
  import type { RandomObject } from './random';
6
- import type { CreateCipherMethod, CreateDecipherMethod } from './Cipher';
6
+ import type {
7
+ CreateCipherMethod,
8
+ CreateDecipherMethod,
9
+ PublicEncryptMethod,
10
+ PrivateDecryptMethod,
11
+ GenerateKeyPairMethod,
12
+ GenerateKeyPairSyncMethod,
13
+ } from './Cipher';
7
14
 
8
15
  interface NativeQuickCryptoSpec {
9
16
  createHmac: CreateHmacMethod;
@@ -12,6 +19,11 @@ interface NativeQuickCryptoSpec {
12
19
  createHash: CreateHashMethod;
13
20
  createCipher: CreateCipherMethod;
14
21
  createDecipher: CreateDecipherMethod;
22
+ publicEncrypt: PublicEncryptMethod;
23
+ publicDecrypt: PublicEncryptMethod;
24
+ privateDecrypt: PrivateDecryptMethod;
25
+ generateKeyPair: GenerateKeyPairMethod;
26
+ generateKeyPairSync: GenerateKeyPairSyncMethod;
15
27
  }
16
28
 
17
29
  // global func declaration for JSI functions
@@ -5,9 +5,15 @@ import {
5
5
  createCipheriv,
6
6
  createDecipher,
7
7
  createDecipheriv,
8
+ publicEncrypt,
9
+ publicDecrypt,
10
+ privateDecrypt,
11
+ generateKeyPair,
12
+ generateKeyPairSync,
8
13
  } from './Cipher';
9
14
  import { createHmac } from './Hmac';
10
15
  import { createHash } from './Hash';
16
+ import { constants } from './constants';
11
17
 
12
18
  export const QuickCrypto = {
13
19
  createHmac,
@@ -18,6 +24,12 @@ export const QuickCrypto = {
18
24
  createCipheriv,
19
25
  createDecipher,
20
26
  createDecipheriv,
27
+ publicEncrypt,
28
+ publicDecrypt,
29
+ privateDecrypt,
30
+ generateKeyPair,
31
+ generateKeyPairSync,
32
+ constants,
21
33
  ...pbkdf2,
22
34
  ...random,
23
35
  };
package/src/Utils.ts CHANGED
@@ -24,6 +24,9 @@ export function getDefaultEncoding(): CipherEncoding {
24
24
  return defaultEncoding;
25
25
  }
26
26
 
27
+ export const kEmptyObject = Object.freeze(Object.create(null));
28
+
29
+ // Should be used by Cipher (or any other module that requires valid encodings)
27
30
  // function slowCases(enc: string) {
28
31
  // switch (enc.length) {
29
32
  // case 4:
@@ -149,3 +152,91 @@ export function binaryLikeToArrayBuffer(
149
152
  export function ab2str(buf: ArrayBuffer, encoding: string = 'hex') {
150
153
  return Buffer.from(buf).toString(encoding);
151
154
  }
155
+
156
+ export function validateString(str: any, name?: string): str is string {
157
+ const isString = typeof str === 'string';
158
+ if (isString) {
159
+ throw new Error(`${name} is not a string`);
160
+ }
161
+ return isString;
162
+ }
163
+
164
+ export function validateFunction(f: any): f is Function {
165
+ return f != null && typeof f === 'function';
166
+ }
167
+
168
+ export function isStringOrBuffer(val: any): val is string | ArrayBuffer {
169
+ return typeof val === 'string' || ArrayBuffer.isView(val);
170
+ }
171
+
172
+ export function validateObject<T>(
173
+ value: any,
174
+ name: string,
175
+ options?: {
176
+ allowArray: boolean;
177
+ allowFunction: boolean;
178
+ nullable: boolean;
179
+ } | null
180
+ ): value is T {
181
+ const useDefaultOptions = options == null;
182
+ const allowArray = useDefaultOptions ? false : options.allowArray;
183
+ const allowFunction = useDefaultOptions ? false : options.allowFunction;
184
+ const nullable = useDefaultOptions ? false : options.nullable;
185
+ if (
186
+ (!nullable && value === null) ||
187
+ (!allowArray && Array.isArray(value)) ||
188
+ (typeof value !== 'object' &&
189
+ (!allowFunction || typeof value !== 'function'))
190
+ ) {
191
+ throw new Error(`${name} is not a valid object $${value}`);
192
+ }
193
+ return true;
194
+ }
195
+
196
+ export function validateInt32(
197
+ value: any,
198
+ name: string,
199
+ min = -2147483648,
200
+ max = 2147483647
201
+ ) {
202
+ // The defaults for min and max correspond to the limits of 32-bit integers.
203
+ if (typeof value !== 'number') {
204
+ throw new Error(`Invalid argument - ${name} is not a number: ${value}`);
205
+ }
206
+ if (!Number.isInteger(value)) {
207
+ throw new Error(
208
+ `Argument out of range - ${name} out of integer range: ${value}`
209
+ );
210
+ }
211
+ if (value < min || value > max) {
212
+ throw new Error(
213
+ `Invalid argument - ${name} out of range >= ${min} && <= ${max}: ${value}`
214
+ );
215
+ }
216
+ }
217
+
218
+ export function validateUint32(
219
+ value: number,
220
+ name: string,
221
+ positive?: boolean
222
+ ) {
223
+ if (typeof value !== 'number') {
224
+ // throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
225
+ throw new Error(`Invalid argument - ${name} is not a number: ${value}`);
226
+ }
227
+ if (!Number.isInteger(value)) {
228
+ // throw new ERR_OUT_OF_RANGE(name, 'an integer', value);
229
+ throw new Error(
230
+ `Argument out of range - ${name} out of integer range: ${value}`
231
+ );
232
+ }
233
+ const min = positive ? 1 : 0;
234
+ // 2 ** 32 === 4294967296
235
+ const max = 4_294_967_295;
236
+ if (value < min || value > max) {
237
+ // throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);
238
+ throw new Error(
239
+ `Invalid argument - ${name} out of range >= ${min} && <= ${max}: ${value}`
240
+ );
241
+ }
242
+ }
@@ -0,0 +1,79 @@
1
+ // Taken by printing node.crypto.constants
2
+ // Node declares them as enums on v8 directly
3
+ // Whenever the API gets updated (or some dependency like OpenSSL) I guess we will have to revisit these
4
+ export const constants = {
5
+ OPENSSL_VERSION_NUMBER: 269488367,
6
+ SSL_OP_ALL: 2147485780,
7
+ SSL_OP_ALLOW_NO_DHE_KEX: 1024,
8
+ SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: 262144,
9
+ SSL_OP_CIPHER_SERVER_PREFERENCE: 4194304,
10
+ SSL_OP_CISCO_ANYCONNECT: 32768,
11
+ SSL_OP_COOKIE_EXCHANGE: 8192,
12
+ SSL_OP_CRYPTOPRO_TLSEXT_BUG: 2147483648,
13
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: 2048,
14
+ SSL_OP_EPHEMERAL_RSA: 0,
15
+ SSL_OP_LEGACY_SERVER_CONNECT: 4,
16
+ SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: 0,
17
+ SSL_OP_MICROSOFT_SESS_ID_BUG: 0,
18
+ SSL_OP_MSIE_SSLV2_RSA_PADDING: 0,
19
+ SSL_OP_NETSCAPE_CA_DN_BUG: 0,
20
+ SSL_OP_NETSCAPE_CHALLENGE_BUG: 0,
21
+ SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: 0,
22
+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: 0,
23
+ SSL_OP_NO_COMPRESSION: 131072,
24
+ SSL_OP_NO_ENCRYPT_THEN_MAC: 524288,
25
+ SSL_OP_NO_QUERY_MTU: 4096,
26
+ SSL_OP_NO_RENEGOTIATION: 1073741824,
27
+ SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: 65536,
28
+ SSL_OP_NO_SSLv2: 0,
29
+ SSL_OP_NO_SSLv3: 33554432,
30
+ SSL_OP_NO_TICKET: 16384,
31
+ SSL_OP_NO_TLSv1: 67108864,
32
+ SSL_OP_NO_TLSv1_1: 268435456,
33
+ SSL_OP_NO_TLSv1_2: 134217728,
34
+ SSL_OP_NO_TLSv1_3: 536870912,
35
+ SSL_OP_PKCS1_CHECK_1: 0,
36
+ SSL_OP_PKCS1_CHECK_2: 0,
37
+ SSL_OP_PRIORITIZE_CHACHA: 2097152,
38
+ SSL_OP_SINGLE_DH_USE: 0,
39
+ SSL_OP_SINGLE_ECDH_USE: 0,
40
+ SSL_OP_SSLEAY_080_CLIENT_DH_BUG: 0,
41
+ SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: 0,
42
+ SSL_OP_TLS_BLOCK_PADDING_BUG: 0,
43
+ SSL_OP_TLS_D5_BUG: 0,
44
+ SSL_OP_TLS_ROLLBACK_BUG: 8388608,
45
+ ENGINE_METHOD_RSA: 1,
46
+ ENGINE_METHOD_DSA: 2,
47
+ ENGINE_METHOD_DH: 4,
48
+ ENGINE_METHOD_RAND: 8,
49
+ ENGINE_METHOD_EC: 2048,
50
+ ENGINE_METHOD_CIPHERS: 64,
51
+ ENGINE_METHOD_DIGESTS: 128,
52
+ ENGINE_METHOD_PKEY_METHS: 512,
53
+ ENGINE_METHOD_PKEY_ASN1_METHS: 1024,
54
+ ENGINE_METHOD_ALL: 65535,
55
+ ENGINE_METHOD_NONE: 0,
56
+ DH_CHECK_P_NOT_SAFE_PRIME: 2,
57
+ DH_CHECK_P_NOT_PRIME: 1,
58
+ DH_UNABLE_TO_CHECK_GENERATOR: 4,
59
+ DH_NOT_SUITABLE_GENERATOR: 8,
60
+ ALPN_ENABLED: 1,
61
+ RSA_PKCS1_PADDING: 1,
62
+ RSA_SSLV23_PADDING: 2,
63
+ RSA_NO_PADDING: 3,
64
+ RSA_PKCS1_OAEP_PADDING: 4,
65
+ RSA_X931_PADDING: 5,
66
+ RSA_PKCS1_PSS_PADDING: 6,
67
+ RSA_PSS_SALTLEN_DIGEST: -1,
68
+ RSA_PSS_SALTLEN_MAX_SIGN: -2,
69
+ RSA_PSS_SALTLEN_AUTO: -2,
70
+ defaultCoreCipherList:
71
+ 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA',
72
+ TLS1_VERSION: 769,
73
+ TLS1_1_VERSION: 770,
74
+ TLS1_2_VERSION: 771,
75
+ TLS1_3_VERSION: 772,
76
+ POINT_CONVERSION_COMPRESSED: 2,
77
+ POINT_CONVERSION_UNCOMPRESSED: 4,
78
+ POINT_CONVERSION_HYBRID: 6,
79
+ };
package/src/index.ts CHANGED
@@ -1 +1,5 @@
1
+ import { QuickCrypto } from './QuickCrypto';
2
+
1
3
  export * from './QuickCrypto';
4
+
5
+ export default QuickCrypto;
package/src/keys.ts ADDED
@@ -0,0 +1,297 @@
1
+ import { BinaryLike, binaryLikeToArrayBuffer, isStringOrBuffer } from './Utils';
2
+
3
+ // On node this value is defined on the native side, for now I'm just creating it here in JS
4
+ // TODO(osp) move this into native side to make sure they always match
5
+ enum KFormatType {
6
+ kKeyFormatDER,
7
+ kKeyFormatPEM,
8
+ kKeyFormatJWK,
9
+ }
10
+
11
+ enum KeyInputContext {
12
+ kConsumePublic,
13
+ kConsumePrivate,
14
+ kCreatePublic,
15
+ kCreatePrivate,
16
+ }
17
+
18
+ enum KeyEncoding {
19
+ kKeyEncodingPKCS1,
20
+ kKeyEncodingPKCS8,
21
+ kKeyEncodingSPKI,
22
+ kKeyEncodingSEC1,
23
+ }
24
+
25
+ const encodingNames = {
26
+ [KeyEncoding.kKeyEncodingPKCS1]: 'pkcs1',
27
+ [KeyEncoding.kKeyEncodingPKCS8]: 'pkcs8',
28
+ [KeyEncoding.kKeyEncodingSPKI]: 'spki',
29
+ [KeyEncoding.kKeyEncodingSEC1]: 'sec1',
30
+ };
31
+
32
+ function option(name: string, objName: string | undefined) {
33
+ return objName === undefined
34
+ ? `options.${name}`
35
+ : `options.${objName}.${name}`;
36
+ }
37
+
38
+ function parseKeyFormat(
39
+ formatStr: string,
40
+ defaultFormat: KFormatType | undefined,
41
+ optionName?: string
42
+ ) {
43
+ if (formatStr === undefined && defaultFormat !== undefined)
44
+ return defaultFormat;
45
+ else if (formatStr === 'pem') return KFormatType.kKeyFormatPEM;
46
+ else if (formatStr === 'der') return KFormatType.kKeyFormatDER;
47
+ else if (formatStr === 'jwk') return KFormatType.kKeyFormatJWK;
48
+ throw new Error(`Invalid key format str: ${optionName}`);
49
+ // throw new ERR_INVALID_ARG_VALUE(optionName, formatStr);
50
+ }
51
+
52
+ function parseKeyType(
53
+ typeStr: string,
54
+ required: boolean,
55
+ keyType: string,
56
+ isPublic: boolean,
57
+ optionName: string
58
+ ) {
59
+ if (typeStr === undefined && !required) {
60
+ return undefined;
61
+ } else if (typeStr === 'pkcs1') {
62
+ if (keyType !== undefined && keyType !== 'rsa') {
63
+ throw new Error(
64
+ `Crypto incompatible key options: ${typeStr} can only be used for RSA keys`
65
+ );
66
+ // throw new ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS(
67
+ // typeStr,
68
+ // 'can only be used for RSA keys'
69
+ // );
70
+ }
71
+ return KeyEncoding.kKeyEncodingPKCS1;
72
+ } else if (typeStr === 'spki' && isPublic !== false) {
73
+ return KeyEncoding.kKeyEncodingSPKI;
74
+ } else if (typeStr === 'pkcs8' && isPublic !== true) {
75
+ return KeyEncoding.kKeyEncodingPKCS8;
76
+ } else if (typeStr === 'sec1' && isPublic !== true) {
77
+ if (keyType !== undefined && keyType !== 'ec') {
78
+ throw new Error(
79
+ `Incompatible key options ${typeStr} can only be used for EC keys`
80
+ );
81
+ }
82
+ return KeyEncoding.kKeyEncodingSEC1;
83
+ }
84
+
85
+ throw new Error(`Invalid option ${optionName} - ${typeStr}`);
86
+ }
87
+
88
+ function parseKeyFormatAndType(
89
+ enc: any,
90
+ keyType: any,
91
+ isPublic: any,
92
+ objName: any
93
+ ) {
94
+ const { format: formatStr, type: typeStr } = enc;
95
+
96
+ const isInput = keyType === undefined;
97
+ const format = parseKeyFormat(
98
+ formatStr,
99
+ isInput ? KFormatType.kKeyFormatPEM : undefined,
100
+ option('format', objName)
101
+ );
102
+
103
+ const isRequired =
104
+ (!isInput || format === KFormatType.kKeyFormatDER) &&
105
+ format !== KFormatType.kKeyFormatJWK;
106
+ const type = parseKeyType(
107
+ typeStr,
108
+ isRequired,
109
+ keyType,
110
+ isPublic,
111
+ option('type', objName)
112
+ );
113
+ return { format, type };
114
+ }
115
+
116
+ function parseKeyEncoding(
117
+ enc: {
118
+ key: any;
119
+ encoding?: string;
120
+ format?: string;
121
+ cipher?: string;
122
+ passphrase?: string;
123
+ },
124
+ keyType: string | undefined,
125
+ isPublic: boolean | undefined,
126
+ objName?: string
127
+ ) {
128
+ // validateObject(enc, 'options');
129
+
130
+ const isInput = keyType === undefined;
131
+
132
+ const { format, type } = parseKeyFormatAndType(
133
+ enc,
134
+ keyType,
135
+ isPublic,
136
+ objName
137
+ );
138
+
139
+ let cipher, passphrase, encoding;
140
+ if (isPublic !== true) {
141
+ ({ cipher, passphrase, encoding } = enc);
142
+
143
+ if (!isInput) {
144
+ if (cipher != null) {
145
+ if (typeof cipher !== 'string')
146
+ throw new Error(
147
+ `Invalid argument ${option('cipher', objName)}: ${cipher}`
148
+ );
149
+ if (
150
+ format === KFormatType.kKeyFormatDER &&
151
+ (type === KeyEncoding.kKeyEncodingPKCS1 ||
152
+ type === KeyEncoding.kKeyEncodingSEC1)
153
+ ) {
154
+ throw new Error(
155
+ `Incompatible key options ${encodingNames[type]} does not support encryption`
156
+ );
157
+ }
158
+ } else if (passphrase !== undefined) {
159
+ throw new Error(
160
+ `invalid argument ${option('cipher', objName)}: ${cipher}`
161
+ );
162
+ }
163
+ }
164
+
165
+ if (
166
+ (isInput && passphrase !== undefined && !isStringOrBuffer(passphrase)) ||
167
+ (!isInput && cipher != null && !isStringOrBuffer(passphrase))
168
+ ) {
169
+ throw new Error(
170
+ `Invalid argument value ${option('passphrase', objName)}: ${passphrase}`
171
+ );
172
+ }
173
+ }
174
+
175
+ if (passphrase !== undefined)
176
+ passphrase = binaryLikeToArrayBuffer(passphrase, encoding);
177
+
178
+ return { format, type, cipher, passphrase };
179
+ }
180
+
181
+ function prepareAsymmetricKey(
182
+ key:
183
+ | BinaryLike
184
+ | { key: any; encoding?: string; format?: any; passphrase?: string },
185
+ ctx: KeyInputContext
186
+ ): {
187
+ format: KFormatType;
188
+ data: ArrayBuffer;
189
+ type?: any;
190
+ passphrase?: any;
191
+ } {
192
+ // TODO(osp) check, KeyObject some node object
193
+ // if (isKeyObject(key)) {
194
+ // // Best case: A key object, as simple as that.
195
+ // return { data: getKeyObjectHandle(key, ctx) };
196
+ // } else
197
+ // if (isCryptoKey(key)) {
198
+ // return { data: getKeyObjectHandle(key[kKeyObject], ctx) };
199
+ // } else
200
+ if (isStringOrBuffer(key)) {
201
+ // Expect PEM by default, mostly for backward compatibility.
202
+ return {
203
+ format: KFormatType.kKeyFormatPEM,
204
+ data: binaryLikeToArrayBuffer(key),
205
+ };
206
+ } else if (typeof key === 'object') {
207
+ const {
208
+ key: data,
209
+ encoding,
210
+ // format
211
+ } = key;
212
+ // // The 'key' property can be a KeyObject as well to allow specifying
213
+ // // additional options such as padding along with the key.
214
+ // if (isKeyObject(data)) return { data: getKeyObjectHandle(data, ctx) };
215
+ // else if (isCryptoKey(data))
216
+ // return { data: getKeyObjectHandle(data[kKeyObject], ctx) };
217
+ // else if (isJwk(data) && format === 'jwk')
218
+ // return { data: getKeyObjectHandleFromJwk(data, ctx), format: 'jwk' };
219
+ // Either PEM or DER using PKCS#1 or SPKI.
220
+ if (!isStringOrBuffer(data)) {
221
+ throw new Error(
222
+ 'prepareAsymmetricKey: key is not a string or ArrayBuffer'
223
+ );
224
+ }
225
+
226
+ const isPublic =
227
+ ctx === KeyInputContext.kConsumePrivate ||
228
+ ctx === KeyInputContext.kCreatePrivate
229
+ ? false
230
+ : undefined;
231
+
232
+ return {
233
+ data: binaryLikeToArrayBuffer(data, encoding),
234
+ ...parseKeyEncoding(key, undefined, isPublic),
235
+ };
236
+ }
237
+
238
+ throw new Error('[prepareAsymetricKey] Invalid argument key: ${key}');
239
+ }
240
+
241
+ // TODO(osp) any here is a node KeyObject
242
+ export function preparePrivateKey(
243
+ key:
244
+ | BinaryLike
245
+ | {
246
+ key: any;
247
+ encoding?: string;
248
+ format?: any;
249
+ padding?: number;
250
+ passphrase?: string;
251
+ }
252
+ ) {
253
+ return prepareAsymmetricKey(key, KeyInputContext.kConsumePrivate);
254
+ }
255
+
256
+ // TODO(osp) any here is a node KeyObject
257
+ export function preparePublicOrPrivateKey(
258
+ key:
259
+ | BinaryLike
260
+ | { key: any; encoding?: string; format?: any; padding?: number }
261
+ ) {
262
+ return prepareAsymmetricKey(key, KeyInputContext.kConsumePublic);
263
+ }
264
+
265
+ // Parses the public key encoding based on an object. keyType must be undefined
266
+ // when this is used to parse an input encoding and must be a valid key type if
267
+ // used to parse an output encoding.
268
+ export function parsePublicKeyEncoding(
269
+ enc: {
270
+ key: any;
271
+ encoding?: string;
272
+ format?: string;
273
+ cipher?: string;
274
+ passphrase?: string;
275
+ },
276
+ keyType: string | undefined,
277
+ objName?: string
278
+ ) {
279
+ return parseKeyEncoding(enc, keyType, keyType ? true : undefined, objName);
280
+ }
281
+
282
+ // Parses the private key encoding based on an object. keyType must be undefined
283
+ // when this is used to parse an input encoding and must be a valid key type if
284
+ // used to parse an output encoding.
285
+ export function parsePrivateKeyEncoding(
286
+ enc: {
287
+ key: any;
288
+ encoding?: string;
289
+ format?: string;
290
+ cipher?: string;
291
+ passphrase?: string;
292
+ },
293
+ keyType: string | undefined,
294
+ objName?: string
295
+ ) {
296
+ return parseKeyEncoding(enc, keyType, false, objName);
297
+ }