1 |
|
2 |
|
3 |
|
4 |
|
5 | import * as core from 'webcrypto-core';
|
6 | import { BufferSourceConverter as BufferSourceConverter$1 } from 'webcrypto-core';
|
7 | export { CryptoKey } from 'webcrypto-core';
|
8 | import { Buffer } from 'buffer';
|
9 | import * as crypto from 'crypto';
|
10 | import crypto__default from 'crypto';
|
11 | import * as process from 'process';
|
12 | import { __decorate } from 'tslib';
|
13 | import { JsonProp, JsonPropTypes, JsonSerializer, JsonParser } from '@peculiar/json-schema';
|
14 | import { Convert, BufferSourceConverter } from 'pvtsutils';
|
15 | import { AsnParser, AsnSerializer } from '@peculiar/asn1-schema';
|
16 |
|
17 | const JsonBase64UrlConverter = {
|
18 | fromJSON: (value) => Buffer.from(Convert.FromBase64Url(value)),
|
19 | toJSON: (value) => Convert.ToBase64Url(value),
|
20 | };
|
21 |
|
22 | class CryptoKey extends core.CryptoKey {
|
23 | constructor() {
|
24 | super(...arguments);
|
25 | this.data = Buffer.alloc(0);
|
26 | this.algorithm = { name: "" };
|
27 | this.extractable = false;
|
28 | this.type = "secret";
|
29 | this.usages = [];
|
30 | this.kty = "oct";
|
31 | this.alg = "";
|
32 | }
|
33 | }
|
34 | __decorate([
|
35 | JsonProp({ name: "ext", type: JsonPropTypes.Boolean, optional: true })
|
36 | ], CryptoKey.prototype, "extractable", void 0);
|
37 | __decorate([
|
38 | JsonProp({ name: "key_ops", type: JsonPropTypes.String, repeated: true, optional: true })
|
39 | ], CryptoKey.prototype, "usages", void 0);
|
40 | __decorate([
|
41 | JsonProp({ type: JsonPropTypes.String })
|
42 | ], CryptoKey.prototype, "kty", void 0);
|
43 | __decorate([
|
44 | JsonProp({ type: JsonPropTypes.String, optional: true })
|
45 | ], CryptoKey.prototype, "alg", void 0);
|
46 |
|
47 | class SymmetricKey extends CryptoKey {
|
48 | constructor() {
|
49 | super(...arguments);
|
50 | this.kty = "oct";
|
51 | this.type = "secret";
|
52 | }
|
53 | }
|
54 |
|
55 | class AsymmetricKey extends CryptoKey {
|
56 | }
|
57 |
|
58 | class AesCryptoKey extends SymmetricKey {
|
59 | get alg() {
|
60 | switch (this.algorithm.name.toUpperCase()) {
|
61 | case "AES-CBC":
|
62 | return `A${this.algorithm.length}CBC`;
|
63 | case "AES-CTR":
|
64 | return `A${this.algorithm.length}CTR`;
|
65 | case "AES-GCM":
|
66 | return `A${this.algorithm.length}GCM`;
|
67 | case "AES-KW":
|
68 | return `A${this.algorithm.length}KW`;
|
69 | case "AES-CMAC":
|
70 | return `A${this.algorithm.length}CMAC`;
|
71 | case "AES-ECB":
|
72 | return `A${this.algorithm.length}ECB`;
|
73 | default:
|
74 | throw new core.AlgorithmError("Unsupported algorithm name");
|
75 | }
|
76 | }
|
77 | set alg(value) {
|
78 | }
|
79 | }
|
80 | __decorate([
|
81 | JsonProp({ name: "k", converter: JsonBase64UrlConverter })
|
82 | ], AesCryptoKey.prototype, "data", void 0);
|
83 |
|
84 | class AesCrypto {
|
85 | static async generateKey(algorithm, extractable, keyUsages) {
|
86 | const key = new AesCryptoKey();
|
87 | key.algorithm = algorithm;
|
88 | key.extractable = extractable;
|
89 | key.usages = keyUsages;
|
90 | key.data = crypto__default.randomBytes(algorithm.length >> 3);
|
91 | return key;
|
92 | }
|
93 | static async exportKey(format, key) {
|
94 | if (!(key instanceof AesCryptoKey)) {
|
95 | throw new Error("key: Is not AesCryptoKey");
|
96 | }
|
97 | switch (format.toLowerCase()) {
|
98 | case "jwk":
|
99 | return JsonSerializer.toJSON(key);
|
100 | case "raw":
|
101 | return new Uint8Array(key.data).buffer;
|
102 | default:
|
103 | throw new core.OperationError("format: Must be 'jwk' or 'raw'");
|
104 | }
|
105 | }
|
106 | static async importKey(format, keyData, algorithm, extractable, keyUsages) {
|
107 | let key;
|
108 | switch (format.toLowerCase()) {
|
109 | case "jwk":
|
110 | key = JsonParser.fromJSON(keyData, { targetSchema: AesCryptoKey });
|
111 | break;
|
112 | case "raw":
|
113 | key = new AesCryptoKey();
|
114 | key.data = Buffer.from(keyData);
|
115 | break;
|
116 | default:
|
117 | throw new core.OperationError("format: Must be 'jwk' or 'raw'");
|
118 | }
|
119 | key.algorithm = algorithm;
|
120 | key.algorithm.length = key.data.length << 3;
|
121 | key.extractable = extractable;
|
122 | key.usages = keyUsages;
|
123 | switch (key.algorithm.length) {
|
124 | case 128:
|
125 | case 192:
|
126 | case 256:
|
127 | break;
|
128 | default:
|
129 | throw new core.OperationError("keyData: Is wrong key length");
|
130 | }
|
131 | return key;
|
132 | }
|
133 | static async encrypt(algorithm, key, data) {
|
134 | switch (algorithm.name.toUpperCase()) {
|
135 | case "AES-CBC":
|
136 | return this.encryptAesCBC(algorithm, key, Buffer.from(data));
|
137 | case "AES-CTR":
|
138 | return this.encryptAesCTR(algorithm, key, Buffer.from(data));
|
139 | case "AES-GCM":
|
140 | return this.encryptAesGCM(algorithm, key, Buffer.from(data));
|
141 | case "AES-KW":
|
142 | return this.encryptAesKW(algorithm, key, Buffer.from(data));
|
143 | case "AES-ECB":
|
144 | return this.encryptAesECB(algorithm, key, Buffer.from(data));
|
145 | default:
|
146 | throw new core.OperationError("algorithm: Is not recognized");
|
147 | }
|
148 | }
|
149 | static async decrypt(algorithm, key, data) {
|
150 | if (!(key instanceof AesCryptoKey)) {
|
151 | throw new Error("key: Is not AesCryptoKey");
|
152 | }
|
153 | switch (algorithm.name.toUpperCase()) {
|
154 | case "AES-CBC":
|
155 | return this.decryptAesCBC(algorithm, key, Buffer.from(data));
|
156 | case "AES-CTR":
|
157 | return this.decryptAesCTR(algorithm, key, Buffer.from(data));
|
158 | case "AES-GCM":
|
159 | return this.decryptAesGCM(algorithm, key, Buffer.from(data));
|
160 | case "AES-KW":
|
161 | return this.decryptAesKW(algorithm, key, Buffer.from(data));
|
162 | case "AES-ECB":
|
163 | return this.decryptAesECB(algorithm, key, Buffer.from(data));
|
164 | default:
|
165 | throw new core.OperationError("algorithm: Is not recognized");
|
166 | }
|
167 | }
|
168 | static async encryptAesCBC(algorithm, key, data) {
|
169 | const cipher = crypto__default.createCipheriv(`aes-${key.algorithm.length}-cbc`, key.data, new Uint8Array(algorithm.iv));
|
170 | let enc = cipher.update(data);
|
171 | enc = Buffer.concat([enc, cipher.final()]);
|
172 | const res = new Uint8Array(enc).buffer;
|
173 | return res;
|
174 | }
|
175 | static async decryptAesCBC(algorithm, key, data) {
|
176 | const decipher = crypto__default.createDecipheriv(`aes-${key.algorithm.length}-cbc`, key.data, new Uint8Array(algorithm.iv));
|
177 | let dec = decipher.update(data);
|
178 | dec = Buffer.concat([dec, decipher.final()]);
|
179 | return new Uint8Array(dec).buffer;
|
180 | }
|
181 | static async encryptAesCTR(algorithm, key, data) {
|
182 | const cipher = crypto__default.createCipheriv(`aes-${key.algorithm.length}-ctr`, key.data, Buffer.from(algorithm.counter));
|
183 | let enc = cipher.update(data);
|
184 | enc = Buffer.concat([enc, cipher.final()]);
|
185 | const res = new Uint8Array(enc).buffer;
|
186 | return res;
|
187 | }
|
188 | static async decryptAesCTR(algorithm, key, data) {
|
189 | const decipher = crypto__default.createDecipheriv(`aes-${key.algorithm.length}-ctr`, key.data, new Uint8Array(algorithm.counter));
|
190 | let dec = decipher.update(data);
|
191 | dec = Buffer.concat([dec, decipher.final()]);
|
192 | return new Uint8Array(dec).buffer;
|
193 | }
|
194 | static async encryptAesGCM(algorithm, key, data) {
|
195 | const cipher = crypto__default.createCipheriv(`aes-${key.algorithm.length}-gcm`, key.data, Buffer.from(algorithm.iv), {
|
196 | authTagLength: (algorithm.tagLength || 128) >> 3,
|
197 | });
|
198 | if (algorithm.additionalData) {
|
199 | cipher.setAAD(Buffer.from(algorithm.additionalData));
|
200 | }
|
201 | let enc = cipher.update(data);
|
202 | enc = Buffer.concat([enc, cipher.final(), cipher.getAuthTag()]);
|
203 | const res = new Uint8Array(enc).buffer;
|
204 | return res;
|
205 | }
|
206 | static async decryptAesGCM(algorithm, key, data) {
|
207 | const decipher = crypto__default.createDecipheriv(`aes-${key.algorithm.length}-gcm`, key.data, new Uint8Array(algorithm.iv));
|
208 | const tagLength = (algorithm.tagLength || 128) >> 3;
|
209 | const enc = data.slice(0, data.length - tagLength);
|
210 | const tag = data.slice(data.length - tagLength);
|
211 | if (algorithm.additionalData) {
|
212 | decipher.setAAD(Buffer.from(algorithm.additionalData));
|
213 | }
|
214 | decipher.setAuthTag(tag);
|
215 | let dec = decipher.update(enc);
|
216 | dec = Buffer.concat([dec, decipher.final()]);
|
217 | return new Uint8Array(dec).buffer;
|
218 | }
|
219 | static async encryptAesKW(algorithm, key, data) {
|
220 | const cipher = crypto__default.createCipheriv(`id-aes${key.algorithm.length}-wrap`, key.data, this.AES_KW_IV);
|
221 | let enc = cipher.update(data);
|
222 | enc = Buffer.concat([enc, cipher.final()]);
|
223 | return new Uint8Array(enc).buffer;
|
224 | }
|
225 | static async decryptAesKW(algorithm, key, data) {
|
226 | const decipher = crypto__default.createDecipheriv(`id-aes${key.algorithm.length}-wrap`, key.data, this.AES_KW_IV);
|
227 | let dec = decipher.update(data);
|
228 | dec = Buffer.concat([dec, decipher.final()]);
|
229 | return new Uint8Array(dec).buffer;
|
230 | }
|
231 | static async encryptAesECB(algorithm, key, data) {
|
232 | const cipher = crypto__default.createCipheriv(`aes-${key.algorithm.length}-ecb`, key.data, new Uint8Array(0));
|
233 | let enc = cipher.update(data);
|
234 | enc = Buffer.concat([enc, cipher.final()]);
|
235 | const res = new Uint8Array(enc).buffer;
|
236 | return res;
|
237 | }
|
238 | static async decryptAesECB(algorithm, key, data) {
|
239 | const decipher = crypto__default.createDecipheriv(`aes-${key.algorithm.length}-ecb`, key.data, new Uint8Array(0));
|
240 | let dec = decipher.update(data);
|
241 | dec = Buffer.concat([dec, decipher.final()]);
|
242 | return new Uint8Array(dec).buffer;
|
243 | }
|
244 | }
|
245 | AesCrypto.AES_KW_IV = Buffer.from("A6A6A6A6A6A6A6A6", "hex");
|
246 |
|
247 | const keyStorage = new WeakMap();
|
248 | function getCryptoKey(key) {
|
249 | const res = keyStorage.get(key);
|
250 | if (!res) {
|
251 | throw new core.OperationError("Cannot get CryptoKey from secure storage");
|
252 | }
|
253 | return res;
|
254 | }
|
255 | function setCryptoKey(value) {
|
256 | const key = core.CryptoKey.create(value.algorithm, value.type, value.extractable, value.usages);
|
257 | Object.freeze(key);
|
258 | keyStorage.set(key, value);
|
259 | return key;
|
260 | }
|
261 |
|
262 | class AesCbcProvider extends core.AesCbcProvider {
|
263 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
264 | const key = await AesCrypto.generateKey({
|
265 | name: this.name,
|
266 | length: algorithm.length,
|
267 | }, extractable, keyUsages);
|
268 | return setCryptoKey(key);
|
269 | }
|
270 | async onEncrypt(algorithm, key, data) {
|
271 | return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
272 | }
|
273 | async onDecrypt(algorithm, key, data) {
|
274 | return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
275 | }
|
276 | async onExportKey(format, key) {
|
277 | return AesCrypto.exportKey(format, getCryptoKey(key));
|
278 | }
|
279 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
280 | const key = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
|
281 | return setCryptoKey(key);
|
282 | }
|
283 | checkCryptoKey(key, keyUsage) {
|
284 | super.checkCryptoKey(key, keyUsage);
|
285 | if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
|
286 | throw new TypeError("key: Is not a AesCryptoKey");
|
287 | }
|
288 | }
|
289 | }
|
290 |
|
291 | const zero = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
292 | const rb = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135]);
|
293 | const blockSize = 16;
|
294 | function bitShiftLeft(buffer) {
|
295 | const shifted = Buffer.alloc(buffer.length);
|
296 | const last = buffer.length - 1;
|
297 | for (let index = 0; index < last; index++) {
|
298 | shifted[index] = buffer[index] << 1;
|
299 | if (buffer[index + 1] & 0x80) {
|
300 | shifted[index] += 0x01;
|
301 | }
|
302 | }
|
303 | shifted[last] = buffer[last] << 1;
|
304 | return shifted;
|
305 | }
|
306 | function xor(a, b) {
|
307 | const length = Math.min(a.length, b.length);
|
308 | const output = Buffer.alloc(length);
|
309 | for (let index = 0; index < length; index++) {
|
310 | output[index] = a[index] ^ b[index];
|
311 | }
|
312 | return output;
|
313 | }
|
314 | function aes(key, message) {
|
315 | const cipher = crypto.createCipheriv(`aes${key.length << 3}`, key, zero);
|
316 | const result = cipher.update(message);
|
317 | cipher.final();
|
318 | return result;
|
319 | }
|
320 | function getMessageBlock(message, blockIndex) {
|
321 | const block = Buffer.alloc(blockSize);
|
322 | const start = blockIndex * blockSize;
|
323 | const end = start + blockSize;
|
324 | message.copy(block, 0, start, end);
|
325 | return block;
|
326 | }
|
327 | function getPaddedMessageBlock(message, blockIndex) {
|
328 | const block = Buffer.alloc(blockSize);
|
329 | const start = blockIndex * blockSize;
|
330 | const end = message.length;
|
331 | block.fill(0);
|
332 | message.copy(block, 0, start, end);
|
333 | block[end - start] = 0x80;
|
334 | return block;
|
335 | }
|
336 | function generateSubkeys(key) {
|
337 | const l = aes(key, zero);
|
338 | let subkey1 = bitShiftLeft(l);
|
339 | if (l[0] & 0x80) {
|
340 | subkey1 = xor(subkey1, rb);
|
341 | }
|
342 | let subkey2 = bitShiftLeft(subkey1);
|
343 | if (subkey1[0] & 0x80) {
|
344 | subkey2 = xor(subkey2, rb);
|
345 | }
|
346 | return { subkey1, subkey2 };
|
347 | }
|
348 | function aesCmac(key, message) {
|
349 | const subkeys = generateSubkeys(key);
|
350 | let blockCount = Math.ceil(message.length / blockSize);
|
351 | let lastBlockCompleteFlag;
|
352 | let lastBlock;
|
353 | if (blockCount === 0) {
|
354 | blockCount = 1;
|
355 | lastBlockCompleteFlag = false;
|
356 | }
|
357 | else {
|
358 | lastBlockCompleteFlag = (message.length % blockSize === 0);
|
359 | }
|
360 | const lastBlockIndex = blockCount - 1;
|
361 | if (lastBlockCompleteFlag) {
|
362 | lastBlock = xor(getMessageBlock(message, lastBlockIndex), subkeys.subkey1);
|
363 | }
|
364 | else {
|
365 | lastBlock = xor(getPaddedMessageBlock(message, lastBlockIndex), subkeys.subkey2);
|
366 | }
|
367 | let x = zero;
|
368 | let y;
|
369 | for (let index = 0; index < lastBlockIndex; index++) {
|
370 | y = xor(x, getMessageBlock(message, index));
|
371 | x = aes(key, y);
|
372 | }
|
373 | y = xor(lastBlock, x);
|
374 | return aes(key, y);
|
375 | }
|
376 | class AesCmacProvider extends core.AesCmacProvider {
|
377 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
378 | const key = await AesCrypto.generateKey({
|
379 | name: this.name,
|
380 | length: algorithm.length,
|
381 | }, extractable, keyUsages);
|
382 | return setCryptoKey(key);
|
383 | }
|
384 | async onSign(algorithm, key, data) {
|
385 | const result = aesCmac(getCryptoKey(key).data, Buffer.from(data));
|
386 | return new Uint8Array(result).buffer;
|
387 | }
|
388 | async onVerify(algorithm, key, signature, data) {
|
389 | const signature2 = await this.sign(algorithm, key, data);
|
390 | return Buffer.from(signature).compare(Buffer.from(signature2)) === 0;
|
391 | }
|
392 | async onExportKey(format, key) {
|
393 | return AesCrypto.exportKey(format, getCryptoKey(key));
|
394 | }
|
395 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
396 | const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
|
397 | return setCryptoKey(res);
|
398 | }
|
399 | checkCryptoKey(key, keyUsage) {
|
400 | super.checkCryptoKey(key, keyUsage);
|
401 | if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
|
402 | throw new TypeError("key: Is not a AesCryptoKey");
|
403 | }
|
404 | }
|
405 | }
|
406 |
|
407 | class AesCtrProvider extends core.AesCtrProvider {
|
408 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
409 | const key = await AesCrypto.generateKey({
|
410 | name: this.name,
|
411 | length: algorithm.length,
|
412 | }, extractable, keyUsages);
|
413 | return setCryptoKey(key);
|
414 | }
|
415 | async onEncrypt(algorithm, key, data) {
|
416 | return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
417 | }
|
418 | async onDecrypt(algorithm, key, data) {
|
419 | return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
420 | }
|
421 | async onExportKey(format, key) {
|
422 | return AesCrypto.exportKey(format, getCryptoKey(key));
|
423 | }
|
424 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
425 | const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
|
426 | return setCryptoKey(res);
|
427 | }
|
428 | checkCryptoKey(key, keyUsage) {
|
429 | super.checkCryptoKey(key, keyUsage);
|
430 | if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
|
431 | throw new TypeError("key: Is not a AesCryptoKey");
|
432 | }
|
433 | }
|
434 | }
|
435 |
|
436 | class AesGcmProvider extends core.AesGcmProvider {
|
437 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
438 | const key = await AesCrypto.generateKey({
|
439 | name: this.name,
|
440 | length: algorithm.length,
|
441 | }, extractable, keyUsages);
|
442 | return setCryptoKey(key);
|
443 | }
|
444 | async onEncrypt(algorithm, key, data) {
|
445 | return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
446 | }
|
447 | async onDecrypt(algorithm, key, data) {
|
448 | return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
449 | }
|
450 | async onExportKey(format, key) {
|
451 | return AesCrypto.exportKey(format, getCryptoKey(key));
|
452 | }
|
453 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
454 | const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
|
455 | return setCryptoKey(res);
|
456 | }
|
457 | checkCryptoKey(key, keyUsage) {
|
458 | super.checkCryptoKey(key, keyUsage);
|
459 | if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
|
460 | throw new TypeError("key: Is not a AesCryptoKey");
|
461 | }
|
462 | }
|
463 | }
|
464 |
|
465 | class AesKwProvider extends core.AesKwProvider {
|
466 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
467 | const res = await AesCrypto.generateKey({
|
468 | name: this.name,
|
469 | length: algorithm.length,
|
470 | }, extractable, keyUsages);
|
471 | return setCryptoKey(res);
|
472 | }
|
473 | async onExportKey(format, key) {
|
474 | return AesCrypto.exportKey(format, getCryptoKey(key));
|
475 | }
|
476 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
477 | const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
|
478 | return setCryptoKey(res);
|
479 | }
|
480 | async onEncrypt(algorithm, key, data) {
|
481 | return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
482 | }
|
483 | async onDecrypt(algorithm, key, data) {
|
484 | return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
485 | }
|
486 | checkCryptoKey(key, keyUsage) {
|
487 | super.checkCryptoKey(key, keyUsage);
|
488 | if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
|
489 | throw new TypeError("key: Is not a AesCryptoKey");
|
490 | }
|
491 | }
|
492 | }
|
493 |
|
494 | class AesEcbProvider extends core.AesEcbProvider {
|
495 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
496 | const key = await AesCrypto.generateKey({
|
497 | name: this.name,
|
498 | length: algorithm.length,
|
499 | }, extractable, keyUsages);
|
500 | return setCryptoKey(key);
|
501 | }
|
502 | async onEncrypt(algorithm, key, data) {
|
503 | return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
504 | }
|
505 | async onDecrypt(algorithm, key, data) {
|
506 | return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
507 | }
|
508 | async onExportKey(format, key) {
|
509 | return AesCrypto.exportKey(format, getCryptoKey(key));
|
510 | }
|
511 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
512 | const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
|
513 | return setCryptoKey(res);
|
514 | }
|
515 | checkCryptoKey(key, keyUsage) {
|
516 | super.checkCryptoKey(key, keyUsage);
|
517 | if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
|
518 | throw new TypeError("key: Is not a AesCryptoKey");
|
519 | }
|
520 | }
|
521 | }
|
522 |
|
523 | class DesCryptoKey extends SymmetricKey {
|
524 | get alg() {
|
525 | switch (this.algorithm.name.toUpperCase()) {
|
526 | case "DES-CBC":
|
527 | return `DES-CBC`;
|
528 | case "DES-EDE3-CBC":
|
529 | return `3DES-CBC`;
|
530 | default:
|
531 | throw new core.AlgorithmError("Unsupported algorithm name");
|
532 | }
|
533 | }
|
534 | set alg(value) {
|
535 | }
|
536 | }
|
537 | __decorate([
|
538 | JsonProp({ name: "k", converter: JsonBase64UrlConverter })
|
539 | ], DesCryptoKey.prototype, "data", void 0);
|
540 |
|
541 | class DesCrypto {
|
542 | static async generateKey(algorithm, extractable, keyUsages) {
|
543 | const key = new DesCryptoKey();
|
544 | key.algorithm = algorithm;
|
545 | key.extractable = extractable;
|
546 | key.usages = keyUsages;
|
547 | key.data = crypto__default.randomBytes(algorithm.length >> 3);
|
548 | return key;
|
549 | }
|
550 | static async exportKey(format, key) {
|
551 | switch (format.toLowerCase()) {
|
552 | case "jwk":
|
553 | return JsonSerializer.toJSON(key);
|
554 | case "raw":
|
555 | return new Uint8Array(key.data).buffer;
|
556 | default:
|
557 | throw new core.OperationError("format: Must be 'jwk' or 'raw'");
|
558 | }
|
559 | }
|
560 | static async importKey(format, keyData, algorithm, extractable, keyUsages) {
|
561 | let key;
|
562 | switch (format.toLowerCase()) {
|
563 | case "jwk":
|
564 | key = JsonParser.fromJSON(keyData, { targetSchema: DesCryptoKey });
|
565 | break;
|
566 | case "raw":
|
567 | key = new DesCryptoKey();
|
568 | key.data = Buffer.from(keyData);
|
569 | break;
|
570 | default:
|
571 | throw new core.OperationError("format: Must be 'jwk' or 'raw'");
|
572 | }
|
573 | key.algorithm = algorithm;
|
574 | key.extractable = extractable;
|
575 | key.usages = keyUsages;
|
576 | return key;
|
577 | }
|
578 | static async encrypt(algorithm, key, data) {
|
579 | switch (algorithm.name.toUpperCase()) {
|
580 | case "DES-CBC":
|
581 | return this.encryptDesCBC(algorithm, key, Buffer.from(data));
|
582 | case "DES-EDE3-CBC":
|
583 | return this.encryptDesEDE3CBC(algorithm, key, Buffer.from(data));
|
584 | default:
|
585 | throw new core.OperationError("algorithm: Is not recognized");
|
586 | }
|
587 | }
|
588 | static async decrypt(algorithm, key, data) {
|
589 | if (!(key instanceof DesCryptoKey)) {
|
590 | throw new Error("key: Is not DesCryptoKey");
|
591 | }
|
592 | switch (algorithm.name.toUpperCase()) {
|
593 | case "DES-CBC":
|
594 | return this.decryptDesCBC(algorithm, key, Buffer.from(data));
|
595 | case "DES-EDE3-CBC":
|
596 | return this.decryptDesEDE3CBC(algorithm, key, Buffer.from(data));
|
597 | default:
|
598 | throw new core.OperationError("algorithm: Is not recognized");
|
599 | }
|
600 | }
|
601 | static async encryptDesCBC(algorithm, key, data) {
|
602 | const cipher = crypto__default.createCipheriv(`des-cbc`, key.data, new Uint8Array(algorithm.iv));
|
603 | let enc = cipher.update(data);
|
604 | enc = Buffer.concat([enc, cipher.final()]);
|
605 | const res = new Uint8Array(enc).buffer;
|
606 | return res;
|
607 | }
|
608 | static async decryptDesCBC(algorithm, key, data) {
|
609 | const decipher = crypto__default.createDecipheriv(`des-cbc`, key.data, new Uint8Array(algorithm.iv));
|
610 | let dec = decipher.update(data);
|
611 | dec = Buffer.concat([dec, decipher.final()]);
|
612 | return new Uint8Array(dec).buffer;
|
613 | }
|
614 | static async encryptDesEDE3CBC(algorithm, key, data) {
|
615 | const cipher = crypto__default.createCipheriv(`des-ede3-cbc`, key.data, Buffer.from(algorithm.iv));
|
616 | let enc = cipher.update(data);
|
617 | enc = Buffer.concat([enc, cipher.final()]);
|
618 | const res = new Uint8Array(enc).buffer;
|
619 | return res;
|
620 | }
|
621 | static async decryptDesEDE3CBC(algorithm, key, data) {
|
622 | const decipher = crypto__default.createDecipheriv(`des-ede3-cbc`, key.data, new Uint8Array(algorithm.iv));
|
623 | let dec = decipher.update(data);
|
624 | dec = Buffer.concat([dec, decipher.final()]);
|
625 | return new Uint8Array(dec).buffer;
|
626 | }
|
627 | }
|
628 |
|
629 | class DesCbcProvider extends core.DesProvider {
|
630 | constructor() {
|
631 | super(...arguments);
|
632 | this.keySizeBits = 64;
|
633 | this.ivSize = 8;
|
634 | this.name = "DES-CBC";
|
635 | }
|
636 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
637 | const key = await DesCrypto.generateKey({
|
638 | name: this.name,
|
639 | length: this.keySizeBits,
|
640 | }, extractable, keyUsages);
|
641 | return setCryptoKey(key);
|
642 | }
|
643 | async onEncrypt(algorithm, key, data) {
|
644 | return DesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
645 | }
|
646 | async onDecrypt(algorithm, key, data) {
|
647 | return DesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
648 | }
|
649 | async onExportKey(format, key) {
|
650 | return DesCrypto.exportKey(format, getCryptoKey(key));
|
651 | }
|
652 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
653 | const key = await DesCrypto.importKey(format, keyData, { name: this.name, length: this.keySizeBits }, extractable, keyUsages);
|
654 | if (key.data.length !== (this.keySizeBits >> 3)) {
|
655 | throw new core.OperationError("keyData: Wrong key size");
|
656 | }
|
657 | return setCryptoKey(key);
|
658 | }
|
659 | checkCryptoKey(key, keyUsage) {
|
660 | super.checkCryptoKey(key, keyUsage);
|
661 | if (!(getCryptoKey(key) instanceof DesCryptoKey)) {
|
662 | throw new TypeError("key: Is not a DesCryptoKey");
|
663 | }
|
664 | }
|
665 | }
|
666 |
|
667 | class DesEde3CbcProvider extends core.DesProvider {
|
668 | constructor() {
|
669 | super(...arguments);
|
670 | this.keySizeBits = 192;
|
671 | this.ivSize = 8;
|
672 | this.name = "DES-EDE3-CBC";
|
673 | }
|
674 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
675 | const key = await DesCrypto.generateKey({
|
676 | name: this.name,
|
677 | length: this.keySizeBits,
|
678 | }, extractable, keyUsages);
|
679 | return setCryptoKey(key);
|
680 | }
|
681 | async onEncrypt(algorithm, key, data) {
|
682 | return DesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
683 | }
|
684 | async onDecrypt(algorithm, key, data) {
|
685 | return DesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data));
|
686 | }
|
687 | async onExportKey(format, key) {
|
688 | return DesCrypto.exportKey(format, getCryptoKey(key));
|
689 | }
|
690 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
691 | const key = await DesCrypto.importKey(format, keyData, { name: this.name, length: this.keySizeBits }, extractable, keyUsages);
|
692 | if (key.data.length !== (this.keySizeBits >> 3)) {
|
693 | throw new core.OperationError("keyData: Wrong key size");
|
694 | }
|
695 | return setCryptoKey(key);
|
696 | }
|
697 | checkCryptoKey(key, keyUsage) {
|
698 | super.checkCryptoKey(key, keyUsage);
|
699 | if (!(getCryptoKey(key) instanceof DesCryptoKey)) {
|
700 | throw new TypeError("key: Is not a DesCryptoKey");
|
701 | }
|
702 | }
|
703 | }
|
704 |
|
705 | function getJwkAlgorithm(algorithm) {
|
706 | switch (algorithm.name.toUpperCase()) {
|
707 | case "RSA-OAEP": {
|
708 | const mdSize = /(\d+)$/.exec(algorithm.hash.name)[1];
|
709 | return `RSA-OAEP${mdSize !== "1" ? `-${mdSize}` : ""}`;
|
710 | }
|
711 | case "RSASSA-PKCS1-V1_5":
|
712 | return `RS${/(\d+)$/.exec(algorithm.hash.name)[1]}`;
|
713 | case "RSA-PSS":
|
714 | return `PS${/(\d+)$/.exec(algorithm.hash.name)[1]}`;
|
715 | case "RSA-PKCS1":
|
716 | return `RS1`;
|
717 | default:
|
718 | throw new core.OperationError("algorithm: Is not recognized");
|
719 | }
|
720 | }
|
721 |
|
722 | class RsaPrivateKey extends AsymmetricKey {
|
723 | constructor() {
|
724 | super(...arguments);
|
725 | this.type = "private";
|
726 | }
|
727 | getKey() {
|
728 | const keyInfo = AsnParser.parse(this.data, core.asn1.PrivateKeyInfo);
|
729 | return AsnParser.parse(keyInfo.privateKey, core.asn1.RsaPrivateKey);
|
730 | }
|
731 | toJSON() {
|
732 | const key = this.getKey();
|
733 | const json = {
|
734 | kty: "RSA",
|
735 | alg: getJwkAlgorithm(this.algorithm),
|
736 | key_ops: this.usages,
|
737 | ext: this.extractable,
|
738 | };
|
739 | return Object.assign(json, JsonSerializer.toJSON(key));
|
740 | }
|
741 | fromJSON(json) {
|
742 | const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.RsaPrivateKey });
|
743 | const keyInfo = new core.asn1.PrivateKeyInfo();
|
744 | keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1";
|
745 | keyInfo.privateKeyAlgorithm.parameters = null;
|
746 | keyInfo.privateKey = AsnSerializer.serialize(key);
|
747 | this.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
748 | }
|
749 | }
|
750 |
|
751 | class RsaPublicKey extends AsymmetricKey {
|
752 | constructor() {
|
753 | super(...arguments);
|
754 | this.type = "public";
|
755 | }
|
756 | getKey() {
|
757 | const keyInfo = AsnParser.parse(this.data, core.asn1.PublicKeyInfo);
|
758 | return AsnParser.parse(keyInfo.publicKey, core.asn1.RsaPublicKey);
|
759 | }
|
760 | toJSON() {
|
761 | const key = this.getKey();
|
762 | const json = {
|
763 | kty: "RSA",
|
764 | alg: getJwkAlgorithm(this.algorithm),
|
765 | key_ops: this.usages,
|
766 | ext: this.extractable,
|
767 | };
|
768 | return Object.assign(json, JsonSerializer.toJSON(key));
|
769 | }
|
770 | fromJSON(json) {
|
771 | const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.RsaPublicKey });
|
772 | const keyInfo = new core.asn1.PublicKeyInfo();
|
773 | keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1";
|
774 | keyInfo.publicKeyAlgorithm.parameters = null;
|
775 | keyInfo.publicKey = AsnSerializer.serialize(key);
|
776 | this.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
777 | }
|
778 | }
|
779 |
|
780 | class RsaCrypto {
|
781 | static async generateKey(algorithm, extractable, keyUsages) {
|
782 | const privateKey = new RsaPrivateKey();
|
783 | privateKey.algorithm = algorithm;
|
784 | privateKey.extractable = extractable;
|
785 | privateKey.usages = keyUsages.filter((usage) => this.privateKeyUsages.indexOf(usage) !== -1);
|
786 | const publicKey = new RsaPublicKey();
|
787 | publicKey.algorithm = algorithm;
|
788 | publicKey.extractable = true;
|
789 | publicKey.usages = keyUsages.filter((usage) => this.publicKeyUsages.indexOf(usage) !== -1);
|
790 | const publicExponent = Buffer.concat([
|
791 | Buffer.alloc(4 - algorithm.publicExponent.byteLength, 0),
|
792 | Buffer.from(algorithm.publicExponent),
|
793 | ]).readInt32BE(0);
|
794 | const keys = crypto__default.generateKeyPairSync("rsa", {
|
795 | modulusLength: algorithm.modulusLength,
|
796 | publicExponent,
|
797 | publicKeyEncoding: {
|
798 | format: "der",
|
799 | type: "spki",
|
800 | },
|
801 | privateKeyEncoding: {
|
802 | format: "der",
|
803 | type: "pkcs8",
|
804 | },
|
805 | });
|
806 | privateKey.data = keys.privateKey;
|
807 | publicKey.data = keys.publicKey;
|
808 | const res = {
|
809 | privateKey,
|
810 | publicKey,
|
811 | };
|
812 | return res;
|
813 | }
|
814 | static async exportKey(format, key) {
|
815 | switch (format.toLowerCase()) {
|
816 | case "jwk":
|
817 | return JsonSerializer.toJSON(key);
|
818 | case "pkcs8":
|
819 | case "spki":
|
820 | return new Uint8Array(key.data).buffer;
|
821 | default:
|
822 | throw new core.OperationError("format: Must be 'jwk', 'pkcs8' or 'spki'");
|
823 | }
|
824 | }
|
825 | static async importKey(format, keyData, algorithm, extractable, keyUsages) {
|
826 | switch (format.toLowerCase()) {
|
827 | case "jwk": {
|
828 | const jwk = keyData;
|
829 | if (jwk.d) {
|
830 | const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.RsaPrivateKey });
|
831 | return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages);
|
832 | }
|
833 | else {
|
834 | const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.RsaPublicKey });
|
835 | return this.importPublicKey(asnKey, algorithm, extractable, keyUsages);
|
836 | }
|
837 | }
|
838 | case "spki": {
|
839 | const keyInfo = AsnParser.parse(new Uint8Array(keyData), core.asn1.PublicKeyInfo);
|
840 | const asnKey = AsnParser.parse(keyInfo.publicKey, core.asn1.RsaPublicKey);
|
841 | return this.importPublicKey(asnKey, algorithm, extractable, keyUsages);
|
842 | }
|
843 | case "pkcs8": {
|
844 | const keyInfo = AsnParser.parse(new Uint8Array(keyData), core.asn1.PrivateKeyInfo);
|
845 | const asnKey = AsnParser.parse(keyInfo.privateKey, core.asn1.RsaPrivateKey);
|
846 | return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages);
|
847 | }
|
848 | default:
|
849 | throw new core.OperationError("format: Must be 'jwk', 'pkcs8' or 'spki'");
|
850 | }
|
851 | }
|
852 | static async sign(algorithm, key, data) {
|
853 | switch (algorithm.name.toUpperCase()) {
|
854 | case "RSA-PSS":
|
855 | case "RSASSA-PKCS1-V1_5":
|
856 | return this.signRsa(algorithm, key, data);
|
857 | default:
|
858 | throw new core.OperationError("algorithm: Is not recognized");
|
859 | }
|
860 | }
|
861 | static async verify(algorithm, key, signature, data) {
|
862 | switch (algorithm.name.toUpperCase()) {
|
863 | case "RSA-PSS":
|
864 | case "RSASSA-PKCS1-V1_5":
|
865 | return this.verifySSA(algorithm, key, data, signature);
|
866 | default:
|
867 | throw new core.OperationError("algorithm: Is not recognized");
|
868 | }
|
869 | }
|
870 | static async encrypt(algorithm, key, data) {
|
871 | switch (algorithm.name.toUpperCase()) {
|
872 | case "RSA-OAEP":
|
873 | return this.encryptOAEP(algorithm, key, data);
|
874 | default:
|
875 | throw new core.OperationError("algorithm: Is not recognized");
|
876 | }
|
877 | }
|
878 | static async decrypt(algorithm, key, data) {
|
879 | switch (algorithm.name.toUpperCase()) {
|
880 | case "RSA-OAEP":
|
881 | return this.decryptOAEP(algorithm, key, data);
|
882 | default:
|
883 | throw new core.OperationError("algorithm: Is not recognized");
|
884 | }
|
885 | }
|
886 | static importPrivateKey(asnKey, algorithm, extractable, keyUsages) {
|
887 | const keyInfo = new core.asn1.PrivateKeyInfo();
|
888 | keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1";
|
889 | keyInfo.privateKeyAlgorithm.parameters = null;
|
890 | keyInfo.privateKey = AsnSerializer.serialize(asnKey);
|
891 | const key = new RsaPrivateKey();
|
892 | key.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
893 | key.algorithm = Object.assign({}, algorithm);
|
894 | key.algorithm.publicExponent = new Uint8Array(asnKey.publicExponent);
|
895 | key.algorithm.modulusLength = asnKey.modulus.byteLength << 3;
|
896 | key.extractable = extractable;
|
897 | key.usages = keyUsages;
|
898 | return key;
|
899 | }
|
900 | static importPublicKey(asnKey, algorithm, extractable, keyUsages) {
|
901 | const keyInfo = new core.asn1.PublicKeyInfo();
|
902 | keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1";
|
903 | keyInfo.publicKeyAlgorithm.parameters = null;
|
904 | keyInfo.publicKey = AsnSerializer.serialize(asnKey);
|
905 | const key = new RsaPublicKey();
|
906 | key.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
907 | key.algorithm = Object.assign({}, algorithm);
|
908 | key.algorithm.publicExponent = new Uint8Array(asnKey.publicExponent);
|
909 | key.algorithm.modulusLength = asnKey.modulus.byteLength << 3;
|
910 | key.extractable = extractable;
|
911 | key.usages = keyUsages;
|
912 | return key;
|
913 | }
|
914 | static getCryptoAlgorithm(alg) {
|
915 | switch (alg.hash.name.toUpperCase()) {
|
916 | case "SHA-1":
|
917 | return "RSA-SHA1";
|
918 | case "SHA-256":
|
919 | return "RSA-SHA256";
|
920 | case "SHA-384":
|
921 | return "RSA-SHA384";
|
922 | case "SHA-512":
|
923 | return "RSA-SHA512";
|
924 | case "SHA3-256":
|
925 | return "RSA-SHA3-256";
|
926 | case "SHA3-384":
|
927 | return "RSA-SHA3-384";
|
928 | case "SHA3-512":
|
929 | return "RSA-SHA3-512";
|
930 | default:
|
931 | throw new core.OperationError("algorithm.hash: Is not recognized");
|
932 | }
|
933 | }
|
934 | static signRsa(algorithm, key, data) {
|
935 | const cryptoAlg = this.getCryptoAlgorithm(key.algorithm);
|
936 | const signer = crypto__default.createSign(cryptoAlg);
|
937 | signer.update(Buffer.from(data));
|
938 | if (!key.pem) {
|
939 | key.pem = `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`;
|
940 | }
|
941 | const options = {
|
942 | key: key.pem,
|
943 | };
|
944 | if (algorithm.name.toUpperCase() === "RSA-PSS") {
|
945 | options.padding = crypto__default.constants.RSA_PKCS1_PSS_PADDING;
|
946 | options.saltLength = algorithm.saltLength;
|
947 | }
|
948 | const signature = signer.sign(options);
|
949 | return new Uint8Array(signature).buffer;
|
950 | }
|
951 | static verifySSA(algorithm, key, data, signature) {
|
952 | const cryptoAlg = this.getCryptoAlgorithm(key.algorithm);
|
953 | const signer = crypto__default.createVerify(cryptoAlg);
|
954 | signer.update(Buffer.from(data));
|
955 | if (!key.pem) {
|
956 | key.pem = `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`;
|
957 | }
|
958 | const options = {
|
959 | key: key.pem,
|
960 | };
|
961 | if (algorithm.name.toUpperCase() === "RSA-PSS") {
|
962 | options.padding = crypto__default.constants.RSA_PKCS1_PSS_PADDING;
|
963 | options.saltLength = algorithm.saltLength;
|
964 | }
|
965 | const ok = signer.verify(options, signature);
|
966 | return ok;
|
967 | }
|
968 | static encryptOAEP(algorithm, key, data) {
|
969 | const options = {
|
970 | key: `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`,
|
971 | padding: crypto__default.constants.RSA_PKCS1_OAEP_PADDING,
|
972 | };
|
973 | if (algorithm.label) ;
|
974 | return new Uint8Array(crypto__default.publicEncrypt(options, data)).buffer;
|
975 | }
|
976 | static decryptOAEP(algorithm, key, data) {
|
977 | const options = {
|
978 | key: `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`,
|
979 | padding: crypto__default.constants.RSA_PKCS1_OAEP_PADDING,
|
980 | };
|
981 | if (algorithm.label) ;
|
982 | return new Uint8Array(crypto__default.privateDecrypt(options, data)).buffer;
|
983 | }
|
984 | }
|
985 | RsaCrypto.publicKeyUsages = ["verify", "encrypt", "wrapKey"];
|
986 | RsaCrypto.privateKeyUsages = ["sign", "decrypt", "unwrapKey"];
|
987 |
|
988 | class RsaSsaProvider extends core.RsaSsaProvider {
|
989 | constructor() {
|
990 | super(...arguments);
|
991 | this.hashAlgorithms = [
|
992 | "SHA-1", "SHA-256", "SHA-384", "SHA-512",
|
993 | "shake128", "shake256",
|
994 | "SHA3-256", "SHA3-384", "SHA3-512"
|
995 | ];
|
996 | }
|
997 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
998 | const keys = await RsaCrypto.generateKey({
|
999 | ...algorithm,
|
1000 | name: this.name,
|
1001 | }, extractable, keyUsages);
|
1002 | return {
|
1003 | privateKey: setCryptoKey(keys.privateKey),
|
1004 | publicKey: setCryptoKey(keys.publicKey),
|
1005 | };
|
1006 | }
|
1007 | async onSign(algorithm, key, data) {
|
1008 | return RsaCrypto.sign(algorithm, getCryptoKey(key), new Uint8Array(data));
|
1009 | }
|
1010 | async onVerify(algorithm, key, signature, data) {
|
1011 | return RsaCrypto.verify(algorithm, getCryptoKey(key), new Uint8Array(signature), new Uint8Array(data));
|
1012 | }
|
1013 | async onExportKey(format, key) {
|
1014 | return RsaCrypto.exportKey(format, getCryptoKey(key));
|
1015 | }
|
1016 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
1017 | const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
|
1018 | return setCryptoKey(key);
|
1019 | }
|
1020 | checkCryptoKey(key, keyUsage) {
|
1021 | super.checkCryptoKey(key, keyUsage);
|
1022 | const internalKey = getCryptoKey(key);
|
1023 | if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) {
|
1024 | throw new TypeError("key: Is not RSA CryptoKey");
|
1025 | }
|
1026 | }
|
1027 | }
|
1028 |
|
1029 | class RsaPssProvider extends core.RsaPssProvider {
|
1030 | constructor() {
|
1031 | super(...arguments);
|
1032 | this.hashAlgorithms = [
|
1033 | "SHA-1", "SHA-256", "SHA-384", "SHA-512",
|
1034 | "shake128", "shake256",
|
1035 | "SHA3-256", "SHA3-384", "SHA3-512"
|
1036 | ];
|
1037 | }
|
1038 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
1039 | const keys = await RsaCrypto.generateKey({
|
1040 | ...algorithm,
|
1041 | name: this.name,
|
1042 | }, extractable, keyUsages);
|
1043 | return {
|
1044 | privateKey: setCryptoKey(keys.privateKey),
|
1045 | publicKey: setCryptoKey(keys.publicKey),
|
1046 | };
|
1047 | }
|
1048 | async onSign(algorithm, key, data) {
|
1049 | return RsaCrypto.sign(algorithm, getCryptoKey(key), new Uint8Array(data));
|
1050 | }
|
1051 | async onVerify(algorithm, key, signature, data) {
|
1052 | return RsaCrypto.verify(algorithm, getCryptoKey(key), new Uint8Array(signature), new Uint8Array(data));
|
1053 | }
|
1054 | async onExportKey(format, key) {
|
1055 | return RsaCrypto.exportKey(format, getCryptoKey(key));
|
1056 | }
|
1057 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
1058 | const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
|
1059 | return setCryptoKey(key);
|
1060 | }
|
1061 | checkCryptoKey(key, keyUsage) {
|
1062 | super.checkCryptoKey(key, keyUsage);
|
1063 | const internalKey = getCryptoKey(key);
|
1064 | if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) {
|
1065 | throw new TypeError("key: Is not RSA CryptoKey");
|
1066 | }
|
1067 | }
|
1068 | }
|
1069 |
|
1070 | class ShaCrypto {
|
1071 | static size(algorithm) {
|
1072 | switch (algorithm.name.toUpperCase()) {
|
1073 | case "SHA-1":
|
1074 | return 160;
|
1075 | case "SHA-256":
|
1076 | case "SHA3-256":
|
1077 | return 256;
|
1078 | case "SHA-384":
|
1079 | case "SHA3-384":
|
1080 | return 384;
|
1081 | case "SHA-512":
|
1082 | case "SHA3-512":
|
1083 | return 512;
|
1084 | default:
|
1085 | throw new Error("Unrecognized name");
|
1086 | }
|
1087 | }
|
1088 | static getAlgorithmName(algorithm) {
|
1089 | switch (algorithm.name.toUpperCase()) {
|
1090 | case "SHA-1":
|
1091 | return "sha1";
|
1092 | case "SHA-256":
|
1093 | return "sha256";
|
1094 | case "SHA-384":
|
1095 | return "sha384";
|
1096 | case "SHA-512":
|
1097 | return "sha512";
|
1098 | case "SHA3-256":
|
1099 | return "sha3-256";
|
1100 | case "SHA3-384":
|
1101 | return "sha3-384";
|
1102 | case "SHA3-512":
|
1103 | return "sha3-512";
|
1104 | default:
|
1105 | throw new Error("Unrecognized name");
|
1106 | }
|
1107 | }
|
1108 | static digest(algorithm, data) {
|
1109 | const hashAlg = this.getAlgorithmName(algorithm);
|
1110 | const hash = crypto__default.createHash(hashAlg)
|
1111 | .update(Buffer.from(data)).digest();
|
1112 | return new Uint8Array(hash).buffer;
|
1113 | }
|
1114 | }
|
1115 |
|
1116 | class RsaOaepProvider extends core.RsaOaepProvider {
|
1117 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
1118 | const keys = await RsaCrypto.generateKey({
|
1119 | ...algorithm,
|
1120 | name: this.name,
|
1121 | }, extractable, keyUsages);
|
1122 | return {
|
1123 | privateKey: setCryptoKey(keys.privateKey),
|
1124 | publicKey: setCryptoKey(keys.publicKey),
|
1125 | };
|
1126 | }
|
1127 | async onEncrypt(algorithm, key, data) {
|
1128 | const internalKey = getCryptoKey(key);
|
1129 | const dataView = new Uint8Array(data);
|
1130 | const keySize = Math.ceil(internalKey.algorithm.modulusLength >> 3);
|
1131 | const hashSize = ShaCrypto.size(internalKey.algorithm.hash) >> 3;
|
1132 | const dataLength = dataView.byteLength;
|
1133 | const psLength = keySize - dataLength - 2 * hashSize - 2;
|
1134 | if (dataLength > keySize - 2 * hashSize - 2) {
|
1135 | throw new Error("Data too large");
|
1136 | }
|
1137 | const message = new Uint8Array(keySize);
|
1138 | const seed = message.subarray(1, hashSize + 1);
|
1139 | const dataBlock = message.subarray(hashSize + 1);
|
1140 | dataBlock.set(dataView, hashSize + psLength + 1);
|
1141 | const labelHash = crypto__default.createHash(internalKey.algorithm.hash.name.replace("-", ""))
|
1142 | .update(core.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0)))
|
1143 | .digest();
|
1144 | dataBlock.set(labelHash, 0);
|
1145 | dataBlock[hashSize + psLength] = 1;
|
1146 | crypto__default.randomFillSync(seed);
|
1147 | const dataBlockMask = this.mgf1(internalKey.algorithm.hash, seed, dataBlock.length);
|
1148 | for (let i = 0; i < dataBlock.length; i++) {
|
1149 | dataBlock[i] ^= dataBlockMask[i];
|
1150 | }
|
1151 | const seedMask = this.mgf1(internalKey.algorithm.hash, dataBlock, seed.length);
|
1152 | for (let i = 0; i < seed.length; i++) {
|
1153 | seed[i] ^= seedMask[i];
|
1154 | }
|
1155 | if (!internalKey.pem) {
|
1156 | internalKey.pem = `-----BEGIN PUBLIC KEY-----\n${internalKey.data.toString("base64")}\n-----END PUBLIC KEY-----`;
|
1157 | }
|
1158 | const pkcs0 = crypto__default.publicEncrypt({
|
1159 | key: internalKey.pem,
|
1160 | padding: crypto__default.constants.RSA_NO_PADDING,
|
1161 | }, Buffer.from(message));
|
1162 | return new Uint8Array(pkcs0).buffer;
|
1163 | }
|
1164 | async onDecrypt(algorithm, key, data) {
|
1165 | const internalKey = getCryptoKey(key);
|
1166 | const keySize = Math.ceil(internalKey.algorithm.modulusLength >> 3);
|
1167 | const hashSize = ShaCrypto.size(internalKey.algorithm.hash) >> 3;
|
1168 | const dataLength = data.byteLength;
|
1169 | if (dataLength !== keySize) {
|
1170 | throw new Error("Bad data");
|
1171 | }
|
1172 | if (!internalKey.pem) {
|
1173 | internalKey.pem = `-----BEGIN PRIVATE KEY-----\n${internalKey.data.toString("base64")}\n-----END PRIVATE KEY-----`;
|
1174 | }
|
1175 | let pkcs0 = crypto__default.privateDecrypt({
|
1176 | key: internalKey.pem,
|
1177 | padding: crypto__default.constants.RSA_NO_PADDING,
|
1178 | }, Buffer.from(data));
|
1179 | const z = pkcs0[0];
|
1180 | const seed = pkcs0.subarray(1, hashSize + 1);
|
1181 | const dataBlock = pkcs0.subarray(hashSize + 1);
|
1182 | if (z !== 0) {
|
1183 | throw new Error("Decryption failed");
|
1184 | }
|
1185 | const seedMask = this.mgf1(internalKey.algorithm.hash, dataBlock, seed.length);
|
1186 | for (let i = 0; i < seed.length; i++) {
|
1187 | seed[i] ^= seedMask[i];
|
1188 | }
|
1189 | const dataBlockMask = this.mgf1(internalKey.algorithm.hash, seed, dataBlock.length);
|
1190 | for (let i = 0; i < dataBlock.length; i++) {
|
1191 | dataBlock[i] ^= dataBlockMask[i];
|
1192 | }
|
1193 | const labelHash = crypto__default.createHash(internalKey.algorithm.hash.name.replace("-", ""))
|
1194 | .update(core.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0)))
|
1195 | .digest();
|
1196 | for (let i = 0; i < hashSize; i++) {
|
1197 | if (labelHash[i] !== dataBlock[i]) {
|
1198 | throw new Error("Decryption failed");
|
1199 | }
|
1200 | }
|
1201 | let psEnd = hashSize;
|
1202 | for (; psEnd < dataBlock.length; psEnd++) {
|
1203 | const psz = dataBlock[psEnd];
|
1204 | if (psz === 1) {
|
1205 | break;
|
1206 | }
|
1207 | if (psz !== 0) {
|
1208 | throw new Error("Decryption failed");
|
1209 | }
|
1210 | }
|
1211 | if (psEnd === dataBlock.length) {
|
1212 | throw new Error("Decryption failed");
|
1213 | }
|
1214 | pkcs0 = dataBlock.subarray(psEnd + 1);
|
1215 | return new Uint8Array(pkcs0).buffer;
|
1216 | }
|
1217 | async onExportKey(format, key) {
|
1218 | return RsaCrypto.exportKey(format, getCryptoKey(key));
|
1219 | }
|
1220 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
1221 | const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
|
1222 | return setCryptoKey(key);
|
1223 | }
|
1224 | checkCryptoKey(key, keyUsage) {
|
1225 | super.checkCryptoKey(key, keyUsage);
|
1226 | const internalKey = getCryptoKey(key);
|
1227 | if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) {
|
1228 | throw new TypeError("key: Is not RSA CryptoKey");
|
1229 | }
|
1230 | }
|
1231 | mgf1(algorithm, seed, length = 0) {
|
1232 | const hashSize = ShaCrypto.size(algorithm) >> 3;
|
1233 | const mask = new Uint8Array(length);
|
1234 | const counter = new Uint8Array(4);
|
1235 | const chunks = Math.ceil(length / hashSize);
|
1236 | for (let i = 0; i < chunks; i++) {
|
1237 | counter[0] = i >>> 24;
|
1238 | counter[1] = (i >>> 16) & 255;
|
1239 | counter[2] = (i >>> 8) & 255;
|
1240 | counter[3] = i & 255;
|
1241 | const submask = mask.subarray(i * hashSize);
|
1242 | let chunk = crypto__default.createHash(algorithm.name.replace("-", ""))
|
1243 | .update(seed)
|
1244 | .update(counter)
|
1245 | .digest();
|
1246 | if (chunk.length > submask.length) {
|
1247 | chunk = chunk.subarray(0, submask.length);
|
1248 | }
|
1249 | submask.set(chunk);
|
1250 | }
|
1251 | return mask;
|
1252 | }
|
1253 | }
|
1254 |
|
1255 | class RsaEsProvider extends core.ProviderCrypto {
|
1256 | constructor() {
|
1257 | super(...arguments);
|
1258 | this.name = "RSAES-PKCS1-v1_5";
|
1259 | this.usages = {
|
1260 | publicKey: ["encrypt", "wrapKey"],
|
1261 | privateKey: ["decrypt", "unwrapKey"],
|
1262 | };
|
1263 | }
|
1264 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
1265 | const keys = await RsaCrypto.generateKey({
|
1266 | ...algorithm,
|
1267 | name: this.name,
|
1268 | }, extractable, keyUsages);
|
1269 | return {
|
1270 | privateKey: setCryptoKey(keys.privateKey),
|
1271 | publicKey: setCryptoKey(keys.publicKey),
|
1272 | };
|
1273 | }
|
1274 | checkGenerateKeyParams(algorithm) {
|
1275 | this.checkRequiredProperty(algorithm, "publicExponent");
|
1276 | if (!(algorithm.publicExponent && algorithm.publicExponent instanceof Uint8Array)) {
|
1277 | throw new TypeError("publicExponent: Missing or not a Uint8Array");
|
1278 | }
|
1279 | const publicExponent = Convert.ToBase64(algorithm.publicExponent);
|
1280 | if (!(publicExponent === "Aw==" || publicExponent === "AQAB")) {
|
1281 | throw new TypeError("publicExponent: Must be [3] or [1,0,1]");
|
1282 | }
|
1283 | this.checkRequiredProperty(algorithm, "modulusLength");
|
1284 | switch (algorithm.modulusLength) {
|
1285 | case 1024:
|
1286 | case 2048:
|
1287 | case 4096:
|
1288 | break;
|
1289 | default:
|
1290 | throw new TypeError("modulusLength: Must be 1024, 2048, or 4096");
|
1291 | }
|
1292 | }
|
1293 | async onEncrypt(algorithm, key, data) {
|
1294 | const options = this.toCryptoOptions(key);
|
1295 | const enc = crypto.publicEncrypt(options, new Uint8Array(data));
|
1296 | return new Uint8Array(enc).buffer;
|
1297 | }
|
1298 | async onDecrypt(algorithm, key, data) {
|
1299 | const options = this.toCryptoOptions(key);
|
1300 | const dec = crypto.privateDecrypt(options, new Uint8Array(data));
|
1301 | return new Uint8Array(dec).buffer;
|
1302 | }
|
1303 | async onExportKey(format, key) {
|
1304 | return RsaCrypto.exportKey(format, getCryptoKey(key));
|
1305 | }
|
1306 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
1307 | const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
|
1308 | return setCryptoKey(key);
|
1309 | }
|
1310 | checkCryptoKey(key, keyUsage) {
|
1311 | super.checkCryptoKey(key, keyUsage);
|
1312 | const internalKey = getCryptoKey(key);
|
1313 | if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) {
|
1314 | throw new TypeError("key: Is not RSA CryptoKey");
|
1315 | }
|
1316 | }
|
1317 | toCryptoOptions(key) {
|
1318 | const type = key.type.toUpperCase();
|
1319 | return {
|
1320 | key: `-----BEGIN ${type} KEY-----\n${getCryptoKey(key).data.toString("base64")}\n-----END ${type} KEY-----`,
|
1321 | padding: crypto.constants.RSA_PKCS1_PADDING,
|
1322 | };
|
1323 | }
|
1324 | }
|
1325 |
|
1326 | const namedOIDs = {
|
1327 | "1.2.840.10045.3.1.7": "P-256",
|
1328 | "P-256": "1.2.840.10045.3.1.7",
|
1329 | "1.3.132.0.34": "P-384",
|
1330 | "P-384": "1.3.132.0.34",
|
1331 | "1.3.132.0.35": "P-521",
|
1332 | "P-521": "1.3.132.0.35",
|
1333 | "1.3.132.0.10": "K-256",
|
1334 | "K-256": "1.3.132.0.10",
|
1335 | "brainpoolP160r1": "1.3.36.3.3.2.8.1.1.1",
|
1336 | "1.3.36.3.3.2.8.1.1.1": "brainpoolP160r1",
|
1337 | "brainpoolP160t1": "1.3.36.3.3.2.8.1.1.2",
|
1338 | "1.3.36.3.3.2.8.1.1.2": "brainpoolP160t1",
|
1339 | "brainpoolP192r1": "1.3.36.3.3.2.8.1.1.3",
|
1340 | "1.3.36.3.3.2.8.1.1.3": "brainpoolP192r1",
|
1341 | "brainpoolP192t1": "1.3.36.3.3.2.8.1.1.4",
|
1342 | "1.3.36.3.3.2.8.1.1.4": "brainpoolP192t1",
|
1343 | "brainpoolP224r1": "1.3.36.3.3.2.8.1.1.5",
|
1344 | "1.3.36.3.3.2.8.1.1.5": "brainpoolP224r1",
|
1345 | "brainpoolP224t1": "1.3.36.3.3.2.8.1.1.6",
|
1346 | "1.3.36.3.3.2.8.1.1.6": "brainpoolP224t1",
|
1347 | "brainpoolP256r1": "1.3.36.3.3.2.8.1.1.7",
|
1348 | "1.3.36.3.3.2.8.1.1.7": "brainpoolP256r1",
|
1349 | "brainpoolP256t1": "1.3.36.3.3.2.8.1.1.8",
|
1350 | "1.3.36.3.3.2.8.1.1.8": "brainpoolP256t1",
|
1351 | "brainpoolP320r1": "1.3.36.3.3.2.8.1.1.9",
|
1352 | "1.3.36.3.3.2.8.1.1.9": "brainpoolP320r1",
|
1353 | "brainpoolP320t1": "1.3.36.3.3.2.8.1.1.10",
|
1354 | "1.3.36.3.3.2.8.1.1.10": "brainpoolP320t1",
|
1355 | "brainpoolP384r1": "1.3.36.3.3.2.8.1.1.11",
|
1356 | "1.3.36.3.3.2.8.1.1.11": "brainpoolP384r1",
|
1357 | "brainpoolP384t1": "1.3.36.3.3.2.8.1.1.12",
|
1358 | "1.3.36.3.3.2.8.1.1.12": "brainpoolP384t1",
|
1359 | "brainpoolP512r1": "1.3.36.3.3.2.8.1.1.13",
|
1360 | "1.3.36.3.3.2.8.1.1.13": "brainpoolP512r1",
|
1361 | "brainpoolP512t1": "1.3.36.3.3.2.8.1.1.14",
|
1362 | "1.3.36.3.3.2.8.1.1.14": "brainpoolP512t1",
|
1363 | };
|
1364 | function getOidByNamedCurve$1(namedCurve) {
|
1365 | const oid = namedOIDs[namedCurve];
|
1366 | if (!oid) {
|
1367 | throw new core.OperationError(`Cannot convert WebCrypto named curve '${namedCurve}' to OID`);
|
1368 | }
|
1369 | return oid;
|
1370 | }
|
1371 |
|
1372 | class EcPrivateKey extends AsymmetricKey {
|
1373 | constructor() {
|
1374 | super(...arguments);
|
1375 | this.type = "private";
|
1376 | }
|
1377 | getKey() {
|
1378 | const keyInfo = AsnParser.parse(this.data, core.asn1.PrivateKeyInfo);
|
1379 | return AsnParser.parse(keyInfo.privateKey, core.asn1.EcPrivateKey);
|
1380 | }
|
1381 | toJSON() {
|
1382 | const key = this.getKey();
|
1383 | const json = {
|
1384 | kty: "EC",
|
1385 | crv: this.algorithm.namedCurve,
|
1386 | key_ops: this.usages,
|
1387 | ext: this.extractable,
|
1388 | };
|
1389 | return Object.assign(json, JsonSerializer.toJSON(key));
|
1390 | }
|
1391 | fromJSON(json) {
|
1392 | if (!json.crv) {
|
1393 | throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`);
|
1394 | }
|
1395 | const keyInfo = new core.asn1.PrivateKeyInfo();
|
1396 | keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1";
|
1397 | keyInfo.privateKeyAlgorithm.parameters = AsnSerializer.serialize(new core.asn1.ObjectIdentifier(getOidByNamedCurve$1(json.crv)));
|
1398 | const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.EcPrivateKey });
|
1399 | keyInfo.privateKey = AsnSerializer.serialize(key);
|
1400 | this.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
1401 | return this;
|
1402 | }
|
1403 | }
|
1404 |
|
1405 | class EcPublicKey extends AsymmetricKey {
|
1406 | constructor() {
|
1407 | super(...arguments);
|
1408 | this.type = "public";
|
1409 | }
|
1410 | getKey() {
|
1411 | const keyInfo = AsnParser.parse(this.data, core.asn1.PublicKeyInfo);
|
1412 | return new core.asn1.EcPublicKey(keyInfo.publicKey);
|
1413 | }
|
1414 | toJSON() {
|
1415 | const key = this.getKey();
|
1416 | const json = {
|
1417 | kty: "EC",
|
1418 | crv: this.algorithm.namedCurve,
|
1419 | key_ops: this.usages,
|
1420 | ext: this.extractable,
|
1421 | };
|
1422 | return Object.assign(json, JsonSerializer.toJSON(key));
|
1423 | }
|
1424 | fromJSON(json) {
|
1425 | if (!json.crv) {
|
1426 | throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`);
|
1427 | }
|
1428 | const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.EcPublicKey });
|
1429 | const keyInfo = new core.asn1.PublicKeyInfo();
|
1430 | keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.10045.2.1";
|
1431 | keyInfo.publicKeyAlgorithm.parameters = AsnSerializer.serialize(new core.asn1.ObjectIdentifier(getOidByNamedCurve$1(json.crv)));
|
1432 | keyInfo.publicKey = AsnSerializer.toASN(key).valueHex;
|
1433 | this.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
1434 | return this;
|
1435 | }
|
1436 | }
|
1437 |
|
1438 | class Sha1Provider extends core.ProviderCrypto {
|
1439 | constructor() {
|
1440 | super(...arguments);
|
1441 | this.name = "SHA-1";
|
1442 | this.usages = [];
|
1443 | }
|
1444 | async onDigest(algorithm, data) {
|
1445 | return ShaCrypto.digest(algorithm, data);
|
1446 | }
|
1447 | }
|
1448 |
|
1449 | class Sha256Provider extends core.ProviderCrypto {
|
1450 | constructor() {
|
1451 | super(...arguments);
|
1452 | this.name = "SHA-256";
|
1453 | this.usages = [];
|
1454 | }
|
1455 | async onDigest(algorithm, data) {
|
1456 | return ShaCrypto.digest(algorithm, data);
|
1457 | }
|
1458 | }
|
1459 |
|
1460 | class Sha384Provider extends core.ProviderCrypto {
|
1461 | constructor() {
|
1462 | super(...arguments);
|
1463 | this.name = "SHA-384";
|
1464 | this.usages = [];
|
1465 | }
|
1466 | async onDigest(algorithm, data) {
|
1467 | return ShaCrypto.digest(algorithm, data);
|
1468 | }
|
1469 | }
|
1470 |
|
1471 | class Sha512Provider extends core.ProviderCrypto {
|
1472 | constructor() {
|
1473 | super(...arguments);
|
1474 | this.name = "SHA-512";
|
1475 | this.usages = [];
|
1476 | }
|
1477 | async onDigest(algorithm, data) {
|
1478 | return ShaCrypto.digest(algorithm, data);
|
1479 | }
|
1480 | }
|
1481 |
|
1482 | class Sha3256Provider extends core.ProviderCrypto {
|
1483 | constructor() {
|
1484 | super(...arguments);
|
1485 | this.name = "SHA3-256";
|
1486 | this.usages = [];
|
1487 | }
|
1488 | async onDigest(algorithm, data) {
|
1489 | return ShaCrypto.digest(algorithm, data);
|
1490 | }
|
1491 | }
|
1492 |
|
1493 | class Sha3384Provider extends core.ProviderCrypto {
|
1494 | constructor() {
|
1495 | super(...arguments);
|
1496 | this.name = "SHA3-384";
|
1497 | this.usages = [];
|
1498 | }
|
1499 | async onDigest(algorithm, data) {
|
1500 | return ShaCrypto.digest(algorithm, data);
|
1501 | }
|
1502 | }
|
1503 |
|
1504 | class Sha3512Provider extends core.ProviderCrypto {
|
1505 | constructor() {
|
1506 | super(...arguments);
|
1507 | this.name = "SHA3-512";
|
1508 | this.usages = [];
|
1509 | }
|
1510 | async onDigest(algorithm, data) {
|
1511 | return ShaCrypto.digest(algorithm, data);
|
1512 | }
|
1513 | }
|
1514 |
|
1515 | class EcCrypto {
|
1516 | static async generateKey(algorithm, extractable, keyUsages) {
|
1517 | const privateKey = new EcPrivateKey();
|
1518 | privateKey.algorithm = algorithm;
|
1519 | privateKey.extractable = extractable;
|
1520 | privateKey.usages = keyUsages.filter((usage) => this.privateKeyUsages.indexOf(usage) !== -1);
|
1521 | const publicKey = new EcPublicKey();
|
1522 | publicKey.algorithm = algorithm;
|
1523 | publicKey.extractable = true;
|
1524 | publicKey.usages = keyUsages.filter((usage) => this.publicKeyUsages.indexOf(usage) !== -1);
|
1525 | const keys = crypto__default.generateKeyPairSync("ec", {
|
1526 | namedCurve: this.getOpenSSLNamedCurve(algorithm.namedCurve),
|
1527 | publicKeyEncoding: {
|
1528 | format: "der",
|
1529 | type: "spki",
|
1530 | },
|
1531 | privateKeyEncoding: {
|
1532 | format: "der",
|
1533 | type: "pkcs8",
|
1534 | },
|
1535 | });
|
1536 | privateKey.data = keys.privateKey;
|
1537 | publicKey.data = keys.publicKey;
|
1538 | const res = {
|
1539 | privateKey,
|
1540 | publicKey,
|
1541 | };
|
1542 | return res;
|
1543 | }
|
1544 | static async sign(algorithm, key, data) {
|
1545 | const cryptoAlg = ShaCrypto.getAlgorithmName(algorithm.hash);
|
1546 | const signer = crypto__default.createSign(cryptoAlg);
|
1547 | signer.update(Buffer.from(data));
|
1548 | if (!key.pem) {
|
1549 | key.pem = `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`;
|
1550 | }
|
1551 | const options = {
|
1552 | key: key.pem,
|
1553 | };
|
1554 | const signature = signer.sign(options);
|
1555 | const ecSignature = AsnParser.parse(signature, core.asn1.EcDsaSignature);
|
1556 | const signatureRaw = core.EcUtils.encodeSignature(ecSignature, core.EcCurves.get(key.algorithm.namedCurve).size);
|
1557 | return signatureRaw.buffer;
|
1558 | }
|
1559 | static async verify(algorithm, key, signature, data) {
|
1560 | const cryptoAlg = ShaCrypto.getAlgorithmName(algorithm.hash);
|
1561 | const signer = crypto__default.createVerify(cryptoAlg);
|
1562 | signer.update(Buffer.from(data));
|
1563 | if (!key.pem) {
|
1564 | key.pem = `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`;
|
1565 | }
|
1566 | const options = {
|
1567 | key: key.pem,
|
1568 | };
|
1569 | const ecSignature = new core.asn1.EcDsaSignature();
|
1570 | const namedCurve = core.EcCurves.get(key.algorithm.namedCurve);
|
1571 | const signaturePoint = core.EcUtils.decodeSignature(signature, namedCurve.size);
|
1572 | ecSignature.r = BufferSourceConverter.toArrayBuffer(signaturePoint.r);
|
1573 | ecSignature.s = BufferSourceConverter.toArrayBuffer(signaturePoint.s);
|
1574 | const ecSignatureRaw = Buffer.from(AsnSerializer.serialize(ecSignature));
|
1575 | const ok = signer.verify(options, ecSignatureRaw);
|
1576 | return ok;
|
1577 | }
|
1578 | static async deriveBits(algorithm, baseKey, length) {
|
1579 | const cryptoAlg = this.getOpenSSLNamedCurve(baseKey.algorithm.namedCurve);
|
1580 | const ecdh = crypto__default.createECDH(cryptoAlg);
|
1581 | const asnPrivateKey = AsnParser.parse(baseKey.data, core.asn1.PrivateKeyInfo);
|
1582 | const asnEcPrivateKey = AsnParser.parse(asnPrivateKey.privateKey, core.asn1.EcPrivateKey);
|
1583 | ecdh.setPrivateKey(Buffer.from(asnEcPrivateKey.privateKey));
|
1584 | const asnPublicKey = AsnParser.parse(algorithm.public.data, core.asn1.PublicKeyInfo);
|
1585 | const bits = ecdh.computeSecret(Buffer.from(asnPublicKey.publicKey));
|
1586 | if (length === null) {
|
1587 | return bits;
|
1588 | }
|
1589 | return new Uint8Array(bits).buffer.slice(0, length >> 3);
|
1590 | }
|
1591 | static async exportKey(format, key) {
|
1592 | switch (format.toLowerCase()) {
|
1593 | case "jwk":
|
1594 | return JsonSerializer.toJSON(key);
|
1595 | case "pkcs8":
|
1596 | case "spki":
|
1597 | return new Uint8Array(key.data).buffer;
|
1598 | case "raw": {
|
1599 | const publicKeyInfo = AsnParser.parse(key.data, core.asn1.PublicKeyInfo);
|
1600 | return publicKeyInfo.publicKey;
|
1601 | }
|
1602 | default:
|
1603 | throw new core.OperationError("format: Must be 'jwk', 'raw', pkcs8' or 'spki'");
|
1604 | }
|
1605 | }
|
1606 | static async importKey(format, keyData, algorithm, extractable, keyUsages) {
|
1607 | switch (format.toLowerCase()) {
|
1608 | case "jwk": {
|
1609 | const jwk = keyData;
|
1610 | if (jwk.d) {
|
1611 | const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.EcPrivateKey });
|
1612 | return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages);
|
1613 | }
|
1614 | else {
|
1615 | const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.EcPublicKey });
|
1616 | return this.importPublicKey(asnKey, algorithm, extractable, keyUsages);
|
1617 | }
|
1618 | }
|
1619 | case "raw": {
|
1620 | const asnKey = new core.asn1.EcPublicKey(keyData);
|
1621 | return this.importPublicKey(asnKey, algorithm, extractable, keyUsages);
|
1622 | }
|
1623 | case "spki": {
|
1624 | const keyInfo = AsnParser.parse(new Uint8Array(keyData), core.asn1.PublicKeyInfo);
|
1625 | const asnKey = new core.asn1.EcPublicKey(keyInfo.publicKey);
|
1626 | this.assertKeyParameters(keyInfo.publicKeyAlgorithm.parameters, algorithm.namedCurve);
|
1627 | return this.importPublicKey(asnKey, algorithm, extractable, keyUsages);
|
1628 | }
|
1629 | case "pkcs8": {
|
1630 | const keyInfo = AsnParser.parse(new Uint8Array(keyData), core.asn1.PrivateKeyInfo);
|
1631 | const asnKey = AsnParser.parse(keyInfo.privateKey, core.asn1.EcPrivateKey);
|
1632 | this.assertKeyParameters(keyInfo.privateKeyAlgorithm.parameters, algorithm.namedCurve);
|
1633 | return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages);
|
1634 | }
|
1635 | default:
|
1636 | throw new core.OperationError("format: Must be 'jwk', 'raw', 'pkcs8' or 'spki'");
|
1637 | }
|
1638 | }
|
1639 | static assertKeyParameters(parameters, namedCurve) {
|
1640 | if (!parameters) {
|
1641 | throw new core.CryptoError("Key info doesn't have required parameters");
|
1642 | }
|
1643 | let namedCurveIdentifier = "";
|
1644 | try {
|
1645 | namedCurveIdentifier = AsnParser.parse(parameters, core.asn1.ObjectIdentifier).value;
|
1646 | }
|
1647 | catch (e) {
|
1648 | throw new core.CryptoError("Cannot read key info parameters");
|
1649 | }
|
1650 | if (getOidByNamedCurve$1(namedCurve) !== namedCurveIdentifier) {
|
1651 | throw new core.CryptoError("Key info parameter doesn't match to named curve");
|
1652 | }
|
1653 | }
|
1654 | static async importPrivateKey(asnKey, algorithm, extractable, keyUsages) {
|
1655 | const keyInfo = new core.asn1.PrivateKeyInfo();
|
1656 | keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1";
|
1657 | keyInfo.privateKeyAlgorithm.parameters = AsnSerializer.serialize(new core.asn1.ObjectIdentifier(getOidByNamedCurve$1(algorithm.namedCurve)));
|
1658 | keyInfo.privateKey = AsnSerializer.serialize(asnKey);
|
1659 | const key = new EcPrivateKey();
|
1660 | key.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
1661 | key.algorithm = Object.assign({}, algorithm);
|
1662 | key.extractable = extractable;
|
1663 | key.usages = keyUsages;
|
1664 | return key;
|
1665 | }
|
1666 | static async importPublicKey(asnKey, algorithm, extractable, keyUsages) {
|
1667 | const keyInfo = new core.asn1.PublicKeyInfo();
|
1668 | keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.10045.2.1";
|
1669 | const namedCurve = getOidByNamedCurve$1(algorithm.namedCurve);
|
1670 | keyInfo.publicKeyAlgorithm.parameters = AsnSerializer.serialize(new core.asn1.ObjectIdentifier(namedCurve));
|
1671 | keyInfo.publicKey = asnKey.value;
|
1672 | const key = new EcPublicKey();
|
1673 | key.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
1674 | key.algorithm = Object.assign({}, algorithm);
|
1675 | key.extractable = extractable;
|
1676 | key.usages = keyUsages;
|
1677 | return key;
|
1678 | }
|
1679 | static getOpenSSLNamedCurve(curve) {
|
1680 | switch (curve.toUpperCase()) {
|
1681 | case "P-256":
|
1682 | return "prime256v1";
|
1683 | case "K-256":
|
1684 | return "secp256k1";
|
1685 | case "P-384":
|
1686 | return "secp384r1";
|
1687 | case "P-521":
|
1688 | return "secp521r1";
|
1689 | default:
|
1690 | return curve;
|
1691 | }
|
1692 | }
|
1693 | }
|
1694 | EcCrypto.publicKeyUsages = ["verify"];
|
1695 | EcCrypto.privateKeyUsages = ["sign", "deriveKey", "deriveBits"];
|
1696 |
|
1697 | class EcdsaProvider extends core.EcdsaProvider {
|
1698 | constructor() {
|
1699 | super(...arguments);
|
1700 | this.namedCurves = core.EcCurves.names;
|
1701 | this.hashAlgorithms = [
|
1702 | "SHA-1", "SHA-256", "SHA-384", "SHA-512",
|
1703 | "shake128", "shake256",
|
1704 | "SHA3-256", "SHA3-384", "SHA3-512"
|
1705 | ];
|
1706 | }
|
1707 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
1708 | const keys = await EcCrypto.generateKey({
|
1709 | ...algorithm,
|
1710 | name: this.name,
|
1711 | }, extractable, keyUsages);
|
1712 | return {
|
1713 | privateKey: setCryptoKey(keys.privateKey),
|
1714 | publicKey: setCryptoKey(keys.publicKey),
|
1715 | };
|
1716 | }
|
1717 | async onSign(algorithm, key, data) {
|
1718 | return EcCrypto.sign(algorithm, getCryptoKey(key), new Uint8Array(data));
|
1719 | }
|
1720 | async onVerify(algorithm, key, signature, data) {
|
1721 | return EcCrypto.verify(algorithm, getCryptoKey(key), new Uint8Array(signature), new Uint8Array(data));
|
1722 | }
|
1723 | async onExportKey(format, key) {
|
1724 | return EcCrypto.exportKey(format, getCryptoKey(key));
|
1725 | }
|
1726 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
1727 | const key = await EcCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
|
1728 | return setCryptoKey(key);
|
1729 | }
|
1730 | checkCryptoKey(key, keyUsage) {
|
1731 | super.checkCryptoKey(key, keyUsage);
|
1732 | const internalKey = getCryptoKey(key);
|
1733 | if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) {
|
1734 | throw new TypeError("key: Is not EC CryptoKey");
|
1735 | }
|
1736 | }
|
1737 | }
|
1738 |
|
1739 | class EcdhProvider extends core.EcdhProvider {
|
1740 | constructor() {
|
1741 | super(...arguments);
|
1742 | this.namedCurves = core.EcCurves.names;
|
1743 | }
|
1744 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
1745 | const keys = await EcCrypto.generateKey({
|
1746 | ...algorithm,
|
1747 | name: this.name,
|
1748 | }, extractable, keyUsages);
|
1749 | return {
|
1750 | privateKey: setCryptoKey(keys.privateKey),
|
1751 | publicKey: setCryptoKey(keys.publicKey),
|
1752 | };
|
1753 | }
|
1754 | async onExportKey(format, key) {
|
1755 | return EcCrypto.exportKey(format, getCryptoKey(key));
|
1756 | }
|
1757 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
1758 | const key = await EcCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
|
1759 | return setCryptoKey(key);
|
1760 | }
|
1761 | checkCryptoKey(key, keyUsage) {
|
1762 | super.checkCryptoKey(key, keyUsage);
|
1763 | const internalKey = getCryptoKey(key);
|
1764 | if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) {
|
1765 | throw new TypeError("key: Is not EC CryptoKey");
|
1766 | }
|
1767 | }
|
1768 | async onDeriveBits(algorithm, baseKey, length) {
|
1769 | const bits = await EcCrypto.deriveBits({ ...algorithm, public: getCryptoKey(algorithm.public) }, getCryptoKey(baseKey), length);
|
1770 | return bits;
|
1771 | }
|
1772 | }
|
1773 |
|
1774 | const edOIDs = {
|
1775 | [core.asn1.idEd448]: "Ed448",
|
1776 | "ed448": core.asn1.idEd448,
|
1777 | [core.asn1.idX448]: "X448",
|
1778 | "x448": core.asn1.idX448,
|
1779 | [core.asn1.idEd25519]: "Ed25519",
|
1780 | "ed25519": core.asn1.idEd25519,
|
1781 | [core.asn1.idX25519]: "X25519",
|
1782 | "x25519": core.asn1.idX25519,
|
1783 | };
|
1784 | function getOidByNamedCurve(namedCurve) {
|
1785 | const oid = edOIDs[namedCurve.toLowerCase()];
|
1786 | if (!oid) {
|
1787 | throw new core.OperationError(`Cannot convert WebCrypto named curve '${namedCurve}' to OID`);
|
1788 | }
|
1789 | return oid;
|
1790 | }
|
1791 |
|
1792 | class EdPrivateKey extends AsymmetricKey {
|
1793 | constructor() {
|
1794 | super(...arguments);
|
1795 | this.type = "private";
|
1796 | }
|
1797 | getKey() {
|
1798 | const keyInfo = AsnParser.parse(this.data, core.asn1.PrivateKeyInfo);
|
1799 | return AsnParser.parse(keyInfo.privateKey, core.asn1.CurvePrivateKey);
|
1800 | }
|
1801 | toJSON() {
|
1802 | const key = this.getKey();
|
1803 | const json = {
|
1804 | kty: "OKP",
|
1805 | crv: this.algorithm.namedCurve,
|
1806 | key_ops: this.usages,
|
1807 | ext: this.extractable,
|
1808 | };
|
1809 | return Object.assign(json, JsonSerializer.toJSON(key));
|
1810 | }
|
1811 | fromJSON(json) {
|
1812 | if (!json.crv) {
|
1813 | throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`);
|
1814 | }
|
1815 | const keyInfo = new core.asn1.PrivateKeyInfo();
|
1816 | keyInfo.privateKeyAlgorithm.algorithm = getOidByNamedCurve(json.crv);
|
1817 | const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.CurvePrivateKey });
|
1818 | keyInfo.privateKey = AsnSerializer.serialize(key);
|
1819 | this.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
1820 | return this;
|
1821 | }
|
1822 | }
|
1823 |
|
1824 | class EdPublicKey extends AsymmetricKey {
|
1825 | constructor() {
|
1826 | super(...arguments);
|
1827 | this.type = "public";
|
1828 | }
|
1829 | getKey() {
|
1830 | const keyInfo = AsnParser.parse(this.data, core.asn1.PublicKeyInfo);
|
1831 | return keyInfo.publicKey;
|
1832 | }
|
1833 | toJSON() {
|
1834 | const key = this.getKey();
|
1835 | const json = {
|
1836 | kty: "OKP",
|
1837 | crv: this.algorithm.namedCurve,
|
1838 | key_ops: this.usages,
|
1839 | ext: this.extractable,
|
1840 | };
|
1841 | return Object.assign(json, {
|
1842 | x: Convert.ToBase64Url(key)
|
1843 | });
|
1844 | }
|
1845 | fromJSON(json) {
|
1846 | if (!json.crv) {
|
1847 | throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`);
|
1848 | }
|
1849 | if (!json.x) {
|
1850 | throw new core.OperationError(`Cannot get property from JWK. Property 'x' is required`);
|
1851 | }
|
1852 | const keyInfo = new core.asn1.PublicKeyInfo();
|
1853 | keyInfo.publicKeyAlgorithm.algorithm = getOidByNamedCurve(json.crv);
|
1854 | keyInfo.publicKey = Convert.FromBase64Url(json.x);
|
1855 | this.data = Buffer.from(AsnSerializer.serialize(keyInfo));
|
1856 | return this;
|
1857 | }
|
1858 | }
|
1859 |
|
1860 | class EdCrypto {
|
1861 | static async generateKey(algorithm, extractable, keyUsages) {
|
1862 | const privateKey = new EdPrivateKey();
|
1863 | privateKey.algorithm = algorithm;
|
1864 | privateKey.extractable = extractable;
|
1865 | privateKey.usages = keyUsages.filter((usage) => this.privateKeyUsages.indexOf(usage) !== -1);
|
1866 | const publicKey = new EdPublicKey();
|
1867 | publicKey.algorithm = algorithm;
|
1868 | publicKey.extractable = true;
|
1869 | publicKey.usages = keyUsages.filter((usage) => this.publicKeyUsages.indexOf(usage) !== -1);
|
1870 | const type = algorithm.namedCurve.toLowerCase();
|
1871 | const keys = crypto__default.generateKeyPairSync(type, {
|
1872 | publicKeyEncoding: {
|
1873 | format: "der",
|
1874 | type: "spki",
|
1875 | },
|
1876 | privateKeyEncoding: {
|
1877 | format: "der",
|
1878 | type: "pkcs8",
|
1879 | },
|
1880 | });
|
1881 | privateKey.data = keys.privateKey;
|
1882 | publicKey.data = keys.publicKey;
|
1883 | const res = {
|
1884 | privateKey,
|
1885 | publicKey,
|
1886 | };
|
1887 | return res;
|
1888 | }
|
1889 | static async sign(algorithm, key, data) {
|
1890 | if (!key.pem) {
|
1891 | key.pem = `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`;
|
1892 | }
|
1893 | const options = {
|
1894 | key: key.pem,
|
1895 | };
|
1896 | const signature = crypto__default.sign(null, Buffer.from(data), options);
|
1897 | return core.BufferSourceConverter.toArrayBuffer(signature);
|
1898 | }
|
1899 | static async verify(algorithm, key, signature, data) {
|
1900 | if (!key.pem) {
|
1901 | key.pem = `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`;
|
1902 | }
|
1903 | const options = {
|
1904 | key: key.pem,
|
1905 | };
|
1906 | const ok = crypto__default.verify(null, Buffer.from(data), options, Buffer.from(signature));
|
1907 | return ok;
|
1908 | }
|
1909 | static async deriveBits(algorithm, baseKey, length) {
|
1910 | const publicKey = crypto__default.createPublicKey({
|
1911 | key: algorithm.public.data,
|
1912 | format: "der",
|
1913 | type: "spki",
|
1914 | });
|
1915 | const privateKey = crypto__default.createPrivateKey({
|
1916 | key: baseKey.data,
|
1917 | format: "der",
|
1918 | type: "pkcs8",
|
1919 | });
|
1920 | const bits = crypto__default.diffieHellman({
|
1921 | publicKey,
|
1922 | privateKey,
|
1923 | });
|
1924 | return new Uint8Array(bits).buffer.slice(0, length >> 3);
|
1925 | }
|
1926 | static async exportKey(format, key) {
|
1927 | switch (format.toLowerCase()) {
|
1928 | case "jwk":
|
1929 | return JsonSerializer.toJSON(key);
|
1930 | case "pkcs8":
|
1931 | case "spki":
|
1932 | return new Uint8Array(key.data).buffer;
|
1933 | case "raw": {
|
1934 | const publicKeyInfo = AsnParser.parse(key.data, core.asn1.PublicKeyInfo);
|
1935 | return publicKeyInfo.publicKey;
|
1936 | }
|
1937 | default:
|
1938 | throw new core.OperationError("format: Must be 'jwk', 'raw', pkcs8' or 'spki'");
|
1939 | }
|
1940 | }
|
1941 | static async importKey(format, keyData, algorithm, extractable, keyUsages) {
|
1942 | switch (format.toLowerCase()) {
|
1943 | case "jwk": {
|
1944 | const jwk = keyData;
|
1945 | if (jwk.d) {
|
1946 | const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.CurvePrivateKey });
|
1947 | return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages);
|
1948 | }
|
1949 | else {
|
1950 | if (!jwk.x) {
|
1951 | throw new TypeError("keyData: Cannot get required 'x' filed");
|
1952 | }
|
1953 | return this.importPublicKey(Convert.FromBase64Url(jwk.x), algorithm, extractable, keyUsages);
|
1954 | }
|
1955 | }
|
1956 | case "raw": {
|
1957 | return this.importPublicKey(keyData, algorithm, extractable, keyUsages);
|
1958 | }
|
1959 | case "spki": {
|
1960 | const keyInfo = AsnParser.parse(new Uint8Array(keyData), core.asn1.PublicKeyInfo);
|
1961 | return this.importPublicKey(keyInfo.publicKey, algorithm, extractable, keyUsages);
|
1962 | }
|
1963 | case "pkcs8": {
|
1964 | const keyInfo = AsnParser.parse(new Uint8Array(keyData), core.asn1.PrivateKeyInfo);
|
1965 | const asnKey = AsnParser.parse(keyInfo.privateKey, core.asn1.CurvePrivateKey);
|
1966 | return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages);
|
1967 | }
|
1968 | default:
|
1969 | throw new core.OperationError("format: Must be 'jwk', 'raw', 'pkcs8' or 'spki'");
|
1970 | }
|
1971 | }
|
1972 | static importPrivateKey(asnKey, algorithm, extractable, keyUsages) {
|
1973 | const key = new EdPrivateKey();
|
1974 | key.fromJSON({
|
1975 | crv: algorithm.namedCurve,
|
1976 | d: Convert.ToBase64Url(asnKey.d),
|
1977 | });
|
1978 | key.algorithm = Object.assign({}, algorithm);
|
1979 | key.extractable = extractable;
|
1980 | key.usages = keyUsages;
|
1981 | return key;
|
1982 | }
|
1983 | static async importPublicKey(asnKey, algorithm, extractable, keyUsages) {
|
1984 | const key = new EdPublicKey();
|
1985 | key.fromJSON({
|
1986 | crv: algorithm.namedCurve,
|
1987 | x: Convert.ToBase64Url(asnKey),
|
1988 | });
|
1989 | key.algorithm = Object.assign({}, algorithm);
|
1990 | key.extractable = extractable;
|
1991 | key.usages = keyUsages;
|
1992 | return key;
|
1993 | }
|
1994 | }
|
1995 | EdCrypto.publicKeyUsages = ["verify"];
|
1996 | EdCrypto.privateKeyUsages = ["sign", "deriveKey", "deriveBits"];
|
1997 |
|
1998 | class EdDsaProvider extends core.EdDsaProvider {
|
1999 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
2000 | const keys = await EdCrypto.generateKey({
|
2001 | name: this.name,
|
2002 | namedCurve: algorithm.namedCurve.replace(/^ed/i, "Ed"),
|
2003 | }, extractable, keyUsages);
|
2004 | return {
|
2005 | privateKey: setCryptoKey(keys.privateKey),
|
2006 | publicKey: setCryptoKey(keys.publicKey),
|
2007 | };
|
2008 | }
|
2009 | async onSign(algorithm, key, data) {
|
2010 | return EdCrypto.sign(algorithm, getCryptoKey(key), new Uint8Array(data));
|
2011 | }
|
2012 | async onVerify(algorithm, key, signature, data) {
|
2013 | return EdCrypto.verify(algorithm, getCryptoKey(key), new Uint8Array(signature), new Uint8Array(data));
|
2014 | }
|
2015 | async onExportKey(format, key) {
|
2016 | return EdCrypto.exportKey(format, getCryptoKey(key));
|
2017 | }
|
2018 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
2019 | const key = await EdCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
|
2020 | return setCryptoKey(key);
|
2021 | }
|
2022 | }
|
2023 |
|
2024 | class EcdhEsProvider extends core.EcdhEsProvider {
|
2025 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
2026 | const keys = await EdCrypto.generateKey({
|
2027 | name: this.name,
|
2028 | namedCurve: algorithm.namedCurve.toUpperCase(),
|
2029 | }, extractable, keyUsages);
|
2030 | return {
|
2031 | privateKey: setCryptoKey(keys.privateKey),
|
2032 | publicKey: setCryptoKey(keys.publicKey),
|
2033 | };
|
2034 | }
|
2035 | async onDeriveBits(algorithm, baseKey, length) {
|
2036 | const bits = await EdCrypto.deriveBits({ ...algorithm, public: getCryptoKey(algorithm.public) }, getCryptoKey(baseKey), length);
|
2037 | return bits;
|
2038 | }
|
2039 | async onExportKey(format, key) {
|
2040 | return EdCrypto.exportKey(format, getCryptoKey(key));
|
2041 | }
|
2042 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
2043 | const key = await EdCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
|
2044 | return setCryptoKey(key);
|
2045 | }
|
2046 | }
|
2047 |
|
2048 | class PbkdfCryptoKey extends CryptoKey {
|
2049 | }
|
2050 |
|
2051 | class Pbkdf2Provider extends core.Pbkdf2Provider {
|
2052 | async onDeriveBits(algorithm, baseKey, length) {
|
2053 | return new Promise((resolve, reject) => {
|
2054 | const salt = core.BufferSourceConverter.toArrayBuffer(algorithm.salt);
|
2055 | const hash = algorithm.hash.name.replace("-", "");
|
2056 | crypto__default.pbkdf2(getCryptoKey(baseKey).data, Buffer.from(salt), algorithm.iterations, length >> 3, hash, (err, derivedBits) => {
|
2057 | if (err) {
|
2058 | reject(err);
|
2059 | }
|
2060 | else {
|
2061 | resolve(new Uint8Array(derivedBits).buffer);
|
2062 | }
|
2063 | });
|
2064 | });
|
2065 | }
|
2066 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
2067 | if (format === "raw") {
|
2068 | const key = new PbkdfCryptoKey();
|
2069 | key.data = Buffer.from(keyData);
|
2070 | key.algorithm = { name: this.name };
|
2071 | key.extractable = false;
|
2072 | key.usages = keyUsages;
|
2073 | return setCryptoKey(key);
|
2074 | }
|
2075 | throw new core.OperationError("format: Must be 'raw'");
|
2076 | }
|
2077 | checkCryptoKey(key, keyUsage) {
|
2078 | super.checkCryptoKey(key, keyUsage);
|
2079 | if (!(getCryptoKey(key) instanceof PbkdfCryptoKey)) {
|
2080 | throw new TypeError("key: Is not PBKDF CryptoKey");
|
2081 | }
|
2082 | }
|
2083 | }
|
2084 |
|
2085 | class HmacCryptoKey extends CryptoKey {
|
2086 | get alg() {
|
2087 | const hash = this.algorithm.hash.name.toUpperCase();
|
2088 | return `HS${hash.replace("SHA-", "")}`;
|
2089 | }
|
2090 | set alg(value) {
|
2091 | }
|
2092 | }
|
2093 | __decorate([
|
2094 | JsonProp({ name: "k", converter: JsonBase64UrlConverter })
|
2095 | ], HmacCryptoKey.prototype, "data", void 0);
|
2096 |
|
2097 | class HmacProvider extends core.HmacProvider {
|
2098 | async onGenerateKey(algorithm, extractable, keyUsages) {
|
2099 | const length = (algorithm.length || this.getDefaultLength(algorithm.hash.name)) >> 3 << 3;
|
2100 | const key = new HmacCryptoKey();
|
2101 | key.algorithm = {
|
2102 | ...algorithm,
|
2103 | length,
|
2104 | name: this.name,
|
2105 | };
|
2106 | key.extractable = extractable;
|
2107 | key.usages = keyUsages;
|
2108 | key.data = crypto__default.randomBytes(length >> 3);
|
2109 | return setCryptoKey(key);
|
2110 | }
|
2111 | async onSign(algorithm, key, data) {
|
2112 | const cryptoAlg = ShaCrypto.getAlgorithmName(key.algorithm.hash);
|
2113 | const hmac = crypto__default.createHmac(cryptoAlg, getCryptoKey(key).data)
|
2114 | .update(Buffer.from(data)).digest();
|
2115 | return new Uint8Array(hmac).buffer;
|
2116 | }
|
2117 | async onVerify(algorithm, key, signature, data) {
|
2118 | const cryptoAlg = ShaCrypto.getAlgorithmName(key.algorithm.hash);
|
2119 | const hmac = crypto__default.createHmac(cryptoAlg, getCryptoKey(key).data)
|
2120 | .update(Buffer.from(data)).digest();
|
2121 | return hmac.compare(Buffer.from(signature)) === 0;
|
2122 | }
|
2123 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
2124 | let key;
|
2125 | switch (format.toLowerCase()) {
|
2126 | case "jwk":
|
2127 | key = JsonParser.fromJSON(keyData, { targetSchema: HmacCryptoKey });
|
2128 | break;
|
2129 | case "raw":
|
2130 | key = new HmacCryptoKey();
|
2131 | key.data = Buffer.from(keyData);
|
2132 | break;
|
2133 | default:
|
2134 | throw new core.OperationError("format: Must be 'jwk' or 'raw'");
|
2135 | }
|
2136 | key.algorithm = {
|
2137 | hash: { name: algorithm.hash.name },
|
2138 | name: this.name,
|
2139 | length: key.data.length << 3,
|
2140 | };
|
2141 | key.extractable = extractable;
|
2142 | key.usages = keyUsages;
|
2143 | return setCryptoKey(key);
|
2144 | }
|
2145 | async onExportKey(format, key) {
|
2146 | switch (format.toLowerCase()) {
|
2147 | case "jwk":
|
2148 | return JsonSerializer.toJSON(getCryptoKey(key));
|
2149 | case "raw":
|
2150 | return new Uint8Array(getCryptoKey(key).data).buffer;
|
2151 | default:
|
2152 | throw new core.OperationError("format: Must be 'jwk' or 'raw'");
|
2153 | }
|
2154 | }
|
2155 | checkCryptoKey(key, keyUsage) {
|
2156 | super.checkCryptoKey(key, keyUsage);
|
2157 | if (!(getCryptoKey(key) instanceof HmacCryptoKey)) {
|
2158 | throw new TypeError("key: Is not HMAC CryptoKey");
|
2159 | }
|
2160 | }
|
2161 | }
|
2162 |
|
2163 | class HkdfCryptoKey extends CryptoKey {
|
2164 | }
|
2165 |
|
2166 | class HkdfProvider extends core.HkdfProvider {
|
2167 | async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
|
2168 | if (format.toLowerCase() !== "raw") {
|
2169 | throw new core.OperationError("Operation not supported");
|
2170 | }
|
2171 | const key = new HkdfCryptoKey();
|
2172 | key.data = Buffer.from(keyData);
|
2173 | key.algorithm = { name: this.name };
|
2174 | key.extractable = extractable;
|
2175 | key.usages = keyUsages;
|
2176 | return setCryptoKey(key);
|
2177 | }
|
2178 | async onDeriveBits(params, baseKey, length) {
|
2179 | const hash = params.hash.name.replace("-", "");
|
2180 | const hashLength = crypto__default.createHash(hash).digest().length;
|
2181 | const byteLength = length / 8;
|
2182 | const info = BufferSourceConverter$1.toUint8Array(params.info);
|
2183 | const PRK = crypto__default.createHmac(hash, BufferSourceConverter$1.toUint8Array(params.salt))
|
2184 | .update(BufferSourceConverter$1.toUint8Array(getCryptoKey(baseKey).data))
|
2185 | .digest();
|
2186 | const blocks = [Buffer.alloc(0)];
|
2187 | const blockCount = Math.ceil(byteLength / hashLength) + 1;
|
2188 | for (let i = 1; i < blockCount; ++i) {
|
2189 | blocks.push(crypto__default.createHmac(hash, PRK)
|
2190 | .update(Buffer.concat([blocks[i - 1], info, Buffer.from([i])]))
|
2191 | .digest());
|
2192 | }
|
2193 | return Buffer.concat(blocks).slice(0, byteLength);
|
2194 | }
|
2195 | checkCryptoKey(key, keyUsage) {
|
2196 | super.checkCryptoKey(key, keyUsage);
|
2197 | if (!(getCryptoKey(key) instanceof HkdfCryptoKey)) {
|
2198 | throw new TypeError("key: Is not HKDF CryptoKey");
|
2199 | }
|
2200 | }
|
2201 | }
|
2202 |
|
2203 | class ShakeCrypto {
|
2204 | static digest(algorithm, data) {
|
2205 | const hash = crypto__default.createHash(algorithm.name.toLowerCase(), { outputLength: algorithm.length })
|
2206 | .update(Buffer.from(data)).digest();
|
2207 | return new Uint8Array(hash).buffer;
|
2208 | }
|
2209 | }
|
2210 |
|
2211 | class Shake128Provider extends core.Shake128Provider {
|
2212 | async onDigest(algorithm, data) {
|
2213 | return ShakeCrypto.digest(algorithm, data);
|
2214 | }
|
2215 | }
|
2216 |
|
2217 | class Shake256Provider extends core.Shake256Provider {
|
2218 | async onDigest(algorithm, data) {
|
2219 | return ShakeCrypto.digest(algorithm, data);
|
2220 | }
|
2221 | }
|
2222 |
|
2223 | class SubtleCrypto extends core.SubtleCrypto {
|
2224 | constructor() {
|
2225 | var _a;
|
2226 | super();
|
2227 | this.providers.set(new AesCbcProvider());
|
2228 | this.providers.set(new AesCtrProvider());
|
2229 | this.providers.set(new AesGcmProvider());
|
2230 | this.providers.set(new AesCmacProvider());
|
2231 | this.providers.set(new AesKwProvider());
|
2232 | this.providers.set(new AesEcbProvider());
|
2233 | const ciphers = crypto.getCiphers();
|
2234 | if (ciphers.includes("des-cbc")) {
|
2235 | this.providers.set(new DesCbcProvider());
|
2236 | }
|
2237 | this.providers.set(new DesEde3CbcProvider());
|
2238 | this.providers.set(new RsaSsaProvider());
|
2239 | this.providers.set(new RsaPssProvider());
|
2240 | this.providers.set(new RsaOaepProvider());
|
2241 | this.providers.set(new RsaEsProvider());
|
2242 | this.providers.set(new EcdsaProvider());
|
2243 | this.providers.set(new EcdhProvider());
|
2244 | this.providers.set(new Sha1Provider());
|
2245 | this.providers.set(new Sha256Provider());
|
2246 | this.providers.set(new Sha384Provider());
|
2247 | this.providers.set(new Sha512Provider());
|
2248 | this.providers.set(new Pbkdf2Provider());
|
2249 | this.providers.set(new HmacProvider());
|
2250 | this.providers.set(new HkdfProvider());
|
2251 | const nodeMajorVersion = (_a = /^v(\d+)/.exec(process.version)) === null || _a === void 0 ? void 0 : _a[1];
|
2252 | if (nodeMajorVersion && parseInt(nodeMajorVersion, 10) >= 12) {
|
2253 | this.providers.set(new Shake128Provider());
|
2254 | this.providers.set(new Shake256Provider());
|
2255 | }
|
2256 | const hashes = crypto.getHashes();
|
2257 | if (hashes.includes("sha3-256")) {
|
2258 | this.providers.set(new Sha3256Provider());
|
2259 | }
|
2260 | if (hashes.includes("sha3-384")) {
|
2261 | this.providers.set(new Sha3384Provider());
|
2262 | }
|
2263 | if (hashes.includes("sha3-512")) {
|
2264 | this.providers.set(new Sha3512Provider());
|
2265 | }
|
2266 | if (nodeMajorVersion && parseInt(nodeMajorVersion, 10) >= 14) {
|
2267 | this.providers.set(new EdDsaProvider());
|
2268 | this.providers.set(new EcdhEsProvider());
|
2269 | }
|
2270 | }
|
2271 | }
|
2272 |
|
2273 | class Crypto extends core.Crypto {
|
2274 | constructor() {
|
2275 | super(...arguments);
|
2276 | this.subtle = new SubtleCrypto();
|
2277 | }
|
2278 | getRandomValues(array) {
|
2279 | if (!ArrayBuffer.isView(array)) {
|
2280 | throw new TypeError("Failed to execute 'getRandomValues' on 'Crypto': parameter 1 is not of type 'ArrayBufferView'");
|
2281 | }
|
2282 | const buffer = Buffer.from(array.buffer, array.byteOffset, array.byteLength);
|
2283 | crypto__default.randomFillSync(buffer);
|
2284 | return array;
|
2285 | }
|
2286 | }
|
2287 |
|
2288 | export { Crypto };
|