UNPKG

353 kBJavaScriptView Raw
1var liner = (function (exports) {
2 'use strict';
3
4 function _defineProperty(obj, key, value) {
5 if (key in obj) {
6 Object.defineProperty(obj, key, {
7 value: value,
8 enumerable: true,
9 configurable: true,
10 writable: true
11 });
12 } else {
13 obj[key] = value;
14 }
15
16 return obj;
17 }
18
19 function _objectSpread(target) {
20 for (var i = 1; i < arguments.length; i++) {
21 var source = arguments[i] != null ? arguments[i] : {};
22 var ownKeys = Object.keys(source);
23
24 if (typeof Object.getOwnPropertySymbols === 'function') {
25 ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
26 return Object.getOwnPropertyDescriptor(source, sym).enumerable;
27 }));
28 }
29
30 ownKeys.forEach(function (key) {
31 _defineProperty(target, key, source[key]);
32 });
33 }
34
35 return target;
36 }
37
38 class Debug {
39 static get enabled() {
40 return typeof self !== "undefined" && window.PV_WEBCRYPTO_LINER_LOG;
41 }
42
43 static log(message, ...optionalParams) {
44 if (this.enabled) {
45 console.log.apply(console, arguments);
46 }
47 }
48
49 static error(message, ...optionalParams) {
50 if (this.enabled) {
51 console.error.apply(console, arguments);
52 }
53 }
54
55 static info(message, ...optionalParams) {
56 if (this.enabled) {
57 console.info.apply(console, arguments);
58 }
59 }
60
61 static warn(message, ...optionalParams) {
62 if (this.enabled) {
63 console.warn.apply(console, arguments);
64 }
65 }
66
67 static trace(message, ...optionalParams) {
68 if (this.enabled) {
69 console.trace.apply(console, arguments);
70 }
71 }
72
73 }
74// section modified by isomorphic-webcrypto build
75
76 const nativeCrypto = window.msCrypto || window.crypto || {};
77 let nativeSubtle = null;
78
79 try {
80 nativeSubtle = nativeCrypto.subtle || nativeCrypto.webkitSubtle;
81 } catch (err) {
82 console.warn("Cannot get subtle from crypto", err);
83 }
84 /*! *****************************************************************************
85 Copyright (c) Microsoft Corporation. All rights reserved.
86 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
87 this file except in compliance with the License. You may obtain a copy of the
88 License at http://www.apache.org/licenses/LICENSE-2.0
89
90 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
91 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
92 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
93 MERCHANTABLITY OR NON-INFRINGEMENT.
94
95 See the Apache Version 2.0 License for specific language governing permissions
96 and limitations under the License.
97 ***************************************************************************** */
98
99
100 function __decorate(decorators, target, key, desc) {
101 var c = arguments.length,
102 r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
103 d;
104 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
105 return c > 3 && r && Object.defineProperty(target, key, r), r;
106 }
107
108 function __awaiter(thisArg, _arguments, P, generator) {
109 return new (P || (P = Promise))(function (resolve, reject) {
110 function fulfilled(value) {
111 try {
112 step(generator.next(value));
113 } catch (e) {
114 reject(e);
115 }
116 }
117
118 function rejected(value) {
119 try {
120 step(generator["throw"](value));
121 } catch (e) {
122 reject(e);
123 }
124 }
125
126 function step(result) {
127 result.done ? resolve(result.value) : new P(function (resolve) {
128 resolve(result.value);
129 }).then(fulfilled, rejected);
130 }
131
132 step((generator = generator.apply(thisArg, _arguments || [])).next());
133 });
134 }
135
136 function PrepareBuffer(buffer) {
137 if (typeof Buffer !== "undefined") {
138 return new Uint8Array(buffer);
139 } else {
140 return new Uint8Array(buffer instanceof ArrayBuffer ? buffer : buffer.buffer);
141 }
142 }
143
144 class Convert {
145 static ToString(buffer, enc = "utf8") {
146 const buf = PrepareBuffer(buffer);
147
148 switch (enc.toLowerCase()) {
149 case "utf8":
150 return this.ToUtf8String(buf);
151
152 case "binary":
153 return this.ToBinary(buf);
154
155 case "hex":
156 return this.ToHex(buf);
157
158 case "base64":
159 return this.ToBase64(buf);
160
161 case "base64url":
162 return this.ToBase64Url(buf);
163
164 default:
165 throw new Error(`Unknown type of encoding '${enc}'`);
166 }
167 }
168
169 static FromString(str, enc = "utf8") {
170 switch (enc.toLowerCase()) {
171 case "utf8":
172 return this.FromUtf8String(str);
173
174 case "binary":
175 return this.FromBinary(str);
176
177 case "hex":
178 return this.FromHex(str);
179
180 case "base64":
181 return this.FromBase64(str);
182
183 case "base64url":
184 return this.FromBase64Url(str);
185
186 default:
187 throw new Error(`Unknown type of encoding '${enc}'`);
188 }
189 }
190
191 static ToBase64(buffer) {
192 const buf = PrepareBuffer(buffer);
193
194 if (typeof btoa !== "undefined") {
195 const binary = this.ToString(buf, "binary");
196 return btoa(binary);
197 } else {
198 return Buffer.from(buf).toString("base64");
199 }
200 }
201
202 static FromBase64(base64Text) {
203 base64Text = base64Text.replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "").replace(/\s/g, "");
204
205 if (typeof atob !== "undefined") {
206 return this.FromBinary(atob(base64Text));
207 } else {
208 return new Uint8Array(Buffer.from(base64Text, "base64")).buffer;
209 }
210 }
211
212 static FromBase64Url(base64url) {
213 return this.FromBase64(this.Base64Padding(base64url.replace(/\-/g, "+").replace(/\_/g, "/")));
214 }
215
216 static ToBase64Url(data) {
217 return this.ToBase64(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, "");
218 }
219
220 static FromUtf8String(text) {
221 const s = unescape(encodeURIComponent(text));
222 const uintArray = new Uint8Array(s.length);
223
224 for (let i = 0; i < s.length; i++) {
225 uintArray[i] = s.charCodeAt(i);
226 }
227
228 return uintArray.buffer;
229 }
230
231 static ToUtf8String(buffer) {
232 const buf = PrepareBuffer(buffer);
233 const encodedString = String.fromCharCode.apply(null, buf);
234 const decodedString = decodeURIComponent(escape(encodedString));
235 return decodedString;
236 }
237
238 static FromBinary(text) {
239 const stringLength = text.length;
240 const resultView = new Uint8Array(stringLength);
241
242 for (let i = 0; i < stringLength; i++) {
243 resultView[i] = text.charCodeAt(i);
244 }
245
246 return resultView.buffer;
247 }
248
249 static ToBinary(buffer) {
250 const buf = PrepareBuffer(buffer);
251 let resultString = "";
252 const len = buf.length;
253
254 for (let i = 0; i < len; i++) {
255 resultString = resultString + String.fromCharCode(buf[i]);
256 }
257
258 return resultString;
259 }
260
261 static ToHex(buffer) {
262 const buf = PrepareBuffer(buffer);
263 const splitter = "";
264 const res = [];
265 const len = buf.length;
266
267 for (let i = 0; i < len; i++) {
268 const char = buf[i].toString(16);
269 res.push(char.length === 1 ? "0" + char : char);
270 }
271
272 return res.join(splitter);
273 }
274
275 static FromHex(hexString) {
276 const res = new Uint8Array(hexString.length / 2);
277
278 for (let i = 0; i < hexString.length; i = i + 2) {
279 const c = hexString.slice(i, i + 2);
280 res[i / 2] = parseInt(c, 16);
281 }
282
283 return res.buffer;
284 }
285
286 static Base64Padding(base64) {
287 const padCount = 4 - base64.length % 4;
288
289 if (padCount < 4) {
290 for (let i = 0; i < padCount; i++) {
291 base64 += "=";
292 }
293 }
294
295 return base64;
296 }
297
298 }
299 /**
300 * Copyright (c) 2019, Peculiar Ventures, All rights reserved.
301 */
302
303
304 class CryptoError extends Error {}
305
306 class AlgorithmError extends CryptoError {}
307
308 class UnsupportedOperationError extends CryptoError {
309 constructor(methodName) {
310 super(`Unsupported operation: ${methodName ? `${methodName}` : ""}`);
311 }
312
313 }
314
315 class OperationError extends CryptoError {}
316
317 class RequiredPropertyError extends CryptoError {
318 constructor(propName) {
319 super(`${propName}: Missing required property`);
320 }
321
322 }
323
324 class BufferSourceConverter {
325 static toArrayBuffer(data) {
326 if (data instanceof ArrayBuffer) {
327 return data;
328 }
329
330 if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
331 return new Uint8Array(data);
332 }
333
334 if (ArrayBuffer.isView(data)) {
335 return data.buffer;
336 }
337
338 throw new TypeError("The provided value is not of type '(ArrayBuffer or ArrayBufferView)'");
339 }
340
341 static toUint8Array(data) {
342 return new Uint8Array(this.toArrayBuffer(data));
343 }
344
345 static isBufferSource(data) {
346 return ArrayBuffer.isView(data) || data instanceof ArrayBuffer;
347 }
348
349 }
350
351 function isJWK(data) {
352 return typeof data === "object" && "kty" in data;
353 }
354
355 class ProviderCrypto {
356 digest(algorithm, data) {
357 return __awaiter(this, arguments, void 0, function* () {
358 this.checkDigest.apply(this, arguments);
359 return this.onDigest.apply(this, arguments);
360 });
361 }
362
363 checkDigest(algorithm, data) {
364 this.checkAlgorithmName(algorithm);
365 }
366
367 onDigest(algorithm, data) {
368 return __awaiter(this, void 0, void 0, function* () {
369 throw new UnsupportedOperationError("digest");
370 });
371 }
372
373 generateKey(algorithm, extractable, keyUsages) {
374 return __awaiter(this, arguments, void 0, function* () {
375 this.checkGenerateKey.apply(this, arguments);
376 return this.onGenerateKey.apply(this, arguments);
377 });
378 }
379
380 checkGenerateKey(algorithm, extractable, keyUsages) {
381 this.checkAlgorithmName(algorithm);
382 this.checkGenerateKeyParams(algorithm);
383
384 if (!(keyUsages && keyUsages.length)) {
385 throw new TypeError(`Usages cannot be empty when creating a key.`);
386 }
387
388 let allowedUsages;
389
390 if (Array.isArray(this.usages)) {
391 allowedUsages = this.usages;
392 } else {
393 allowedUsages = this.usages.privateKey.concat(this.usages.publicKey);
394 }
395
396 this.checkKeyUsages(keyUsages, allowedUsages);
397 }
398
399 checkGenerateKeyParams(algorithm) {}
400
401 onGenerateKey(algorithm, extractable, keyUsages) {
402 return __awaiter(this, void 0, void 0, function* () {
403 throw new UnsupportedOperationError("generateKey");
404 });
405 }
406
407 sign(algorithm, key, data) {
408 return __awaiter(this, arguments, void 0, function* () {
409 this.checkSign.apply(this, arguments);
410 return this.onSign.apply(this, arguments);
411 });
412 }
413
414 checkSign(algorithm, key, data) {
415 this.checkAlgorithmName(algorithm);
416 this.checkAlgorithmParams(algorithm);
417 this.checkCryptoKey(key, "sign");
418 }
419
420 onSign(algorithm, key, data) {
421 return __awaiter(this, void 0, void 0, function* () {
422 throw new UnsupportedOperationError("sign");
423 });
424 }
425
426 verify(algorithm, key, signature, data) {
427 return __awaiter(this, arguments, void 0, function* () {
428 this.checkVerify.apply(this, arguments);
429 return this.onVerify.apply(this, arguments);
430 });
431 }
432
433 checkVerify(algorithm, key, signature, data) {
434 this.checkAlgorithmName(algorithm);
435 this.checkAlgorithmParams(algorithm);
436 this.checkCryptoKey(key, "verify");
437 }
438
439 onVerify(algorithm, key, signature, data) {
440 return __awaiter(this, void 0, void 0, function* () {
441 throw new UnsupportedOperationError("verify");
442 });
443 }
444
445 encrypt(algorithm, key, data, options) {
446 return __awaiter(this, arguments, void 0, function* () {
447 this.checkEncrypt.apply(this, arguments);
448 return this.onEncrypt.apply(this, arguments);
449 });
450 }
451
452 checkEncrypt(algorithm, key, data, options = {}) {
453 this.checkAlgorithmName(algorithm);
454 this.checkAlgorithmParams(algorithm);
455 this.checkCryptoKey(key, options.keyUsage ? "encrypt" : void 0);
456 }
457
458 onEncrypt(algorithm, key, data) {
459 return __awaiter(this, void 0, void 0, function* () {
460 throw new UnsupportedOperationError("encrypt");
461 });
462 }
463
464 decrypt(algorithm, key, data, options) {
465 return __awaiter(this, arguments, void 0, function* () {
466 this.checkDecrypt.apply(this, arguments);
467 return this.onDecrypt.apply(this, arguments);
468 });
469 }
470
471 checkDecrypt(algorithm, key, data, options = {}) {
472 this.checkAlgorithmName(algorithm);
473 this.checkAlgorithmParams(algorithm);
474 this.checkCryptoKey(key, options.keyUsage ? "decrypt" : void 0);
475 }
476
477 onDecrypt(algorithm, key, data) {
478 return __awaiter(this, void 0, void 0, function* () {
479 throw new UnsupportedOperationError("decrypt");
480 });
481 }
482
483 deriveBits(algorithm, baseKey, length, options) {
484 return __awaiter(this, arguments, void 0, function* () {
485 this.checkDeriveBits.apply(this, arguments);
486 return this.onDeriveBits.apply(this, arguments);
487 });
488 }
489
490 checkDeriveBits(algorithm, baseKey, length, options = {}) {
491 this.checkAlgorithmName(algorithm);
492 this.checkAlgorithmParams(algorithm);
493 this.checkCryptoKey(baseKey, options.keyUsage ? "deriveBits" : void 0);
494
495 if (length % 8 !== 0) {
496 throw new OperationError("length: Is not multiple of 8");
497 }
498 }
499
500 onDeriveBits(algorithm, baseKey, length) {
501 return __awaiter(this, void 0, void 0, function* () {
502 throw new UnsupportedOperationError("deriveBits");
503 });
504 }
505
506 exportKey(format, key) {
507 return __awaiter(this, arguments, void 0, function* () {
508 this.checkExportKey.apply(this, arguments);
509 return this.onExportKey.apply(this, arguments);
510 });
511 }
512
513 checkExportKey(format, key) {
514 this.checkKeyFormat(format);
515 this.checkCryptoKey(key);
516
517 if (!key.extractable) {
518 throw new CryptoError("key: Is not extractable");
519 }
520 }
521
522 onExportKey(format, key) {
523 return __awaiter(this, void 0, void 0, function* () {
524 throw new UnsupportedOperationError("exportKey");
525 });
526 }
527
528 importKey(format, keyData, algorithm, extractable, keyUsages) {
529 return __awaiter(this, arguments, void 0, function* () {
530 this.checkImportKey.apply(this, arguments);
531 return this.onImportKey.apply(this, arguments);
532 });
533 }
534
535 checkImportKey(format, keyData, algorithm, extractable, keyUsages) {
536 this.checkKeyFormat(format);
537 this.checkKeyData(format, keyData);
538 this.checkAlgorithmName(algorithm);
539 this.checkImportParams(algorithm);
540
541 if (Array.isArray(this.usages)) {
542 this.checkKeyUsages(keyUsages, this.usages);
543 }
544 }
545
546 onImportKey(format, keyData, algorithm, extractable, keyUsages) {
547 return __awaiter(this, void 0, void 0, function* () {
548 throw new UnsupportedOperationError("importKey");
549 });
550 }
551
552 checkAlgorithmName(algorithm) {
553 if (algorithm.name.toLowerCase() !== this.name.toLowerCase()) {
554 throw new AlgorithmError("Unrecognized name");
555 }
556 }
557
558 checkAlgorithmParams(algorithm) {}
559
560 checkDerivedKeyParams(algorithm) {}
561
562 checkKeyUsages(usages, allowed) {
563 for (const usage of usages) {
564 if (allowed.indexOf(usage) === -1) {
565 throw new TypeError("Cannot create a key using the specified key usages");
566 }
567 }
568 }
569
570 checkCryptoKey(key, keyUsage) {
571 this.checkAlgorithmName(key.algorithm);
572
573 if (keyUsage && key.usages.indexOf(keyUsage) === -1) {
574 throw new CryptoError(`key does not match that of operation`);
575 }
576 }
577
578 checkRequiredProperty(data, propName) {
579 if (!(propName in data)) {
580 throw new RequiredPropertyError(propName);
581 }
582 }
583
584 checkHashAlgorithm(algorithm, hashAlgorithms) {
585 for (const item of hashAlgorithms) {
586 if (item.toLowerCase() === algorithm.name.toLowerCase()) {
587 return;
588 }
589 }
590
591 throw new OperationError(`hash: Must be one of ${hashAlgorithms.join(", ")}`);
592 }
593
594 checkImportParams(algorithm) {}
595
596 checkKeyFormat(format) {
597 switch (format) {
598 case "raw":
599 case "pkcs8":
600 case "spki":
601 case "jwk":
602 break;
603
604 default:
605 throw new TypeError("format: Is invalid value. Must be 'jwk', 'raw', 'spki', or 'pkcs8'");
606 }
607 }
608
609 checkKeyData(format, keyData) {
610 if (!keyData) {
611 throw new TypeError("keyData: Cannot be empty on empty on key importing");
612 }
613
614 if (format === "jwk") {
615 if (!isJWK(keyData)) {
616 throw new TypeError("keyData: Is not JsonWebToken");
617 }
618 } else if (!BufferSourceConverter.isBufferSource(keyData)) {
619 throw new TypeError("keyData: Is not ArrayBufferView or ArrrayBuffer");
620 }
621 }
622
623 prepareData(data) {
624 return BufferSourceConverter.toArrayBuffer(data);
625 }
626
627 }
628
629 class AesProvider extends ProviderCrypto {
630 checkGenerateKeyParams(algorithm) {
631 this.checkRequiredProperty(algorithm, "length");
632
633 if (typeof algorithm.length !== "number") {
634 throw new TypeError("length: Is not of type Number");
635 }
636
637 switch (algorithm.length) {
638 case 128:
639 case 192:
640 case 256:
641 break;
642
643 default:
644 throw new TypeError("length: Must be 128, 192, or 256");
645 }
646 }
647
648 checkDerivedKeyParams(algorithm) {
649 this.checkGenerateKeyParams(algorithm);
650 }
651
652 }
653
654 class AesCbcProvider extends AesProvider {
655 constructor() {
656 super(...arguments);
657 this.name = "AES-CBC";
658 this.usages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"];
659 }
660
661 checkAlgorithmParams(algorithm) {
662 this.checkRequiredProperty(algorithm, "iv");
663
664 if (!(algorithm.iv instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.iv))) {
665 throw new TypeError("iv: Is not of type '(ArrayBuffer or ArrayBufferView)'");
666 }
667
668 if (algorithm.iv.byteLength !== 16) {
669 throw new TypeError("iv: Must have length 16 bytes");
670 }
671 }
672
673 }
674
675 class AesCtrProvider extends AesProvider {
676 constructor() {
677 super(...arguments);
678 this.name = "AES-CTR";
679 this.usages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"];
680 }
681
682 checkAlgorithmParams(algorithm) {
683 this.checkRequiredProperty(algorithm, "counter");
684
685 if (!(algorithm.counter instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.counter))) {
686 throw new TypeError("counter: Is not of type '(ArrayBuffer or ArrayBufferView)'");
687 }
688
689 if (algorithm.counter.byteLength !== 16) {
690 throw new TypeError("iv: Must have length 16 bytes");
691 }
692
693 this.checkRequiredProperty(algorithm, "length");
694
695 if (typeof algorithm.length !== "number") {
696 throw new TypeError("length: Is not a Number");
697 }
698
699 if (algorithm.length < 1) {
700 throw new OperationError("length: Must be more than 0");
701 }
702 }
703
704 }
705
706 class AesEcbProvider extends AesProvider {
707 constructor() {
708 super(...arguments);
709 this.name = "AES-ECB";
710 this.usages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"];
711 }
712
713 }
714
715 class AesGcmProvider extends AesProvider {
716 constructor() {
717 super(...arguments);
718 this.name = "AES-GCM";
719 this.usages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"];
720 }
721
722 checkAlgorithmParams(algorithm) {
723 this.checkRequiredProperty(algorithm, "iv");
724
725 if (!(algorithm.iv instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.iv))) {
726 throw new TypeError("iv: Is not of type '(ArrayBuffer or ArrayBufferView)'");
727 }
728
729 if (algorithm.iv.byteLength < 1) {
730 throw new OperationError("iv: Must have length more than 0 and less than 2^64 - 1");
731 }
732
733 if (!("tagLength" in algorithm)) {
734 algorithm.tagLength = 128;
735 }
736
737 switch (algorithm.tagLength) {
738 case 32:
739 case 64:
740 case 96:
741 case 104:
742 case 112:
743 case 120:
744 case 128:
745 break;
746
747 default:
748 throw new OperationError("tagLength: Must be one of 32, 64, 96, 104, 112, 120 or 128");
749 }
750 }
751
752 }
753
754 class AesKwProvider extends AesProvider {
755 constructor() {
756 super(...arguments);
757 this.name = "AES-KW";
758 this.usages = ["wrapKey", "unwrapKey"];
759 }
760
761 }
762
763 class DesProvider extends ProviderCrypto {
764 constructor() {
765 super(...arguments);
766 this.usages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"];
767 }
768
769 checkAlgorithmParams(algorithm) {
770 if (this.ivSize) {
771 this.checkRequiredProperty(algorithm, "iv");
772
773 if (!(algorithm.iv instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.iv))) {
774 throw new TypeError("iv: Is not of type '(ArrayBuffer or ArrayBufferView)'");
775 }
776
777 if (algorithm.iv.byteLength !== this.ivSize) {
778 throw new TypeError(`iv: Must have length ${this.ivSize} bytes`);
779 }
780 }
781 }
782
783 checkGenerateKeyParams(algorithm) {
784 this.checkRequiredProperty(algorithm, "length");
785
786 if (typeof algorithm.length !== "number") {
787 throw new TypeError("length: Is not of type Number");
788 }
789
790 if (algorithm.length !== this.keySizeBits) {
791 throw new OperationError(`algorith.length: Must be ${this.keySizeBits}`);
792 }
793 }
794
795 checkDerivedKeyParams(algorithm) {
796 this.checkGenerateKeyParams(algorithm);
797 }
798
799 }
800
801 class RsaProvider extends ProviderCrypto {
802 constructor() {
803 super(...arguments);
804 this.hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"];
805 }
806
807 checkGenerateKeyParams(algorithm) {
808 this.checkRequiredProperty(algorithm, "hash");
809 this.checkHashAlgorithm(algorithm.hash, this.hashAlgorithms);
810 this.checkRequiredProperty(algorithm, "publicExponent");
811
812 if (!(algorithm.publicExponent && algorithm.publicExponent instanceof Uint8Array)) {
813 throw new TypeError("publicExponent: Missing or not a Uint8Array");
814 }
815
816 const publicExponent = Convert.ToBase64(algorithm.publicExponent);
817
818 if (!(publicExponent === "Aw==" || publicExponent === "AQAB")) {
819 throw new TypeError("publicExponent: Must be [3] or [1,0,1]");
820 }
821
822 this.checkRequiredProperty(algorithm, "modulusLength");
823
824 switch (algorithm.modulusLength) {
825 case 1024:
826 case 2048:
827 case 4096:
828 break;
829
830 default:
831 throw new TypeError("modulusLength: Must be 1024, 2048, or 4096");
832 }
833 }
834
835 checkImportParams(algorithm) {
836 this.checkRequiredProperty(algorithm, "hash");
837 this.checkHashAlgorithm(algorithm.hash, this.hashAlgorithms);
838 }
839
840 }
841
842 class RsaSsaProvider extends RsaProvider {
843 constructor() {
844 super(...arguments);
845 this.name = "RSASSA-PKCS1-v1_5";
846 this.usages = {
847 privateKey: ["sign"],
848 publicKey: ["verify"]
849 };
850 }
851
852 }
853
854 class RsaPssProvider extends RsaProvider {
855 constructor() {
856 super(...arguments);
857 this.name = "RSA-PSS";
858 this.usages = {
859 privateKey: ["sign"],
860 publicKey: ["verify"]
861 };
862 }
863
864 checkAlgorithmParams(algorithm) {
865 this.checkRequiredProperty(algorithm, "saltLength");
866
867 if (typeof algorithm.saltLength !== "number") {
868 throw new TypeError("saltLength: Is not a Number");
869 }
870
871 if (algorithm.saltLength < 1) {
872 throw new RangeError("saltLength: Must be more than 0");
873 }
874 }
875
876 }
877
878 class RsaOaepProvider extends RsaProvider {
879 constructor() {
880 super(...arguments);
881 this.name = "RSA-OAEP";
882 this.usages = {
883 privateKey: ["decrypt", "unwrapKey"],
884 publicKey: ["encrypt", "wrapKey"]
885 };
886 }
887
888 checkAlgorithmParams(algorithm) {
889 if (algorithm.label && !(algorithm.label instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.label))) {
890 throw new TypeError("label: Is not of type '(ArrayBuffer or ArrayBufferView)'");
891 }
892 }
893
894 }
895
896 class EllipticProvider extends ProviderCrypto {
897 checkGenerateKeyParams(algorithm) {
898 this.checkRequiredProperty(algorithm, "namedCurve");
899 this.checkNamedCurve(algorithm.namedCurve);
900 }
901
902 checkNamedCurve(namedCurve) {
903 for (const item of this.namedCurves) {
904 if (item.toLowerCase() === namedCurve.toLowerCase()) {
905 return;
906 }
907 }
908
909 throw new OperationError(`namedCurve: Must be one of ${this.namedCurves.join(", ")}`);
910 }
911
912 }
913
914 class EcdsaProvider extends EllipticProvider {
915 constructor() {
916 super(...arguments);
917 this.name = "ECDSA";
918 this.hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"];
919 this.usages = {
920 privateKey: ["sign"],
921 publicKey: ["verify"]
922 };
923 this.namedCurves = ["P-256", "P-384", "P-521", "K-256"];
924 }
925
926 checkAlgorithmParams(algorithm) {
927 this.checkRequiredProperty(algorithm, "hash");
928 this.checkHashAlgorithm(algorithm.hash, this.hashAlgorithms);
929 }
930
931 }
932
933 const KEY_TYPES = ["secret", "private", "public"];
934
935 class CryptoKey {
936 static create(algorithm, type, extractable, usages) {
937 const key = new this();
938 key.algorithm = algorithm;
939 key.type = type;
940 key.extractable = extractable;
941 key.usages = usages;
942 return key;
943 }
944
945 static isKeyType(data) {
946 return KEY_TYPES.indexOf(data) !== -1;
947 }
948
949 }
950
951 class EcdhProvider extends EllipticProvider {
952 constructor() {
953 super(...arguments);
954 this.name = "ECDH";
955 this.usages = {
956 privateKey: ["deriveBits", "deriveKey"],
957 publicKey: []
958 };
959 this.namedCurves = ["P-256", "P-384", "P-521"];
960 }
961
962 checkAlgorithmParams(algorithm) {
963 this.checkRequiredProperty(algorithm, "public");
964
965 if (!(algorithm.public instanceof CryptoKey)) {
966 throw new TypeError("public: Is not a CryptoKey");
967 }
968
969 if (algorithm.public.type !== "public") {
970 throw new OperationError("public: Is not a public key");
971 }
972
973 if (algorithm.public.algorithm.name !== this.name) {
974 throw new OperationError(`public: Is not ${this.name} key`);
975 }
976 }
977
978 }
979
980 class Pbkdf2Provider extends ProviderCrypto {
981 constructor() {
982 super(...arguments);
983 this.name = "PBKDF2";
984 this.hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"];
985 this.usages = ["deriveBits", "deriveKey"];
986 }
987
988 checkAlgorithmParams(algorithm) {
989 this.checkRequiredProperty(algorithm, "hash");
990 this.checkHashAlgorithm(algorithm.hash, this.hashAlgorithms);
991 this.checkRequiredProperty(algorithm, "salt");
992
993 if (!(algorithm.salt instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.salt))) {
994 throw new TypeError("salt: Is not of type '(ArrayBuffer or ArrayBufferView)'");
995 }
996
997 this.checkRequiredProperty(algorithm, "iterations");
998
999 if (typeof algorithm.iterations !== "number") {
1000 throw new TypeError("iterations: Is not a Number");
1001 }
1002
1003 if (algorithm.iterations < 1) {
1004 throw new TypeError("iterations: Is less than 1");
1005 }
1006 }
1007
1008 checkImportKey(format, keyData, algorithm, extractable, keyUsages) {
1009 super.checkImportKey(format, keyData, algorithm, extractable, keyUsages);
1010
1011 if (extractable) {
1012 throw new SyntaxError("extractable: Must be False");
1013 }
1014 }
1015
1016 }
1017
1018 class Crypto {}
1019
1020 class ProviderStorage {
1021 constructor() {
1022 this.items = {};
1023 }
1024
1025 get(algorithmName) {
1026 return this.items[algorithmName.toLowerCase()] || null;
1027 }
1028
1029 set(provider) {
1030 this.items[provider.name.toLowerCase()] = provider;
1031 }
1032
1033 removeAt(algorithmName) {
1034 const provider = this.get(algorithmName.toLowerCase());
1035
1036 if (provider) {
1037 delete this.items[algorithmName];
1038 }
1039
1040 return provider;
1041 }
1042
1043 has(name) {
1044 return !!this.get(name);
1045 }
1046
1047 get length() {
1048 return Object.keys(this.items).length;
1049 }
1050
1051 get algorithms() {
1052 const algorithms = [];
1053
1054 for (const key in this.items) {
1055 const provider = this.items[key];
1056 algorithms.push(provider.name);
1057 }
1058
1059 return algorithms.sort();
1060 }
1061
1062 }
1063
1064 class SubtleCrypto {
1065 constructor() {
1066 this.providers = new ProviderStorage();
1067 }
1068
1069 static isHashedAlgorithm(data) {
1070 return data instanceof Object && "name" in data && "hash" in data;
1071 }
1072
1073 digest(algorithm, data) {
1074 return __awaiter(this, arguments, void 0, function* () {
1075 this.checkRequiredArguments(arguments, 2, "digest");
1076 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1077 const preparedData = BufferSourceConverter.toArrayBuffer(data);
1078 const provider = this.getProvider(preparedAlgorithm.name);
1079 const result = yield provider.digest(preparedAlgorithm, preparedData);
1080 return result;
1081 });
1082 }
1083
1084 generateKey(algorithm, extractable, keyUsages) {
1085 return __awaiter(this, arguments, void 0, function* () {
1086 this.checkRequiredArguments(arguments, 3, "generateKey");
1087 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1088 const provider = this.getProvider(preparedAlgorithm.name);
1089 const result = yield provider.generateKey(Object.assign({}, preparedAlgorithm, {
1090 name: provider.name
1091 }), extractable, keyUsages);
1092 return result;
1093 });
1094 }
1095
1096 sign(algorithm, key, data) {
1097 return __awaiter(this, arguments, void 0, function* () {
1098 this.checkRequiredArguments(arguments, 3, "sign");
1099 this.checkCryptoKey(key);
1100 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1101 const preparedData = BufferSourceConverter.toArrayBuffer(data);
1102 const provider = this.getProvider(preparedAlgorithm.name);
1103 const result = yield provider.sign(Object.assign({}, preparedAlgorithm, {
1104 name: provider.name
1105 }), key, preparedData);
1106 return result;
1107 });
1108 }
1109
1110 verify(algorithm, key, signature, data) {
1111 return __awaiter(this, arguments, void 0, function* () {
1112 this.checkRequiredArguments(arguments, 4, "verify");
1113 this.checkCryptoKey(key);
1114 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1115 const preparedData = BufferSourceConverter.toArrayBuffer(data);
1116 const preparedSignature = BufferSourceConverter.toArrayBuffer(signature);
1117 const provider = this.getProvider(preparedAlgorithm.name);
1118 const result = yield provider.verify(Object.assign({}, preparedAlgorithm, {
1119 name: provider.name
1120 }), key, preparedSignature, preparedData);
1121 return result;
1122 });
1123 }
1124
1125 encrypt(algorithm, key, data) {
1126 return __awaiter(this, arguments, void 0, function* () {
1127 this.checkRequiredArguments(arguments, 3, "encrypt");
1128 this.checkCryptoKey(key);
1129 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1130 const preparedData = BufferSourceConverter.toArrayBuffer(data);
1131 const provider = this.getProvider(preparedAlgorithm.name);
1132 const result = yield provider.encrypt(Object.assign({}, preparedAlgorithm, {
1133 name: provider.name
1134 }), key, preparedData, {
1135 keyUsage: true
1136 });
1137 return result;
1138 });
1139 }
1140
1141 decrypt(algorithm, key, data) {
1142 return __awaiter(this, arguments, void 0, function* () {
1143 this.checkRequiredArguments(arguments, 3, "decrypt");
1144 this.checkCryptoKey(key);
1145 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1146 const preparedData = BufferSourceConverter.toArrayBuffer(data);
1147 const provider = this.getProvider(preparedAlgorithm.name);
1148 const result = yield provider.decrypt(Object.assign({}, preparedAlgorithm, {
1149 name: provider.name
1150 }), key, preparedData, {
1151 keyUsage: true
1152 });
1153 return result;
1154 });
1155 }
1156
1157 deriveBits(algorithm, baseKey, length) {
1158 return __awaiter(this, arguments, void 0, function* () {
1159 this.checkRequiredArguments(arguments, 3, "deriveBits");
1160 this.checkCryptoKey(baseKey);
1161 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1162 const provider = this.getProvider(preparedAlgorithm.name);
1163 const result = yield provider.deriveBits(Object.assign({}, preparedAlgorithm, {
1164 name: provider.name
1165 }), baseKey, length, {
1166 keyUsage: true
1167 });
1168 return result;
1169 });
1170 }
1171
1172 deriveKey(algorithm, baseKey, derivedKeyType, extractable, keyUsages) {
1173 return __awaiter(this, arguments, void 0, function* () {
1174 this.checkRequiredArguments(arguments, 5, "deriveKey");
1175 const preparedDerivedKeyType = this.prepareAlgorithm(derivedKeyType);
1176 const importProvider = this.getProvider(preparedDerivedKeyType.name);
1177 importProvider.checkDerivedKeyParams(preparedDerivedKeyType);
1178 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1179 const provider = this.getProvider(preparedAlgorithm.name);
1180 provider.checkCryptoKey(baseKey, "deriveKey");
1181 const derivedBits = yield provider.deriveBits(Object.assign({}, preparedAlgorithm, {
1182 name: provider.name
1183 }), baseKey, derivedKeyType.length, {
1184 keyUsage: false
1185 });
1186 return this.importKey("raw", derivedBits, derivedKeyType, extractable, keyUsages);
1187 });
1188 }
1189
1190 exportKey(format, key) {
1191 return __awaiter(this, arguments, void 0, function* () {
1192 this.checkRequiredArguments(arguments, 2, "exportKey");
1193 this.checkCryptoKey(key);
1194 const provider = this.getProvider(key.algorithm.name);
1195 const result = yield provider.exportKey(format, key);
1196 return result;
1197 });
1198 }
1199
1200 importKey(format, keyData, algorithm, extractable, keyUsages) {
1201 return __awaiter(this, arguments, void 0, function* () {
1202 this.checkRequiredArguments(arguments, 5, "importKey");
1203 const preparedAlgorithm = this.prepareAlgorithm(algorithm);
1204 const provider = this.getProvider(preparedAlgorithm.name);
1205
1206 if (["pkcs8", "spki", "raw"].indexOf(format) !== -1) {
1207 const preparedData = BufferSourceConverter.toArrayBuffer(keyData);
1208 return provider.importKey(format, preparedData, Object.assign({}, preparedAlgorithm, {
1209 name: provider.name
1210 }), extractable, keyUsages);
1211 } else {
1212 if (!keyData.kty) {
1213 throw new TypeError("keyData: Is not JSON");
1214 }
1215 }
1216
1217 return provider.importKey(format, keyData, Object.assign({}, preparedAlgorithm, {
1218 name: provider.name
1219 }), extractable, keyUsages);
1220 });
1221 }
1222
1223 wrapKey(format, key, wrappingKey, wrapAlgorithm) {
1224 return __awaiter(this, void 0, void 0, function* () {
1225 let keyData = yield this.exportKey(format, key);
1226
1227 if (format === "jwk") {
1228 const json = JSON.stringify(keyData);
1229 keyData = Convert.FromUtf8String(json);
1230 }
1231
1232 const preparedAlgorithm = this.prepareAlgorithm(wrapAlgorithm);
1233 const preparedData = BufferSourceConverter.toArrayBuffer(keyData);
1234 const provider = this.getProvider(preparedAlgorithm.name);
1235 return provider.encrypt(Object.assign({}, preparedAlgorithm, {
1236 name: provider.name
1237 }), wrappingKey, preparedData, {
1238 keyUsage: false
1239 });
1240 });
1241 }
1242
1243 unwrapKey(format, wrappedKey, unwrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages) {
1244 return __awaiter(this, void 0, void 0, function* () {
1245 const preparedAlgorithm = this.prepareAlgorithm(unwrapAlgorithm);
1246 const preparedData = BufferSourceConverter.toArrayBuffer(wrappedKey);
1247 const provider = this.getProvider(preparedAlgorithm.name);
1248 let keyData = yield provider.decrypt(Object.assign({}, preparedAlgorithm, {
1249 name: provider.name
1250 }), unwrappingKey, preparedData, {
1251 keyUsage: false
1252 });
1253
1254 if (format === "jwk") {
1255 try {
1256 keyData = JSON.parse(Convert.ToUtf8String(keyData));
1257 } catch (e) {
1258 const error = new TypeError("wrappedKey: Is not a JSON");
1259 error.internal = e;
1260 throw error;
1261 }
1262 }
1263
1264 return this.importKey(format, keyData, unwrappedKeyAlgorithm, extractable, keyUsages);
1265 });
1266 }
1267
1268 checkRequiredArguments(args, size, methodName) {
1269 if (args.length !== size) {
1270 throw new TypeError(`Failed to execute '${methodName}' on 'SubtleCrypto': ${size} arguments required, but only ${args.length} present`);
1271 }
1272 }
1273
1274 prepareAlgorithm(algorithm) {
1275 if (typeof algorithm === "string") {
1276 return {
1277 name: algorithm
1278 };
1279 }
1280
1281 if (SubtleCrypto.isHashedAlgorithm(algorithm)) {
1282 const preparedAlgorithm = Object.assign({}, algorithm);
1283 preparedAlgorithm.hash = this.prepareAlgorithm(algorithm.hash);
1284 return preparedAlgorithm;
1285 }
1286
1287 return Object.assign({}, algorithm);
1288 }
1289
1290 getProvider(name) {
1291 const provider = this.providers.get(name);
1292
1293 if (!provider) {
1294 throw new AlgorithmError("Unrecognized name");
1295 }
1296
1297 return provider;
1298 }
1299
1300 checkCryptoKey(key) {
1301 if (!(key instanceof CryptoKey)) {
1302 throw new TypeError(`Key is not of type 'CryptoKey'`);
1303 }
1304 }
1305
1306 }
1307
1308 function unwrapExports(x) {
1309 return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x.default : x;
1310 }
1311
1312 function createCommonjsModule(fn, module) {
1313 return module = {
1314 exports: {}
1315 }, fn(module, module.exports), module.exports;
1316 } //**************************************************************************************
1317
1318 /**
1319 * Making UTC date from local date
1320 * @param {Date} date Date to convert from
1321 * @returns {Date}
1322 */
1323
1324
1325 function getUTCDate(date) {
1326 // noinspection NestedFunctionCallJS, MagicNumberJS
1327 return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
1328 } //**************************************************************************************
1329 // noinspection FunctionWithMultipleReturnPointsJS
1330
1331 /**
1332 * Get value for input parameters, or set a default value
1333 * @param {Object} parameters
1334 * @param {string} name
1335 * @param defaultValue
1336 */
1337
1338
1339 function getParametersValue(parameters, name, defaultValue) {
1340 // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
1341 if (parameters instanceof Object === false) return defaultValue; // noinspection NonBlockStatementBodyJS
1342
1343 if (name in parameters) return parameters[name];
1344 return defaultValue;
1345 } //**************************************************************************************
1346
1347 /**
1348 * Converts "ArrayBuffer" into a hexdecimal string
1349 * @param {ArrayBuffer} inputBuffer
1350 * @param {number} [inputOffset=0]
1351 * @param {number} [inputLength=inputBuffer.byteLength]
1352 * @param {boolean} [insertSpace=false]
1353 * @returns {string}
1354 */
1355
1356
1357 function bufferToHexCodes(inputBuffer, inputOffset = 0, inputLength = inputBuffer.byteLength - inputOffset, insertSpace = false) {
1358 let result = "";
1359
1360 for (const item of new Uint8Array(inputBuffer, inputOffset, inputLength)) {
1361 // noinspection ChainedFunctionCallJS
1362 const str = item.toString(16).toUpperCase(); // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
1363
1364 if (str.length === 1) result += "0";
1365 result += str; // noinspection NonBlockStatementBodyJS
1366
1367 if (insertSpace) result += " ";
1368 }
1369
1370 return result.trim();
1371 } //**************************************************************************************
1372 // noinspection JSValidateJSDoc, FunctionWithMultipleReturnPointsJS
1373
1374 /**
1375 * Check input "ArrayBuffer" for common functions
1376 * @param {LocalBaseBlock} baseBlock
1377 * @param {ArrayBuffer} inputBuffer
1378 * @param {number} inputOffset
1379 * @param {number} inputLength
1380 * @returns {boolean}
1381 */
1382
1383
1384 function checkBufferParams(baseBlock, inputBuffer, inputOffset, inputLength) {
1385 // noinspection ConstantOnRightSideOfComparisonJS
1386 if (inputBuffer instanceof ArrayBuffer === false) {
1387 // noinspection JSUndefinedPropertyAssignment
1388 baseBlock.error = "Wrong parameter: inputBuffer must be \"ArrayBuffer\"";
1389 return false;
1390 } // noinspection ConstantOnRightSideOfComparisonJS
1391
1392
1393 if (inputBuffer.byteLength === 0) {
1394 // noinspection JSUndefinedPropertyAssignment
1395 baseBlock.error = "Wrong parameter: inputBuffer has zero length";
1396 return false;
1397 } // noinspection ConstantOnRightSideOfComparisonJS
1398
1399
1400 if (inputOffset < 0) {
1401 // noinspection JSUndefinedPropertyAssignment
1402 baseBlock.error = "Wrong parameter: inputOffset less than zero";
1403 return false;
1404 } // noinspection ConstantOnRightSideOfComparisonJS
1405
1406
1407 if (inputLength < 0) {
1408 // noinspection JSUndefinedPropertyAssignment
1409 baseBlock.error = "Wrong parameter: inputLength less than zero";
1410 return false;
1411 } // noinspection ConstantOnRightSideOfComparisonJS
1412
1413
1414 if (inputBuffer.byteLength - inputOffset - inputLength < 0) {
1415 // noinspection JSUndefinedPropertyAssignment
1416 baseBlock.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
1417 return false;
1418 }
1419
1420 return true;
1421 } //**************************************************************************************
1422 // noinspection FunctionWithMultipleReturnPointsJS
1423
1424 /**
1425 * Convert number from 2^base to 2^10
1426 * @param {Uint8Array} inputBuffer
1427 * @param {number} inputBase
1428 * @returns {number}
1429 */
1430
1431
1432 function utilFromBase(inputBuffer, inputBase) {
1433 let result = 0; // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
1434
1435 if (inputBuffer.length === 1) return inputBuffer[0]; // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
1436
1437 for (let i = inputBuffer.length - 1; i >= 0; i--) result += inputBuffer[inputBuffer.length - 1 - i] * Math.pow(2, inputBase * i);
1438
1439 return result;
1440 } //**************************************************************************************
1441 // noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
1442
1443 /**
1444 * Convert number from 2^10 to 2^base
1445 * @param {!number} value The number to convert
1446 * @param {!number} base The base for 2^base
1447 * @param {number} [reserved=0] Pre-defined number of bytes in output array (-1 = limited by function itself)
1448 * @returns {ArrayBuffer}
1449 */
1450
1451
1452 function utilToBase(value, base, reserved = -1) {
1453 const internalReserved = reserved;
1454 let internalValue = value;
1455 let result = 0;
1456 let biggest = Math.pow(2, base); // noinspection ConstantOnRightSideOfComparisonJS
1457
1458 for (let i = 1; i < 8; i++) {
1459 if (value < biggest) {
1460 let retBuf; // noinspection ConstantOnRightSideOfComparisonJS
1461
1462 if (internalReserved < 0) {
1463 retBuf = new ArrayBuffer(i);
1464 result = i;
1465 } else {
1466 // noinspection NonBlockStatementBodyJS
1467 if (internalReserved < i) return new ArrayBuffer(0);
1468 retBuf = new ArrayBuffer(internalReserved);
1469 result = internalReserved;
1470 }
1471
1472 const retView = new Uint8Array(retBuf); // noinspection ConstantOnRightSideOfComparisonJS
1473
1474 for (let j = i - 1; j >= 0; j--) {
1475 const basis = Math.pow(2, j * base);
1476 retView[result - j - 1] = Math.floor(internalValue / basis);
1477 internalValue -= retView[result - j - 1] * basis;
1478 }
1479
1480 return retBuf;
1481 }
1482
1483 biggest *= Math.pow(2, base);
1484 }
1485
1486 return new ArrayBuffer(0);
1487 } //**************************************************************************************
1488 // noinspection FunctionWithMultipleLoopsJS
1489
1490 /**
1491 * Concatenate two ArrayBuffers
1492 * @param {...ArrayBuffer} buffers Set of ArrayBuffer
1493 */
1494
1495
1496 function utilConcatBuf(...buffers) {
1497 //region Initial variables
1498 let outputLength = 0;
1499 let prevLength = 0; //endregion
1500 //region Calculate output length
1501 // noinspection NonBlockStatementBodyJS
1502
1503 for (const buffer of buffers) outputLength += buffer.byteLength; //endregion
1504
1505
1506 const retBuf = new ArrayBuffer(outputLength);
1507 const retView = new Uint8Array(retBuf);
1508
1509 for (const buffer of buffers) {
1510 // noinspection NestedFunctionCallJS
1511 retView.set(new Uint8Array(buffer), prevLength);
1512 prevLength += buffer.byteLength;
1513 }
1514
1515 return retBuf;
1516 } //**************************************************************************************
1517 // noinspection FunctionWithMultipleLoopsJS
1518
1519 /**
1520 * Concatenate two Uint8Array
1521 * @param {...Uint8Array} views Set of Uint8Array
1522 */
1523
1524
1525 function utilConcatView(...views) {
1526 //region Initial variables
1527 let outputLength = 0;
1528 let prevLength = 0; //endregion
1529 //region Calculate output length
1530 // noinspection NonBlockStatementBodyJS
1531
1532 for (const view of views) outputLength += view.length; //endregion
1533
1534
1535 const retBuf = new ArrayBuffer(outputLength);
1536 const retView = new Uint8Array(retBuf);
1537
1538 for (const view of views) {
1539 retView.set(view, prevLength);
1540 prevLength += view.length;
1541 }
1542
1543 return retView;
1544 } //**************************************************************************************
1545 // noinspection FunctionWithMultipleLoopsJS
1546
1547 /**
1548 * Decoding of "two complement" values
1549 * The function must be called in scope of instance of "hexBlock" class ("valueHex" and "warnings" properties must be present)
1550 * @returns {number}
1551 */
1552
1553
1554 function utilDecodeTC() {
1555 const buf = new Uint8Array(this.valueHex); // noinspection ConstantOnRightSideOfComparisonJS
1556
1557 if (this.valueHex.byteLength >= 2) {
1558 //noinspection JSBitwiseOperatorUsage, ConstantOnRightSideOfComparisonJS, LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
1559 const condition1 = buf[0] === 0xFF && buf[1] & 0x80; // noinspection ConstantOnRightSideOfComparisonJS, LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
1560
1561 const condition2 = buf[0] === 0x00 && (buf[1] & 0x80) === 0x00; // noinspection NonBlockStatementBodyJS
1562
1563 if (condition1 || condition2) this.warnings.push("Needlessly long format");
1564 } //region Create big part of the integer
1565
1566
1567 const bigIntBuffer = new ArrayBuffer(this.valueHex.byteLength);
1568 const bigIntView = new Uint8Array(bigIntBuffer); // noinspection NonBlockStatementBodyJS
1569
1570 for (let i = 0; i < this.valueHex.byteLength; i++) bigIntView[i] = 0; // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
1571
1572
1573 bigIntView[0] = buf[0] & 0x80; // mask only the biggest bit
1574
1575 const bigInt = utilFromBase(bigIntView, 8); //endregion
1576 //region Create small part of the integer
1577
1578 const smallIntBuffer = new ArrayBuffer(this.valueHex.byteLength);
1579 const smallIntView = new Uint8Array(smallIntBuffer); // noinspection NonBlockStatementBodyJS
1580
1581 for (let j = 0; j < this.valueHex.byteLength; j++) smallIntView[j] = buf[j]; // noinspection MagicNumberJS
1582
1583
1584 smallIntView[0] &= 0x7F; // mask biggest bit
1585
1586 const smallInt = utilFromBase(smallIntView, 8); //endregion
1587
1588 return smallInt - bigInt;
1589 } //**************************************************************************************
1590 // noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
1591
1592 /**
1593 * Encode integer value to "two complement" format
1594 * @param {number} value Value to encode
1595 * @returns {ArrayBuffer}
1596 */
1597
1598
1599 function utilEncodeTC(value) {
1600 // noinspection ConstantOnRightSideOfComparisonJS, ConditionalExpressionJS
1601 const modValue = value < 0 ? value * -1 : value;
1602 let bigInt = 128; // noinspection ConstantOnRightSideOfComparisonJS
1603
1604 for (let i = 1; i < 8; i++) {
1605 if (modValue <= bigInt) {
1606 // noinspection ConstantOnRightSideOfComparisonJS
1607 if (value < 0) {
1608 const smallInt = bigInt - modValue;
1609 const retBuf = utilToBase(smallInt, 8, i);
1610 const retView = new Uint8Array(retBuf); // noinspection MagicNumberJS
1611
1612 retView[0] |= 0x80;
1613 return retBuf;
1614 }
1615
1616 let retBuf = utilToBase(modValue, 8, i);
1617 let retView = new Uint8Array(retBuf); //noinspection JSBitwiseOperatorUsage, MagicNumberJS, NonShortCircuitBooleanExpressionJS
1618
1619 if (retView[0] & 0x80) {
1620 //noinspection JSCheckFunctionSignatures
1621 const tempBuf = retBuf.slice(0);
1622 const tempView = new Uint8Array(tempBuf);
1623 retBuf = new ArrayBuffer(retBuf.byteLength + 1); // noinspection ReuseOfLocalVariableJS
1624
1625 retView = new Uint8Array(retBuf); // noinspection NonBlockStatementBodyJS
1626
1627 for (let k = 0; k < tempBuf.byteLength; k++) retView[k + 1] = tempView[k]; // noinspection MagicNumberJS
1628
1629
1630 retView[0] = 0x00;
1631 }
1632
1633 return retBuf;
1634 }
1635
1636 bigInt *= Math.pow(2, 8);
1637 }
1638
1639 return new ArrayBuffer(0);
1640 } //**************************************************************************************
1641 // noinspection FunctionWithMultipleReturnPointsJS, ParameterNamingConventionJS
1642
1643 /**
1644 * Compare two array buffers
1645 * @param {!ArrayBuffer} inputBuffer1
1646 * @param {!ArrayBuffer} inputBuffer2
1647 * @returns {boolean}
1648 */
1649
1650
1651 function isEqualBuffer(inputBuffer1, inputBuffer2) {
1652 // noinspection NonBlockStatementBodyJS
1653 if (inputBuffer1.byteLength !== inputBuffer2.byteLength) return false; // noinspection LocalVariableNamingConventionJS
1654
1655 const view1 = new Uint8Array(inputBuffer1); // noinspection LocalVariableNamingConventionJS
1656
1657 const view2 = new Uint8Array(inputBuffer2);
1658
1659 for (let i = 0; i < view1.length; i++) {
1660 // noinspection NonBlockStatementBodyJS
1661 if (view1[i] !== view2[i]) return false;
1662 }
1663
1664 return true;
1665 } //**************************************************************************************
1666 // noinspection FunctionWithMultipleReturnPointsJS
1667
1668 /**
1669 * Pad input number with leade "0" if needed
1670 * @returns {string}
1671 * @param {number} inputNumber
1672 * @param {number} fullLength
1673 */
1674
1675
1676 function padNumber(inputNumber, fullLength) {
1677 const str = inputNumber.toString(10); // noinspection NonBlockStatementBodyJS
1678
1679 if (fullLength < str.length) return "";
1680 const dif = fullLength - str.length;
1681 const padding = new Array(dif); // noinspection NonBlockStatementBodyJS
1682
1683 for (let i = 0; i < dif; i++) padding[i] = "0";
1684
1685 const paddingString = padding.join("");
1686 return paddingString.concat(str);
1687 } //**************************************************************************************
1688
1689
1690 const base64Template = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
1691 const base64UrlTemplate = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="; //**************************************************************************************
1692 // noinspection FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionTooLongJS, FunctionNamingConventionJS
1693
1694 /**
1695 * Encode string into BASE64 (or "base64url")
1696 * @param {string} input
1697 * @param {boolean} useUrlTemplate If "true" then output would be encoded using "base64url"
1698 * @param {boolean} skipPadding Skip BASE-64 padding or not
1699 * @param {boolean} skipLeadingZeros Skip leading zeros in input data or not
1700 * @returns {string}
1701 */
1702
1703 function toBase64(input, useUrlTemplate = false, skipPadding = false, skipLeadingZeros = false) {
1704 let i = 0; // noinspection LocalVariableNamingConventionJS
1705
1706 let flag1 = 0; // noinspection LocalVariableNamingConventionJS
1707
1708 let flag2 = 0;
1709 let output = ""; // noinspection ConditionalExpressionJS
1710
1711 const template = useUrlTemplate ? base64UrlTemplate : base64Template;
1712
1713 if (skipLeadingZeros) {
1714 let nonZeroPosition = 0;
1715
1716 for (let i = 0; i < input.length; i++) {
1717 // noinspection ConstantOnRightSideOfComparisonJS
1718 if (input.charCodeAt(i) !== 0) {
1719 nonZeroPosition = i; // noinspection BreakStatementJS
1720
1721 break;
1722 }
1723 } // noinspection AssignmentToFunctionParameterJS
1724
1725
1726 input = input.slice(nonZeroPosition);
1727 }
1728
1729 while (i < input.length) {
1730 // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
1731 const chr1 = input.charCodeAt(i++); // noinspection NonBlockStatementBodyJS
1732
1733 if (i >= input.length) flag1 = 1; // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
1734
1735 const chr2 = input.charCodeAt(i++); // noinspection NonBlockStatementBodyJS
1736
1737 if (i >= input.length) flag2 = 1; // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
1738
1739 const chr3 = input.charCodeAt(i++); // noinspection LocalVariableNamingConventionJS
1740
1741 const enc1 = chr1 >> 2; // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
1742
1743 const enc2 = (chr1 & 0x03) << 4 | chr2 >> 4; // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
1744
1745 let enc3 = (chr2 & 0x0F) << 2 | chr3 >> 6; // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
1746
1747 let enc4 = chr3 & 0x3F; // noinspection ConstantOnRightSideOfComparisonJS
1748
1749 if (flag1 === 1) {
1750 // noinspection NestedAssignmentJS, AssignmentResultUsedJS, MagicNumberJS
1751 enc3 = enc4 = 64;
1752 } else {
1753 // noinspection ConstantOnRightSideOfComparisonJS
1754 if (flag2 === 1) {
1755 // noinspection MagicNumberJS
1756 enc4 = 64;
1757 }
1758 } // noinspection NonBlockStatementBodyJS
1759
1760
1761 if (skipPadding) {
1762 // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
1763 if (enc3 === 64) output += `${template.charAt(enc1)}${template.charAt(enc2)}`;else {
1764 // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
1765 if (enc4 === 64) output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}`;else output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}${template.charAt(enc4)}`;
1766 }
1767 } else output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}${template.charAt(enc4)}`;
1768 }
1769
1770 return output;
1771 } //**************************************************************************************
1772 // noinspection FunctionWithMoreThanThreeNegationsJS, FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionNamingConventionJS
1773
1774 /**
1775 * Decode string from BASE64 (or "base64url")
1776 * @param {string} input
1777 * @param {boolean} [useUrlTemplate=false] If "true" then output would be encoded using "base64url"
1778 * @param {boolean} [cutTailZeros=false] If "true" then cut tailing zeroz from function result
1779 * @returns {string}
1780 */
1781
1782
1783 function fromBase64(input, useUrlTemplate = false, cutTailZeros = false) {
1784 // noinspection ConditionalExpressionJS
1785 const template = useUrlTemplate ? base64UrlTemplate : base64Template; //region Aux functions
1786 // noinspection FunctionWithMultipleReturnPointsJS, NestedFunctionJS
1787
1788 function indexof(toSearch) {
1789 // noinspection ConstantOnRightSideOfComparisonJS, MagicNumberJS
1790 for (let i = 0; i < 64; i++) {
1791 // noinspection NonBlockStatementBodyJS
1792 if (template.charAt(i) === toSearch) return i;
1793 } // noinspection MagicNumberJS
1794
1795
1796 return 64;
1797 } // noinspection NestedFunctionJS
1798
1799
1800 function test(incoming) {
1801 // noinspection ConstantOnRightSideOfComparisonJS, ConditionalExpressionJS, MagicNumberJS
1802 return incoming === 64 ? 0x00 : incoming;
1803 } //endregion
1804
1805
1806 let i = 0;
1807 let output = "";
1808
1809 while (i < input.length) {
1810 // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
1811 const enc1 = indexof(input.charAt(i++)); // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
1812
1813 const enc2 = i >= input.length ? 0x00 : indexof(input.charAt(i++)); // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
1814
1815 const enc3 = i >= input.length ? 0x00 : indexof(input.charAt(i++)); // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
1816
1817 const enc4 = i >= input.length ? 0x00 : indexof(input.charAt(i++)); // noinspection LocalVariableNamingConventionJS, NonShortCircuitBooleanExpressionJS
1818
1819 const chr1 = test(enc1) << 2 | test(enc2) >> 4; // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
1820
1821 const chr2 = (test(enc2) & 0x0F) << 4 | test(enc3) >> 2; // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
1822
1823 const chr3 = (test(enc3) & 0x03) << 6 | test(enc4);
1824 output += String.fromCharCode(chr1); // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
1825
1826 if (enc3 !== 64) output += String.fromCharCode(chr2); // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
1827
1828 if (enc4 !== 64) output += String.fromCharCode(chr3);
1829 }
1830
1831 if (cutTailZeros) {
1832 const outputLength = output.length;
1833 let nonZeroStart = -1; // noinspection ConstantOnRightSideOfComparisonJS
1834
1835 for (let i = outputLength - 1; i >= 0; i--) {
1836 // noinspection ConstantOnRightSideOfComparisonJS
1837 if (output.charCodeAt(i) !== 0) {
1838 nonZeroStart = i; // noinspection BreakStatementJS
1839
1840 break;
1841 }
1842 } // noinspection NonBlockStatementBodyJS, NegatedIfStatementJS
1843
1844
1845 if (nonZeroStart !== -1) output = output.slice(0, nonZeroStart + 1);else output = "";
1846 }
1847
1848 return output;
1849 } //**************************************************************************************
1850
1851
1852 function arrayBufferToString(buffer) {
1853 let resultString = "";
1854 const view = new Uint8Array(buffer); // noinspection NonBlockStatementBodyJS
1855
1856 for (const element of view) resultString += String.fromCharCode(element);
1857
1858 return resultString;
1859 } //**************************************************************************************
1860
1861
1862 function stringToArrayBuffer(str) {
1863 const stringLength = str.length;
1864 const resultBuffer = new ArrayBuffer(stringLength);
1865 const resultView = new Uint8Array(resultBuffer); // noinspection NonBlockStatementBodyJS
1866
1867 for (let i = 0; i < stringLength; i++) resultView[i] = str.charCodeAt(i);
1868
1869 return resultBuffer;
1870 } //**************************************************************************************
1871
1872
1873 const log2 = Math.log(2); //**************************************************************************************
1874 // noinspection FunctionNamingConventionJS
1875
1876 /**
1877 * Get nearest to input length power of 2
1878 * @param {number} length Current length of existing array
1879 * @returns {number}
1880 */
1881
1882 function nearestPowerOf2(length) {
1883 const base = Math.log(length) / log2;
1884 const floor = Math.floor(base);
1885 const round = Math.round(base); // noinspection ConditionalExpressionJS
1886
1887 return floor === round ? floor : round;
1888 } //**************************************************************************************
1889
1890 /**
1891 * Delete properties by name from specified object
1892 * @param {Object} object Object to delete properties from
1893 * @param {Array.<string>} propsArray Array of properties names
1894 */
1895
1896
1897 function clearProps(object, propsArray) {
1898 for (const prop of propsArray) delete object[prop];
1899 } //**************************************************************************************
1900
1901
1902 var utils =
1903 /*#__PURE__*/
1904 Object.freeze({
1905 getUTCDate: getUTCDate,
1906 getParametersValue: getParametersValue,
1907 bufferToHexCodes: bufferToHexCodes,
1908 checkBufferParams: checkBufferParams,
1909 utilFromBase: utilFromBase,
1910 utilToBase: utilToBase,
1911 utilConcatBuf: utilConcatBuf,
1912 utilConcatView: utilConcatView,
1913 utilDecodeTC: utilDecodeTC,
1914 utilEncodeTC: utilEncodeTC,
1915 isEqualBuffer: isEqualBuffer,
1916 padNumber: padNumber,
1917 toBase64: toBase64,
1918 fromBase64: fromBase64,
1919 arrayBufferToString: arrayBufferToString,
1920 stringToArrayBuffer: stringToArrayBuffer,
1921 nearestPowerOf2: nearestPowerOf2,
1922 clearProps: clearProps
1923 });
1924 var asn1 = createCommonjsModule(function (module, exports) {
1925 Object.defineProperty(exports, "__esModule", {
1926 value: true
1927 });
1928 exports.RawData = exports.Repeated = exports.Any = exports.Choice = exports.TIME = exports.Duration = exports.DateTime = exports.TimeOfDay = exports.DATE = exports.GeneralizedTime = exports.UTCTime = exports.CharacterString = exports.GeneralString = exports.VisibleString = exports.GraphicString = exports.IA5String = exports.VideotexString = exports.TeletexString = exports.PrintableString = exports.NumericString = exports.UniversalString = exports.BmpString = exports.Utf8String = exports.ObjectIdentifier = exports.Enumerated = exports.Integer = exports.BitString = exports.OctetString = exports.Null = exports.Set = exports.Sequence = exports.Boolean = exports.EndOfContent = exports.Constructed = exports.Primitive = exports.BaseBlock = undefined;
1929 exports.fromBER = fromBER;
1930 exports.compareSchema = compareSchema;
1931 exports.verifySchema = verifySchema;
1932 exports.fromJSON = fromJSON; //**************************************************************************************
1933 //region Declaration of global variables
1934 //**************************************************************************************
1935
1936 const powers2 = [new Uint8Array([1])];
1937 /* eslint-disable indent */
1938
1939 /*
1940 * Copyright (c) 2016-2018, Peculiar Ventures
1941 * All rights reserved.
1942 *
1943 * Author 2016-2018, Yury Strozhevsky <www.strozhevsky.com>.
1944 *
1945 * Redistribution and use in source and binary forms, with or without modification,
1946 * are permitted provided that the following conditions are met:
1947 *
1948 * 1. Redistributions of source code must retain the above copyright notice,
1949 * this list of conditions and the following disclaimer.
1950 *
1951 * 2. Redistributions in binary form must reproduce the above copyright notice,
1952 * this list of conditions and the following disclaimer in the documentation
1953 * and/or other materials provided with the distribution.
1954 *
1955 * 3. Neither the name of the copyright holder nor the names of its contributors
1956 * may be used to endorse or promote products derived from this software without
1957 * specific prior written permission.
1958 *
1959 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1960 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1961 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1962 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
1963 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1964 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1965 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
1966 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1967 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
1968 * OF SUCH DAMAGE.
1969 *
1970 */
1971 //**************************************************************************************
1972
1973 const digitsString = "0123456789"; //**************************************************************************************
1974 //endregion
1975 //**************************************************************************************
1976 //region Declaration for "LocalBaseBlock" class
1977 //**************************************************************************************
1978
1979 /**
1980 * Class used as a base block for all remaining ASN.1 classes
1981 * @typedef LocalBaseBlock
1982 * @interface
1983 * @property {number} blockLength
1984 * @property {string} error
1985 * @property {Array.<string>} warnings
1986 * @property {ArrayBuffer} valueBeforeDecode
1987 */
1988
1989 class LocalBaseBlock {
1990 //**********************************************************************************
1991
1992 /**
1993 * Constructor for "LocalBaseBlock" class
1994 * @param {Object} [parameters={}]
1995 * @property {ArrayBuffer} [valueBeforeDecode]
1996 */
1997 constructor(parameters = {}) {
1998 /**
1999 * @type {number} blockLength
2000 */
2001 this.blockLength = (0, utils.getParametersValue)(parameters, "blockLength", 0);
2002 /**
2003 * @type {string} error
2004 */
2005
2006 this.error = (0, utils.getParametersValue)(parameters, "error", "");
2007 /**
2008 * @type {Array.<string>} warnings
2009 */
2010
2011 this.warnings = (0, utils.getParametersValue)(parameters, "warnings", []); //noinspection JSCheckFunctionSignatures
2012
2013 /**
2014 * @type {ArrayBuffer} valueBeforeDecode
2015 */
2016
2017 if ("valueBeforeDecode" in parameters) this.valueBeforeDecode = parameters.valueBeforeDecode.slice(0);else this.valueBeforeDecode = new ArrayBuffer(0);
2018 } //**********************************************************************************
2019
2020 /**
2021 * Aux function, need to get a block name. Need to have it here for inhiritence
2022 * @returns {string}
2023 */
2024
2025
2026 static blockName() {
2027 return "baseBlock";
2028 } //**********************************************************************************
2029
2030 /**
2031 * Convertion for the block to JSON object
2032 * @returns {{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
2033 */
2034
2035
2036 toJSON() {
2037 return {
2038 blockName: this.constructor.blockName(),
2039 blockLength: this.blockLength,
2040 error: this.error,
2041 warnings: this.warnings,
2042 valueBeforeDecode: (0, utils.bufferToHexCodes)(this.valueBeforeDecode, 0, this.valueBeforeDecode.byteLength)
2043 };
2044 } //**********************************************************************************
2045
2046
2047 } //**************************************************************************************
2048 //endregion
2049 //**************************************************************************************
2050 //region Description for "LocalHexBlock" class
2051 //**************************************************************************************
2052
2053 /**
2054 * Class used as a base block for all remaining ASN.1 classes
2055 * @extends LocalBaseBlock
2056 * @typedef LocalHexBlock
2057 * @property {number} blockLength
2058 * @property {string} error
2059 * @property {Array.<string>} warnings
2060 * @property {ArrayBuffer} valueBeforeDecode
2061 * @property {boolean} isHexOnly
2062 * @property {ArrayBuffer} valueHex
2063 */
2064 //noinspection JSUnusedLocalSymbols
2065
2066
2067 const LocalHexBlock = BaseClass => class LocalHexBlockMixin extends BaseClass {
2068 //**********************************************************************************
2069 //noinspection JSUnusedGlobalSymbols
2070
2071 /**
2072 * Constructor for "LocalHexBlock" class
2073 * @param {Object} [parameters={}]
2074 * @property {ArrayBuffer} [valueHex]
2075 */
2076 constructor(parameters = {}) {
2077 super(parameters);
2078 /**
2079 * @type {boolean}
2080 */
2081
2082 this.isHexOnly = (0, utils.getParametersValue)(parameters, "isHexOnly", false);
2083 /**
2084 * @type {ArrayBuffer}
2085 */
2086
2087 if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else this.valueHex = new ArrayBuffer(0);
2088 } //**********************************************************************************
2089
2090 /**
2091 * Aux function, need to get a block name. Need to have it here for inhiritence
2092 * @returns {string}
2093 */
2094
2095
2096 static blockName() {
2097 return "hexBlock";
2098 } //**********************************************************************************
2099
2100 /**
2101 * Base function for converting block from BER encoded array of bytes
2102 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
2103 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
2104 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
2105 * @returns {number} Offset after least decoded byte
2106 */
2107
2108
2109 fromBER(inputBuffer, inputOffset, inputLength) {
2110 //region Basic check for parameters
2111 //noinspection JSCheckFunctionSignatures
2112 if ((0, utils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
2113 //region Getting Uint8Array from ArrayBuffer
2114
2115 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
2116 //region Initial checks
2117
2118 if (intBuffer.length === 0) {
2119 this.warnings.push("Zero buffer length");
2120 return inputOffset;
2121 } //endregion
2122 //region Copy input buffer to internal buffer
2123
2124
2125 this.valueHex = inputBuffer.slice(inputOffset, inputOffset + inputLength); //endregion
2126
2127 this.blockLength = inputLength;
2128 return inputOffset + inputLength;
2129 } //**********************************************************************************
2130
2131 /**
2132 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
2133 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
2134 * @returns {ArrayBuffer}
2135 */
2136
2137
2138 toBER(sizeOnly = false) {
2139 if (this.isHexOnly !== true) {
2140 this.error = "Flag \"isHexOnly\" is not set, abort";
2141 return new ArrayBuffer(0);
2142 }
2143
2144 if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength); //noinspection JSCheckFunctionSignatures
2145
2146 return this.valueHex.slice(0);
2147 } //**********************************************************************************
2148
2149 /**
2150 * Convertion for the block to JSON object
2151 * @returns {Object}
2152 */
2153
2154
2155 toJSON() {
2156 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
2157
2158 try {
2159 object = super.toJSON();
2160 } catch (ex) {} //endregion
2161
2162
2163 object.blockName = this.constructor.blockName();
2164 object.isHexOnly = this.isHexOnly;
2165 object.valueHex = (0, utils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
2166 return object;
2167 } //**********************************************************************************
2168
2169
2170 }; //**************************************************************************************
2171 //endregion
2172 //**************************************************************************************
2173 //region Declaration of identification block class
2174 //**************************************************************************************
2175
2176
2177 class LocalIdentificationBlock extends LocalHexBlock(LocalBaseBlock) {
2178 //**********************************************************************************
2179
2180 /**
2181 * Constructor for "LocalBaseBlock" class
2182 * @param {Object} [parameters={}]
2183 * @property {Object} [idBlock]
2184 */
2185 constructor(parameters = {}) {
2186 super();
2187
2188 if ("idBlock" in parameters) {
2189 //region Properties from hexBlock class
2190 this.isHexOnly = (0, utils.getParametersValue)(parameters.idBlock, "isHexOnly", false);
2191 this.valueHex = (0, utils.getParametersValue)(parameters.idBlock, "valueHex", new ArrayBuffer(0)); //endregion
2192
2193 this.tagClass = (0, utils.getParametersValue)(parameters.idBlock, "tagClass", -1);
2194 this.tagNumber = (0, utils.getParametersValue)(parameters.idBlock, "tagNumber", -1);
2195 this.isConstructed = (0, utils.getParametersValue)(parameters.idBlock, "isConstructed", false);
2196 } else {
2197 this.tagClass = -1;
2198 this.tagNumber = -1;
2199 this.isConstructed = false;
2200 }
2201 } //**********************************************************************************
2202
2203 /**
2204 * Aux function, need to get a block name. Need to have it here for inhiritence
2205 * @returns {string}
2206 */
2207
2208
2209 static blockName() {
2210 return "identificationBlock";
2211 } //**********************************************************************************
2212
2213 /**
2214 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
2215 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
2216 * @returns {ArrayBuffer}
2217 */
2218
2219
2220 toBER(sizeOnly = false) {
2221 //region Initial variables
2222 let firstOctet = 0;
2223 let retBuf;
2224 let retView; //endregion
2225
2226 switch (this.tagClass) {
2227 case 1:
2228 firstOctet |= 0x00; // UNIVERSAL
2229
2230 break;
2231
2232 case 2:
2233 firstOctet |= 0x40; // APPLICATION
2234
2235 break;
2236
2237 case 3:
2238 firstOctet |= 0x80; // CONTEXT-SPECIFIC
2239
2240 break;
2241
2242 case 4:
2243 firstOctet |= 0xC0; // PRIVATE
2244
2245 break;
2246
2247 default:
2248 this.error = "Unknown tag class";
2249 return new ArrayBuffer(0);
2250 }
2251
2252 if (this.isConstructed) firstOctet |= 0x20;
2253
2254 if (this.tagNumber < 31 && !this.isHexOnly) {
2255 retBuf = new ArrayBuffer(1);
2256 retView = new Uint8Array(retBuf);
2257
2258 if (!sizeOnly) {
2259 let number = this.tagNumber;
2260 number &= 0x1F;
2261 firstOctet |= number;
2262 retView[0] = firstOctet;
2263 }
2264
2265 return retBuf;
2266 }
2267
2268 if (this.isHexOnly === false) {
2269 const encodedBuf = (0, utils.utilToBase)(this.tagNumber, 7);
2270 const encodedView = new Uint8Array(encodedBuf);
2271 const size = encodedBuf.byteLength;
2272 retBuf = new ArrayBuffer(size + 1);
2273 retView = new Uint8Array(retBuf);
2274 retView[0] = firstOctet | 0x1F;
2275
2276 if (!sizeOnly) {
2277 for (let i = 0; i < size - 1; i++) retView[i + 1] = encodedView[i] | 0x80;
2278
2279 retView[size] = encodedView[size - 1];
2280 }
2281
2282 return retBuf;
2283 }
2284
2285 retBuf = new ArrayBuffer(this.valueHex.byteLength + 1);
2286 retView = new Uint8Array(retBuf);
2287 retView[0] = firstOctet | 0x1F;
2288
2289 if (sizeOnly === false) {
2290 const curView = new Uint8Array(this.valueHex);
2291
2292 for (let i = 0; i < curView.length - 1; i++) retView[i + 1] = curView[i] | 0x80;
2293
2294 retView[this.valueHex.byteLength] = curView[curView.length - 1];
2295 }
2296
2297 return retBuf;
2298 } //**********************************************************************************
2299
2300 /**
2301 * Base function for converting block from BER encoded array of bytes
2302 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
2303 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
2304 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
2305 * @returns {number}
2306 */
2307
2308
2309 fromBER(inputBuffer, inputOffset, inputLength) {
2310 //region Basic check for parameters
2311 //noinspection JSCheckFunctionSignatures
2312 if ((0, utils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
2313 //region Getting Uint8Array from ArrayBuffer
2314
2315 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
2316 //region Initial checks
2317
2318 if (intBuffer.length === 0) {
2319 this.error = "Zero buffer length";
2320 return -1;
2321 } //endregion
2322 //region Find tag class
2323
2324
2325 const tagClassMask = intBuffer[0] & 0xC0;
2326
2327 switch (tagClassMask) {
2328 case 0x00:
2329 this.tagClass = 1; // UNIVERSAL
2330
2331 break;
2332
2333 case 0x40:
2334 this.tagClass = 2; // APPLICATION
2335
2336 break;
2337
2338 case 0x80:
2339 this.tagClass = 3; // CONTEXT-SPECIFIC
2340
2341 break;
2342
2343 case 0xC0:
2344 this.tagClass = 4; // PRIVATE
2345
2346 break;
2347
2348 default:
2349 this.error = "Unknown tag class";
2350 return -1;
2351 } //endregion
2352 //region Find it's constructed or not
2353
2354
2355 this.isConstructed = (intBuffer[0] & 0x20) === 0x20; //endregion
2356 //region Find tag number
2357
2358 this.isHexOnly = false;
2359 const tagNumberMask = intBuffer[0] & 0x1F; //region Simple case (tag number < 31)
2360
2361 if (tagNumberMask !== 0x1F) {
2362 this.tagNumber = tagNumberMask;
2363 this.blockLength = 1;
2364 } //endregion
2365 //region Tag number bigger or equal to 31
2366 else {
2367 let count = 1;
2368 this.valueHex = new ArrayBuffer(255);
2369 let tagNumberBufferMaxLength = 255;
2370 let intTagNumberBuffer = new Uint8Array(this.valueHex); //noinspection JSBitwiseOperatorUsage
2371
2372 while (intBuffer[count] & 0x80) {
2373 intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F;
2374 count++;
2375
2376 if (count >= intBuffer.length) {
2377 this.error = "End of input reached before message was fully decoded";
2378 return -1;
2379 } //region In case if tag number length is greater than 255 bytes (rare but possible case)
2380
2381
2382 if (count === tagNumberBufferMaxLength) {
2383 tagNumberBufferMaxLength += 255;
2384 const tempBuffer = new ArrayBuffer(tagNumberBufferMaxLength);
2385 const tempBufferView = new Uint8Array(tempBuffer);
2386
2387 for (let i = 0; i < intTagNumberBuffer.length; i++) tempBufferView[i] = intTagNumberBuffer[i];
2388
2389 this.valueHex = new ArrayBuffer(tagNumberBufferMaxLength);
2390 intTagNumberBuffer = new Uint8Array(this.valueHex);
2391 } //endregion
2392
2393 }
2394
2395 this.blockLength = count + 1;
2396 intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F; // Write last byte to buffer
2397 //region Cut buffer
2398
2399 const tempBuffer = new ArrayBuffer(count);
2400 const tempBufferView = new Uint8Array(tempBuffer);
2401
2402 for (let i = 0; i < count; i++) tempBufferView[i] = intTagNumberBuffer[i];
2403
2404 this.valueHex = new ArrayBuffer(count);
2405 intTagNumberBuffer = new Uint8Array(this.valueHex);
2406 intTagNumberBuffer.set(tempBufferView); //endregion
2407 //region Try to convert long tag number to short form
2408
2409 if (this.blockLength <= 9) this.tagNumber = (0, utils.utilFromBase)(intTagNumberBuffer, 7);else {
2410 this.isHexOnly = true;
2411 this.warnings.push("Tag too long, represented as hex-coded");
2412 } //endregion
2413 } //endregion
2414 //endregion
2415 //region Check if constructed encoding was using for primitive type
2416
2417
2418 if (this.tagClass === 1 && this.isConstructed) {
2419 switch (this.tagNumber) {
2420 case 1: // Boolean
2421
2422 case 2: // REAL
2423
2424 case 5: // Null
2425
2426 case 6: // OBJECT IDENTIFIER
2427
2428 case 9: // REAL
2429
2430 case 14: // Time
2431
2432 case 23:
2433 case 24:
2434 case 31:
2435 case 32:
2436 case 33:
2437 case 34:
2438 this.error = "Constructed encoding used for primitive type";
2439 return -1;
2440
2441 default:
2442 }
2443 } //endregion
2444
2445
2446 return inputOffset + this.blockLength; // Return current offset in input buffer
2447 } //**********************************************************************************
2448
2449 /**
2450 * Convertion for the block to JSON object
2451 * @returns {{blockName: string,
2452 * tagClass: number,
2453 * tagNumber: number,
2454 * isConstructed: boolean,
2455 * isHexOnly: boolean,
2456 * valueHex: ArrayBuffer,
2457 * blockLength: number,
2458 * error: string, warnings: Array.<string>,
2459 * valueBeforeDecode: string}}
2460 */
2461
2462
2463 toJSON() {
2464 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
2465
2466 try {
2467 object = super.toJSON();
2468 } catch (ex) {} //endregion
2469
2470
2471 object.blockName = this.constructor.blockName();
2472 object.tagClass = this.tagClass;
2473 object.tagNumber = this.tagNumber;
2474 object.isConstructed = this.isConstructed;
2475 return object;
2476 } //**********************************************************************************
2477
2478
2479 } //**************************************************************************************
2480 //endregion
2481 //**************************************************************************************
2482 //region Declaration of length block class
2483 //**************************************************************************************
2484
2485
2486 class LocalLengthBlock extends LocalBaseBlock {
2487 //**********************************************************************************
2488
2489 /**
2490 * Constructor for "LocalLengthBlock" class
2491 * @param {Object} [parameters={}]
2492 * @property {Object} [lenBlock]
2493 */
2494 constructor(parameters = {}) {
2495 super();
2496
2497 if ("lenBlock" in parameters) {
2498 this.isIndefiniteForm = (0, utils.getParametersValue)(parameters.lenBlock, "isIndefiniteForm", false);
2499 this.longFormUsed = (0, utils.getParametersValue)(parameters.lenBlock, "longFormUsed", false);
2500 this.length = (0, utils.getParametersValue)(parameters.lenBlock, "length", 0);
2501 } else {
2502 this.isIndefiniteForm = false;
2503 this.longFormUsed = false;
2504 this.length = 0;
2505 }
2506 } //**********************************************************************************
2507
2508 /**
2509 * Aux function, need to get a block name. Need to have it here for inhiritence
2510 * @returns {string}
2511 */
2512
2513
2514 static blockName() {
2515 return "lengthBlock";
2516 } //**********************************************************************************
2517
2518 /**
2519 * Base function for converting block from BER encoded array of bytes
2520 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
2521 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
2522 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
2523 * @returns {number}
2524 */
2525
2526
2527 fromBER(inputBuffer, inputOffset, inputLength) {
2528 //region Basic check for parameters
2529 //noinspection JSCheckFunctionSignatures
2530 if ((0, utils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
2531 //region Getting Uint8Array from ArrayBuffer
2532
2533 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
2534 //region Initial checks
2535
2536 if (intBuffer.length === 0) {
2537 this.error = "Zero buffer length";
2538 return -1;
2539 }
2540
2541 if (intBuffer[0] === 0xFF) {
2542 this.error = "Length block 0xFF is reserved by standard";
2543 return -1;
2544 } //endregion
2545 //region Check for length form type
2546
2547
2548 this.isIndefiniteForm = intBuffer[0] === 0x80; //endregion
2549 //region Stop working in case of indefinite length form
2550
2551 if (this.isIndefiniteForm === true) {
2552 this.blockLength = 1;
2553 return inputOffset + this.blockLength;
2554 } //endregion
2555 //region Check is long form of length encoding using
2556
2557
2558 this.longFormUsed = !!(intBuffer[0] & 0x80); //endregion
2559 //region Stop working in case of short form of length value
2560
2561 if (this.longFormUsed === false) {
2562 this.length = intBuffer[0];
2563 this.blockLength = 1;
2564 return inputOffset + this.blockLength;
2565 } //endregion
2566 //region Calculate length value in case of long form
2567
2568
2569 const count = intBuffer[0] & 0x7F;
2570
2571 if (count > 8) // Too big length value
2572 {
2573 this.error = "Too big integer";
2574 return -1;
2575 }
2576
2577 if (count + 1 > intBuffer.length) {
2578 this.error = "End of input reached before message was fully decoded";
2579 return -1;
2580 }
2581
2582 const lengthBufferView = new Uint8Array(count);
2583
2584 for (let i = 0; i < count; i++) lengthBufferView[i] = intBuffer[i + 1];
2585
2586 if (lengthBufferView[count - 1] === 0x00) this.warnings.push("Needlessly long encoded length");
2587 this.length = (0, utils.utilFromBase)(lengthBufferView, 8);
2588 if (this.longFormUsed && this.length <= 127) this.warnings.push("Unneccesary usage of long length form");
2589 this.blockLength = count + 1; //endregion
2590
2591 return inputOffset + this.blockLength; // Return current offset in input buffer
2592 } //**********************************************************************************
2593
2594 /**
2595 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
2596 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
2597 * @returns {ArrayBuffer}
2598 */
2599
2600
2601 toBER(sizeOnly = false) {
2602 //region Initial variables
2603 let retBuf;
2604 let retView; //endregion
2605
2606 if (this.length > 127) this.longFormUsed = true;
2607
2608 if (this.isIndefiniteForm) {
2609 retBuf = new ArrayBuffer(1);
2610
2611 if (sizeOnly === false) {
2612 retView = new Uint8Array(retBuf);
2613 retView[0] = 0x80;
2614 }
2615
2616 return retBuf;
2617 }
2618
2619 if (this.longFormUsed === true) {
2620 const encodedBuf = (0, utils.utilToBase)(this.length, 8);
2621
2622 if (encodedBuf.byteLength > 127) {
2623 this.error = "Too big length";
2624 return new ArrayBuffer(0);
2625 }
2626
2627 retBuf = new ArrayBuffer(encodedBuf.byteLength + 1);
2628 if (sizeOnly === true) return retBuf;
2629 const encodedView = new Uint8Array(encodedBuf);
2630 retView = new Uint8Array(retBuf);
2631 retView[0] = encodedBuf.byteLength | 0x80;
2632
2633 for (let i = 0; i < encodedBuf.byteLength; i++) retView[i + 1] = encodedView[i];
2634
2635 return retBuf;
2636 }
2637
2638 retBuf = new ArrayBuffer(1);
2639
2640 if (sizeOnly === false) {
2641 retView = new Uint8Array(retBuf);
2642 retView[0] = this.length;
2643 }
2644
2645 return retBuf;
2646 } //**********************************************************************************
2647
2648 /**
2649 * Convertion for the block to JSON object
2650 * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
2651 */
2652
2653
2654 toJSON() {
2655 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
2656
2657 try {
2658 object = super.toJSON();
2659 } catch (ex) {} //endregion
2660
2661
2662 object.blockName = this.constructor.blockName();
2663 object.isIndefiniteForm = this.isIndefiniteForm;
2664 object.longFormUsed = this.longFormUsed;
2665 object.length = this.length;
2666 return object;
2667 } //**********************************************************************************
2668
2669
2670 } //**************************************************************************************
2671 //endregion
2672 //**************************************************************************************
2673 //region Declaration of value block class
2674 //**************************************************************************************
2675
2676
2677 class LocalValueBlock extends LocalBaseBlock {
2678 //**********************************************************************************
2679
2680 /**
2681 * Constructor for "LocalValueBlock" class
2682 * @param {Object} [parameters={}]
2683 */
2684 constructor(parameters = {}) {
2685 super(parameters);
2686 } //**********************************************************************************
2687
2688 /**
2689 * Aux function, need to get a block name. Need to have it here for inhiritence
2690 * @returns {string}
2691 */
2692
2693
2694 static blockName() {
2695 return "valueBlock";
2696 } //**********************************************************************************
2697 //noinspection JSUnusedLocalSymbols,JSUnusedLocalSymbols,JSUnusedLocalSymbols
2698
2699 /**
2700 * Base function for converting block from BER encoded array of bytes
2701 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
2702 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
2703 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
2704 * @returns {number}
2705 */
2706
2707
2708 fromBER(inputBuffer, inputOffset, inputLength) {
2709 //region Throw an exception for a function which needs to be specified in extended classes
2710 throw TypeError("User need to make a specific function in a class which extends \"LocalValueBlock\""); //endregion
2711 } //**********************************************************************************
2712 //noinspection JSUnusedLocalSymbols
2713
2714 /**
2715 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
2716 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
2717 * @returns {ArrayBuffer}
2718 */
2719
2720
2721 toBER(sizeOnly = false) {
2722 //region Throw an exception for a function which needs to be specified in extended classes
2723 throw TypeError("User need to make a specific function in a class which extends \"LocalValueBlock\""); //endregion
2724 } //**********************************************************************************
2725
2726
2727 } //**************************************************************************************
2728 //endregion
2729 //**************************************************************************************
2730 //region Declaration of basic ASN.1 block class
2731 //**************************************************************************************
2732
2733
2734 class BaseBlock extends LocalBaseBlock {
2735 //**********************************************************************************
2736
2737 /**
2738 * Constructor for "BaseBlock" class
2739 * @param {Object} [parameters={}]
2740 * @property {Object} [primitiveSchema]
2741 * @property {string} [name]
2742 * @property {boolean} [optional]
2743 * @param valueBlockType Type of value block
2744 */
2745 constructor(parameters = {}, valueBlockType = LocalValueBlock) {
2746 super(parameters);
2747 if ("name" in parameters) this.name = parameters.name;
2748 if ("optional" in parameters) this.optional = parameters.optional;
2749 if ("primitiveSchema" in parameters) this.primitiveSchema = parameters.primitiveSchema;
2750 this.idBlock = new LocalIdentificationBlock(parameters);
2751 this.lenBlock = new LocalLengthBlock(parameters);
2752 this.valueBlock = new valueBlockType(parameters);
2753 } //**********************************************************************************
2754
2755 /**
2756 * Aux function, need to get a block name. Need to have it here for inhiritence
2757 * @returns {string}
2758 */
2759
2760
2761 static blockName() {
2762 return "BaseBlock";
2763 } //**********************************************************************************
2764
2765 /**
2766 * Base function for converting block from BER encoded array of bytes
2767 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
2768 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
2769 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
2770 * @returns {number}
2771 */
2772
2773
2774 fromBER(inputBuffer, inputOffset, inputLength) {
2775 const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
2776
2777 if (resultOffset === -1) {
2778 this.error = this.valueBlock.error;
2779 return resultOffset;
2780 }
2781
2782 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
2783 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
2784 if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
2785 return resultOffset;
2786 } //**********************************************************************************
2787
2788 /**
2789 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
2790 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
2791 * @returns {ArrayBuffer}
2792 */
2793
2794
2795 toBER(sizeOnly = false) {
2796 let retBuf;
2797 const idBlockBuf = this.idBlock.toBER(sizeOnly);
2798 const valueBlockSizeBuf = this.valueBlock.toBER(true);
2799 this.lenBlock.length = valueBlockSizeBuf.byteLength;
2800 const lenBlockBuf = this.lenBlock.toBER(sizeOnly);
2801 retBuf = (0, utils.utilConcatBuf)(idBlockBuf, lenBlockBuf);
2802 let valueBlockBuf;
2803 if (sizeOnly === false) valueBlockBuf = this.valueBlock.toBER(sizeOnly);else valueBlockBuf = new ArrayBuffer(this.lenBlock.length);
2804 retBuf = (0, utils.utilConcatBuf)(retBuf, valueBlockBuf);
2805
2806 if (this.lenBlock.isIndefiniteForm === true) {
2807 const indefBuf = new ArrayBuffer(2);
2808
2809 if (sizeOnly === false) {
2810 const indefView = new Uint8Array(indefBuf);
2811 indefView[0] = 0x00;
2812 indefView[1] = 0x00;
2813 }
2814
2815 retBuf = (0, utils.utilConcatBuf)(retBuf, indefBuf);
2816 }
2817
2818 return retBuf;
2819 } //**********************************************************************************
2820
2821 /**
2822 * Convertion for the block to JSON object
2823 * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
2824 */
2825
2826
2827 toJSON() {
2828 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
2829
2830 try {
2831 object = super.toJSON();
2832 } catch (ex) {} //endregion
2833
2834
2835 object.idBlock = this.idBlock.toJSON();
2836 object.lenBlock = this.lenBlock.toJSON();
2837 object.valueBlock = this.valueBlock.toJSON();
2838 if ("name" in this) object.name = this.name;
2839 if ("optional" in this) object.optional = this.optional;
2840 if ("primitiveSchema" in this) object.primitiveSchema = this.primitiveSchema.toJSON();
2841 return object;
2842 } //**********************************************************************************
2843
2844
2845 }
2846
2847 exports.BaseBlock = BaseBlock; //**************************************************************************************
2848 //endregion
2849 //**************************************************************************************
2850 //region Declaration of basic block for all PRIMITIVE types
2851 //**************************************************************************************
2852
2853 class LocalPrimitiveValueBlock extends LocalValueBlock {
2854 //**********************************************************************************
2855
2856 /**
2857 * Constructor for "LocalPrimitiveValueBlock" class
2858 * @param {Object} [parameters={}]
2859 * @property {ArrayBuffer} [valueBeforeDecode]
2860 */
2861 constructor(parameters = {}) {
2862 super(parameters); //region Variables from "hexBlock" class
2863
2864 if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else this.valueHex = new ArrayBuffer(0);
2865 this.isHexOnly = (0, utils.getParametersValue)(parameters, "isHexOnly", true); //endregion
2866 } //**********************************************************************************
2867
2868 /**
2869 * Base function for converting block from BER encoded array of bytes
2870 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
2871 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
2872 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
2873 * @returns {number}
2874 */
2875
2876
2877 fromBER(inputBuffer, inputOffset, inputLength) {
2878 //region Basic check for parameters
2879 //noinspection JSCheckFunctionSignatures
2880 if ((0, utils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
2881 //region Getting Uint8Array from ArrayBuffer
2882
2883 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
2884 //region Initial checks
2885
2886 if (intBuffer.length === 0) {
2887 this.warnings.push("Zero buffer length");
2888 return inputOffset;
2889 } //endregion
2890 //region Copy input buffer into internal buffer
2891
2892
2893 this.valueHex = new ArrayBuffer(intBuffer.length);
2894 const valueHexView = new Uint8Array(this.valueHex);
2895
2896 for (let i = 0; i < intBuffer.length; i++) valueHexView[i] = intBuffer[i]; //endregion
2897
2898
2899 this.blockLength = inputLength;
2900 return inputOffset + inputLength;
2901 } //**********************************************************************************
2902 //noinspection JSUnusedLocalSymbols
2903
2904 /**
2905 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
2906 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
2907 * @returns {ArrayBuffer}
2908 */
2909
2910
2911 toBER(sizeOnly = false) {
2912 return this.valueHex.slice(0);
2913 } //**********************************************************************************
2914
2915 /**
2916 * Aux function, need to get a block name. Need to have it here for inhiritence
2917 * @returns {string}
2918 */
2919
2920
2921 static blockName() {
2922 return "PrimitiveValueBlock";
2923 } //**********************************************************************************
2924
2925 /**
2926 * Convertion for the block to JSON object
2927 * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
2928 */
2929
2930
2931 toJSON() {
2932 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
2933
2934 try {
2935 object = super.toJSON();
2936 } catch (ex) {} //endregion
2937
2938
2939 object.valueHex = (0, utils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
2940 object.isHexOnly = this.isHexOnly;
2941 return object;
2942 } //**********************************************************************************
2943
2944
2945 } //**************************************************************************************
2946
2947
2948 class Primitive extends BaseBlock {
2949 //**********************************************************************************
2950
2951 /**
2952 * Constructor for "Primitive" class
2953 * @param {Object} [parameters={}]
2954 * @property {ArrayBuffer} [valueHex]
2955 */
2956 constructor(parameters = {}) {
2957 super(parameters, LocalPrimitiveValueBlock);
2958 this.idBlock.isConstructed = false;
2959 } //**********************************************************************************
2960
2961 /**
2962 * Aux function, need to get a block name. Need to have it here for inhiritence
2963 * @returns {string}
2964 */
2965
2966
2967 static blockName() {
2968 return "PRIMITIVE";
2969 } //**********************************************************************************
2970
2971
2972 }
2973
2974 exports.Primitive = Primitive; //**************************************************************************************
2975 //endregion
2976 //**************************************************************************************
2977 //region Declaration of basic block for all CONSTRUCTED types
2978 //**************************************************************************************
2979
2980 class LocalConstructedValueBlock extends LocalValueBlock {
2981 //**********************************************************************************
2982
2983 /**
2984 * Constructor for "LocalConstructedValueBlock" class
2985 * @param {Object} [parameters={}]
2986 */
2987 constructor(parameters = {}) {
2988 super(parameters);
2989 this.value = (0, utils.getParametersValue)(parameters, "value", []);
2990 this.isIndefiniteForm = (0, utils.getParametersValue)(parameters, "isIndefiniteForm", false);
2991 } //**********************************************************************************
2992
2993 /**
2994 * Base function for converting block from BER encoded array of bytes
2995 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
2996 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
2997 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
2998 * @returns {number}
2999 */
3000
3001
3002 fromBER(inputBuffer, inputOffset, inputLength) {
3003 //region Store initial offset and length
3004 const initialOffset = inputOffset;
3005 const initialLength = inputLength; //endregion
3006 //region Basic check for parameters
3007 //noinspection JSCheckFunctionSignatures
3008
3009 if ((0, utils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
3010 //region Getting Uint8Array from ArrayBuffer
3011
3012 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
3013 //region Initial checks
3014
3015 if (intBuffer.length === 0) {
3016 this.warnings.push("Zero buffer length");
3017 return inputOffset;
3018 } //endregion
3019 //region Aux function
3020
3021
3022 function checkLen(indefiniteLength, length) {
3023 if (indefiniteLength === true) return 1;
3024 return length;
3025 } //endregion
3026
3027
3028 let currentOffset = inputOffset;
3029
3030 while (checkLen(this.isIndefiniteForm, inputLength) > 0) {
3031 const returnObject = LocalFromBER(inputBuffer, currentOffset, inputLength);
3032
3033 if (returnObject.offset === -1) {
3034 this.error = returnObject.result.error;
3035 this.warnings.concat(returnObject.result.warnings);
3036 return -1;
3037 }
3038
3039 currentOffset = returnObject.offset;
3040 this.blockLength += returnObject.result.blockLength;
3041 inputLength -= returnObject.result.blockLength;
3042 this.value.push(returnObject.result);
3043 if (this.isIndefiniteForm === true && returnObject.result.constructor.blockName() === EndOfContent.blockName()) break;
3044 }
3045
3046 if (this.isIndefiniteForm === true) {
3047 if (this.value[this.value.length - 1].constructor.blockName() === EndOfContent.blockName()) this.value.pop();else this.warnings.push("No EndOfContent block encoded");
3048 } //region Copy "inputBuffer" to "valueBeforeDecode"
3049
3050
3051 this.valueBeforeDecode = inputBuffer.slice(initialOffset, initialOffset + initialLength); //endregion
3052
3053 return currentOffset;
3054 } //**********************************************************************************
3055
3056 /**
3057 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
3058 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
3059 * @returns {ArrayBuffer}
3060 */
3061
3062
3063 toBER(sizeOnly = false) {
3064 let retBuf = new ArrayBuffer(0);
3065
3066 for (let i = 0; i < this.value.length; i++) {
3067 const valueBuf = this.value[i].toBER(sizeOnly);
3068 retBuf = (0, utils.utilConcatBuf)(retBuf, valueBuf);
3069 }
3070
3071 return retBuf;
3072 } //**********************************************************************************
3073
3074 /**
3075 * Aux function, need to get a block name. Need to have it here for inhiritence
3076 * @returns {string}
3077 */
3078
3079
3080 static blockName() {
3081 return "ConstructedValueBlock";
3082 } //**********************************************************************************
3083
3084 /**
3085 * Convertion for the block to JSON object
3086 * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
3087 */
3088
3089
3090 toJSON() {
3091 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
3092
3093 try {
3094 object = super.toJSON();
3095 } catch (ex) {} //endregion
3096
3097
3098 object.isIndefiniteForm = this.isIndefiniteForm;
3099 object.value = [];
3100
3101 for (let i = 0; i < this.value.length; i++) object.value.push(this.value[i].toJSON());
3102
3103 return object;
3104 } //**********************************************************************************
3105
3106
3107 } //**************************************************************************************
3108
3109
3110 class Constructed extends BaseBlock {
3111 //**********************************************************************************
3112
3113 /**
3114 * Constructor for "Constructed" class
3115 * @param {Object} [parameters={}]
3116 */
3117 constructor(parameters = {}) {
3118 super(parameters, LocalConstructedValueBlock);
3119 this.idBlock.isConstructed = true;
3120 } //**********************************************************************************
3121
3122 /**
3123 * Aux function, need to get a block name. Need to have it here for inhiritence
3124 * @returns {string}
3125 */
3126
3127
3128 static blockName() {
3129 return "CONSTRUCTED";
3130 } //**********************************************************************************
3131
3132 /**
3133 * Base function for converting block from BER encoded array of bytes
3134 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
3135 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
3136 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3137 * @returns {number}
3138 */
3139
3140
3141 fromBER(inputBuffer, inputOffset, inputLength) {
3142 this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
3143 const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
3144
3145 if (resultOffset === -1) {
3146 this.error = this.valueBlock.error;
3147 return resultOffset;
3148 }
3149
3150 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
3151 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
3152 if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
3153 return resultOffset;
3154 } //**********************************************************************************
3155
3156
3157 }
3158
3159 exports.Constructed = Constructed; //**************************************************************************************
3160 //endregion
3161 //**************************************************************************************
3162 //region Declaration of ASN.1 EndOfContent type class
3163 //**************************************************************************************
3164
3165 class LocalEndOfContentValueBlock extends LocalValueBlock {
3166 //**********************************************************************************
3167
3168 /**
3169 * Constructor for "LocalEndOfContentValueBlock" class
3170 * @param {Object} [parameters={}]
3171 */
3172 constructor(parameters = {}) {
3173 super(parameters);
3174 } //**********************************************************************************
3175 //noinspection JSUnusedLocalSymbols,JSUnusedLocalSymbols
3176
3177 /**
3178 * Base function for converting block from BER encoded array of bytes
3179 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
3180 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
3181 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3182 * @returns {number}
3183 */
3184
3185
3186 fromBER(inputBuffer, inputOffset, inputLength) {
3187 //region There is no "value block" for EndOfContent type and we need to return the same offset
3188 return inputOffset; //endregion
3189 } //**********************************************************************************
3190 //noinspection JSUnusedLocalSymbols
3191
3192 /**
3193 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
3194 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
3195 * @returns {ArrayBuffer}
3196 */
3197
3198
3199 toBER(sizeOnly = false) {
3200 return new ArrayBuffer(0);
3201 } //**********************************************************************************
3202
3203 /**
3204 * Aux function, need to get a block name. Need to have it here for inhiritence
3205 * @returns {string}
3206 */
3207
3208
3209 static blockName() {
3210 return "EndOfContentValueBlock";
3211 } //**********************************************************************************
3212
3213
3214 } //**************************************************************************************
3215
3216
3217 class EndOfContent extends BaseBlock {
3218 //**********************************************************************************
3219 constructor(paramaters = {}) {
3220 super(paramaters, LocalEndOfContentValueBlock);
3221 this.idBlock.tagClass = 1; // UNIVERSAL
3222
3223 this.idBlock.tagNumber = 0; // EndOfContent
3224 } //**********************************************************************************
3225
3226 /**
3227 * Aux function, need to get a block name. Need to have it here for inhiritence
3228 * @returns {string}
3229 */
3230
3231
3232 static blockName() {
3233 return "EndOfContent";
3234 } //**********************************************************************************
3235
3236
3237 }
3238
3239 exports.EndOfContent = EndOfContent; //**************************************************************************************
3240 //endregion
3241 //**************************************************************************************
3242 //region Declaration of ASN.1 Boolean type class
3243 //**************************************************************************************
3244
3245 class LocalBooleanValueBlock extends LocalValueBlock {
3246 //**********************************************************************************
3247
3248 /**
3249 * Constructor for "LocalBooleanValueBlock" class
3250 * @param {Object} [parameters={}]
3251 */
3252 constructor(parameters = {}) {
3253 super(parameters);
3254 this.value = (0, utils.getParametersValue)(parameters, "value", false);
3255 this.isHexOnly = (0, utils.getParametersValue)(parameters, "isHexOnly", false);
3256 if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else {
3257 this.valueHex = new ArrayBuffer(1);
3258
3259 if (this.value === true) {
3260 const view = new Uint8Array(this.valueHex);
3261 view[0] = 0xFF;
3262 }
3263 }
3264 } //**********************************************************************************
3265
3266 /**
3267 * Base function for converting block from BER encoded array of bytes
3268 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
3269 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
3270 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3271 * @returns {number} Offset after least decoded byte
3272 */
3273
3274
3275 fromBER(inputBuffer, inputOffset, inputLength) {
3276 //region Basic check for parameters
3277 //noinspection JSCheckFunctionSignatures
3278 if ((0, utils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
3279 //region Getting Uint8Array from ArrayBuffer
3280
3281 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
3282
3283 if (inputLength > 1) this.warnings.push("Boolean value encoded in more then 1 octet");
3284 this.isHexOnly = true; //region Copy input buffer to internal array
3285
3286 this.valueHex = new ArrayBuffer(intBuffer.length);
3287 const view = new Uint8Array(this.valueHex);
3288
3289 for (let i = 0; i < intBuffer.length; i++) view[i] = intBuffer[i]; //endregion
3290
3291
3292 if (utils.utilDecodeTC.call(this) !== 0) this.value = true;else this.value = false;
3293 this.blockLength = inputLength;
3294 return inputOffset + inputLength;
3295 } //**********************************************************************************
3296 //noinspection JSUnusedLocalSymbols
3297
3298 /**
3299 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
3300 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
3301 * @returns {ArrayBuffer}
3302 */
3303
3304
3305 toBER(sizeOnly = false) {
3306 return this.valueHex;
3307 } //**********************************************************************************
3308
3309 /**
3310 * Aux function, need to get a block name. Need to have it here for inhiritence
3311 * @returns {string}
3312 */
3313
3314
3315 static blockName() {
3316 return "BooleanValueBlock";
3317 } //**********************************************************************************
3318
3319 /**
3320 * Convertion for the block to JSON object
3321 * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
3322 */
3323
3324
3325 toJSON() {
3326 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
3327
3328 try {
3329 object = super.toJSON();
3330 } catch (ex) {} //endregion
3331
3332
3333 object.value = this.value;
3334 object.isHexOnly = this.isHexOnly;
3335 object.valueHex = (0, utils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
3336 return object;
3337 } //**********************************************************************************
3338
3339
3340 } //**************************************************************************************
3341
3342
3343 class Boolean extends BaseBlock {
3344 //**********************************************************************************
3345
3346 /**
3347 * Constructor for "Boolean" class
3348 * @param {Object} [parameters={}]
3349 */
3350 constructor(parameters = {}) {
3351 super(parameters, LocalBooleanValueBlock);
3352 this.idBlock.tagClass = 1; // UNIVERSAL
3353
3354 this.idBlock.tagNumber = 1; // Boolean
3355 } //**********************************************************************************
3356
3357 /**
3358 * Aux function, need to get a block name. Need to have it here for inhiritence
3359 * @returns {string}
3360 */
3361
3362
3363 static blockName() {
3364 return "Boolean";
3365 } //**********************************************************************************
3366
3367
3368 }
3369
3370 exports.Boolean = Boolean; //**************************************************************************************
3371 //endregion
3372 //**************************************************************************************
3373 //region Declaration of ASN.1 Sequence and Set type classes
3374 //**************************************************************************************
3375
3376 class Sequence extends Constructed {
3377 //**********************************************************************************
3378
3379 /**
3380 * Constructor for "Sequence" class
3381 * @param {Object} [parameters={}]
3382 */
3383 constructor(parameters = {}) {
3384 super(parameters);
3385 this.idBlock.tagClass = 1; // UNIVERSAL
3386
3387 this.idBlock.tagNumber = 16; // Sequence
3388 } //**********************************************************************************
3389
3390 /**
3391 * Aux function, need to get a block name. Need to have it here for inhiritence
3392 * @returns {string}
3393 */
3394
3395
3396 static blockName() {
3397 return "Sequence";
3398 } //**********************************************************************************
3399
3400
3401 }
3402
3403 exports.Sequence = Sequence; //**************************************************************************************
3404
3405 class Set extends Constructed {
3406 //**********************************************************************************
3407
3408 /**
3409 * Constructor for "Set" class
3410 * @param {Object} [parameters={}]
3411 */
3412 constructor(parameters = {}) {
3413 super(parameters);
3414 this.idBlock.tagClass = 1; // UNIVERSAL
3415
3416 this.idBlock.tagNumber = 17; // Set
3417 } //**********************************************************************************
3418
3419 /**
3420 * Aux function, need to get a block name. Need to have it here for inhiritence
3421 * @returns {string}
3422 */
3423
3424
3425 static blockName() {
3426 return "Set";
3427 } //**********************************************************************************
3428
3429
3430 }
3431
3432 exports.Set = Set; //**************************************************************************************
3433 //endregion
3434 //**************************************************************************************
3435 //region Declaration of ASN.1 Null type class
3436 //**************************************************************************************
3437
3438 class Null extends BaseBlock {
3439 //**********************************************************************************
3440
3441 /**
3442 * Constructor for "Null" class
3443 * @param {Object} [parameters={}]
3444 */
3445 constructor(parameters = {}) {
3446 super(parameters, LocalBaseBlock); // We will not have a call to "Null value block" because of specified "fromBER" and "toBER" functions
3447
3448 this.idBlock.tagClass = 1; // UNIVERSAL
3449
3450 this.idBlock.tagNumber = 5; // Null
3451 } //**********************************************************************************
3452
3453 /**
3454 * Aux function, need to get a block name. Need to have it here for inhiritence
3455 * @returns {string}
3456 */
3457
3458
3459 static blockName() {
3460 return "Null";
3461 } //**********************************************************************************
3462 //noinspection JSUnusedLocalSymbols
3463
3464 /**
3465 * Base function for converting block from BER encoded array of bytes
3466 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
3467 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
3468 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3469 * @returns {number} Offset after least decoded byte
3470 */
3471
3472
3473 fromBER(inputBuffer, inputOffset, inputLength) {
3474 if (this.lenBlock.length > 0) this.warnings.push("Non-zero length of value block for Null type");
3475 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
3476 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
3477 this.blockLength += inputLength;
3478
3479 if (inputOffset + inputLength > inputBuffer.byteLength) {
3480 this.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
3481 return -1;
3482 }
3483
3484 return inputOffset + inputLength;
3485 } //**********************************************************************************
3486
3487 /**
3488 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
3489 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
3490 * @returns {ArrayBuffer}
3491 */
3492
3493
3494 toBER(sizeOnly = false) {
3495 const retBuf = new ArrayBuffer(2);
3496 if (sizeOnly === true) return retBuf;
3497 const retView = new Uint8Array(retBuf);
3498 retView[0] = 0x05;
3499 retView[1] = 0x00;
3500 return retBuf;
3501 } //**********************************************************************************
3502
3503
3504 }
3505
3506 exports.Null = Null; //**************************************************************************************
3507 //endregion
3508 //**************************************************************************************
3509 //region Declaration of ASN.1 OctetString type class
3510 //**************************************************************************************
3511
3512 class LocalOctetStringValueBlock extends LocalHexBlock(LocalConstructedValueBlock) {
3513 //**********************************************************************************
3514
3515 /**
3516 * Constructor for "LocalOctetStringValueBlock" class
3517 * @param {Object} [parameters={}]
3518 * @property {ArrayBuffer} [valueHex]
3519 */
3520 constructor(parameters = {}) {
3521 super(parameters);
3522 this.isConstructed = (0, utils.getParametersValue)(parameters, "isConstructed", false);
3523 } //**********************************************************************************
3524
3525 /**
3526 * Base function for converting block from BER encoded array of bytes
3527 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
3528 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
3529 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3530 * @returns {number} Offset after least decoded byte
3531 */
3532
3533
3534 fromBER(inputBuffer, inputOffset, inputLength) {
3535 let resultOffset = 0;
3536
3537 if (this.isConstructed === true) {
3538 this.isHexOnly = false;
3539 resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength);
3540 if (resultOffset === -1) return resultOffset;
3541
3542 for (let i = 0; i < this.value.length; i++) {
3543 const currentBlockName = this.value[i].constructor.blockName();
3544
3545 if (currentBlockName === EndOfContent.blockName()) {
3546 if (this.isIndefiniteForm === true) break;else {
3547 this.error = "EndOfContent is unexpected, OCTET STRING may consists of OCTET STRINGs only";
3548 return -1;
3549 }
3550 }
3551
3552 if (currentBlockName !== OctetString.blockName()) {
3553 this.error = "OCTET STRING may consists of OCTET STRINGs only";
3554 return -1;
3555 }
3556 }
3557 } else {
3558 this.isHexOnly = true;
3559 resultOffset = super.fromBER(inputBuffer, inputOffset, inputLength);
3560 this.blockLength = inputLength;
3561 }
3562
3563 return resultOffset;
3564 } //**********************************************************************************
3565
3566 /**
3567 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
3568 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
3569 * @returns {ArrayBuffer}
3570 */
3571
3572
3573 toBER(sizeOnly = false) {
3574 if (this.isConstructed === true) return LocalConstructedValueBlock.prototype.toBER.call(this, sizeOnly);
3575 let retBuf = new ArrayBuffer(this.valueHex.byteLength);
3576 if (sizeOnly === true) return retBuf;
3577 if (this.valueHex.byteLength === 0) return retBuf;
3578 retBuf = this.valueHex.slice(0);
3579 return retBuf;
3580 } //**********************************************************************************
3581
3582 /**
3583 * Aux function, need to get a block name. Need to have it here for inhiritence
3584 * @returns {string}
3585 */
3586
3587
3588 static blockName() {
3589 return "OctetStringValueBlock";
3590 } //**********************************************************************************
3591
3592
3593 toJSON() {
3594 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
3595
3596 try {
3597 object = super.toJSON();
3598 } catch (ex) {} //endregion
3599
3600
3601 object.isConstructed = this.isConstructed;
3602 object.isHexOnly = this.isHexOnly;
3603 object.valueHex = (0, utils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
3604 return object;
3605 } //**********************************************************************************
3606
3607
3608 } //**************************************************************************************
3609
3610
3611 class OctetString extends BaseBlock {
3612 //**********************************************************************************
3613
3614 /**
3615 * Constructor for "OctetString" class
3616 * @param {Object} [parameters={}]
3617 */
3618 constructor(parameters = {}) {
3619 super(parameters, LocalOctetStringValueBlock);
3620 this.idBlock.tagClass = 1; // UNIVERSAL
3621
3622 this.idBlock.tagNumber = 4; // OctetString
3623 } //**********************************************************************************
3624
3625 /**
3626 * Base function for converting block from BER encoded array of bytes
3627 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
3628 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
3629 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3630 * @returns {number} Offset after least decoded byte
3631 */
3632
3633
3634 fromBER(inputBuffer, inputOffset, inputLength) {
3635 this.valueBlock.isConstructed = this.idBlock.isConstructed;
3636 this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm; //region Ability to encode empty OCTET STRING
3637
3638 if (inputLength === 0) {
3639 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
3640 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
3641 return inputOffset;
3642 } //endregion
3643
3644
3645 return super.fromBER(inputBuffer, inputOffset, inputLength);
3646 } //**********************************************************************************
3647
3648 /**
3649 * Aux function, need to get a block name. Need to have it here for inhiritence
3650 * @returns {string}
3651 */
3652
3653
3654 static blockName() {
3655 return "OctetString";
3656 } //**********************************************************************************
3657 //noinspection JSUnusedGlobalSymbols
3658
3659 /**
3660 * Checking that two OCTETSTRINGs are equal
3661 * @param {OctetString} octetString
3662 */
3663
3664
3665 isEqual(octetString) {
3666 //region Check input type
3667 if (octetString instanceof OctetString === false) return false; //endregion
3668 //region Compare two JSON strings
3669
3670 if (JSON.stringify(this) !== JSON.stringify(octetString)) return false; //endregion
3671
3672 return true;
3673 } //**********************************************************************************
3674
3675
3676 }
3677
3678 exports.OctetString = OctetString; //**************************************************************************************
3679 //endregion
3680 //**************************************************************************************
3681 //region Declaration of ASN.1 BitString type class
3682 //**************************************************************************************
3683
3684 class LocalBitStringValueBlock extends LocalHexBlock(LocalConstructedValueBlock) {
3685 //**********************************************************************************
3686
3687 /**
3688 * Constructor for "LocalBitStringValueBlock" class
3689 * @param {Object} [parameters={}]
3690 * @property {ArrayBuffer} [valueHex]
3691 */
3692 constructor(parameters = {}) {
3693 super(parameters);
3694 this.unusedBits = (0, utils.getParametersValue)(parameters, "unusedBits", 0);
3695 this.isConstructed = (0, utils.getParametersValue)(parameters, "isConstructed", false);
3696 this.blockLength = this.valueHex.byteLength;
3697 } //**********************************************************************************
3698
3699 /**
3700 * Base function for converting block from BER encoded array of bytes
3701 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
3702 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
3703 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3704 * @returns {number} Offset after least decoded byte
3705 */
3706
3707
3708 fromBER(inputBuffer, inputOffset, inputLength) {
3709 //region Ability to decode zero-length BitString value
3710 if (inputLength === 0) return inputOffset; //endregion
3711
3712 let resultOffset = -1; //region If the BISTRING supposed to be a constructed value
3713
3714 if (this.isConstructed === true) {
3715 resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength);
3716 if (resultOffset === -1) return resultOffset;
3717
3718 for (let i = 0; i < this.value.length; i++) {
3719 const currentBlockName = this.value[i].constructor.blockName();
3720
3721 if (currentBlockName === EndOfContent.blockName()) {
3722 if (this.isIndefiniteForm === true) break;else {
3723 this.error = "EndOfContent is unexpected, BIT STRING may consists of BIT STRINGs only";
3724 return -1;
3725 }
3726 }
3727
3728 if (currentBlockName !== BitString.blockName()) {
3729 this.error = "BIT STRING may consists of BIT STRINGs only";
3730 return -1;
3731 }
3732
3733 if (this.unusedBits > 0 && this.value[i].valueBlock.unusedBits > 0) {
3734 this.error = "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only";
3735 return -1;
3736 }
3737
3738 this.unusedBits = this.value[i].valueBlock.unusedBits;
3739
3740 if (this.unusedBits > 7) {
3741 this.error = "Unused bits for BitString must be in range 0-7";
3742 return -1;
3743 }
3744 }
3745
3746 return resultOffset;
3747 } //endregion
3748 //region If the BitString supposed to be a primitive value
3749 //region Basic check for parameters
3750 //noinspection JSCheckFunctionSignatures
3751
3752
3753 if ((0, utils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
3754
3755 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
3756 this.unusedBits = intBuffer[0];
3757
3758 if (this.unusedBits > 7) {
3759 this.error = "Unused bits for BitString must be in range 0-7";
3760 return -1;
3761 } //region Copy input buffer to internal buffer
3762
3763
3764 this.valueHex = new ArrayBuffer(intBuffer.length - 1);
3765 const view = new Uint8Array(this.valueHex);
3766
3767 for (let i = 0; i < inputLength - 1; i++) view[i] = intBuffer[i + 1]; //endregion
3768
3769
3770 this.blockLength = intBuffer.length;
3771 return inputOffset + inputLength; //endregion
3772 } //**********************************************************************************
3773
3774 /**
3775 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
3776 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
3777 * @returns {ArrayBuffer}
3778 */
3779
3780
3781 toBER(sizeOnly = false) {
3782 if (this.isConstructed === true) return LocalConstructedValueBlock.prototype.toBER.call(this, sizeOnly);
3783 if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength + 1);
3784 if (this.valueHex.byteLength === 0) return new ArrayBuffer(0);
3785 const curView = new Uint8Array(this.valueHex);
3786 const retBuf = new ArrayBuffer(this.valueHex.byteLength + 1);
3787 const retView = new Uint8Array(retBuf);
3788 retView[0] = this.unusedBits;
3789
3790 for (let i = 0; i < this.valueHex.byteLength; i++) retView[i + 1] = curView[i];
3791
3792 return retBuf;
3793 } //**********************************************************************************
3794
3795 /**
3796 * Aux function, need to get a block name. Need to have it here for inhiritence
3797 * @returns {string}
3798 */
3799
3800
3801 static blockName() {
3802 return "BitStringValueBlock";
3803 } //**********************************************************************************
3804
3805 /**
3806 * Convertion for the block to JSON object
3807 * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
3808 */
3809
3810
3811 toJSON() {
3812 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
3813
3814 try {
3815 object = super.toJSON();
3816 } catch (ex) {} //endregion
3817
3818
3819 object.unusedBits = this.unusedBits;
3820 object.isConstructed = this.isConstructed;
3821 object.isHexOnly = this.isHexOnly;
3822 object.valueHex = (0, utils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
3823 return object;
3824 } //**********************************************************************************
3825
3826
3827 } //**************************************************************************************
3828
3829
3830 class BitString extends BaseBlock {
3831 //**********************************************************************************
3832
3833 /**
3834 * Constructor for "BitString" class
3835 * @param {Object} [parameters={}]
3836 */
3837 constructor(parameters = {}) {
3838 super(parameters, LocalBitStringValueBlock);
3839 this.idBlock.tagClass = 1; // UNIVERSAL
3840
3841 this.idBlock.tagNumber = 3; // BitString
3842 } //**********************************************************************************
3843
3844 /**
3845 * Aux function, need to get a block name. Need to have it here for inhiritence
3846 * @returns {string}
3847 */
3848
3849
3850 static blockName() {
3851 return "BitString";
3852 } //**********************************************************************************
3853
3854 /**
3855 * Base function for converting block from BER encoded array of bytes
3856 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
3857 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
3858 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3859 * @returns {number} Offset after least decoded byte
3860 */
3861
3862
3863 fromBER(inputBuffer, inputOffset, inputLength) {
3864 //region Ability to encode empty BitString
3865 if (inputLength === 0) return inputOffset; //endregion
3866
3867 this.valueBlock.isConstructed = this.idBlock.isConstructed;
3868 this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
3869 return super.fromBER(inputBuffer, inputOffset, inputLength);
3870 } //**********************************************************************************
3871
3872 /**
3873 * Checking that two BITSTRINGs are equal
3874 * @param {BitString} bitString
3875 */
3876
3877
3878 isEqual(bitString) {
3879 //region Check input type
3880 if (bitString instanceof BitString === false) return false; //endregion
3881 //region Compare two JSON strings
3882
3883 if (JSON.stringify(this) !== JSON.stringify(bitString)) return false; //endregion
3884
3885 return true;
3886 } //**********************************************************************************
3887
3888
3889 }
3890
3891 exports.BitString = BitString; //**************************************************************************************
3892 //endregion
3893 //**************************************************************************************
3894 //region Declaration of ASN.1 Integer type class
3895 //**************************************************************************************
3896
3897 /**
3898 * @extends LocalValueBlock
3899 */
3900
3901 class LocalIntegerValueBlock extends LocalHexBlock(LocalValueBlock) {
3902 //**********************************************************************************
3903
3904 /**
3905 * Constructor for "LocalIntegerValueBlock" class
3906 * @param {Object} [parameters={}]
3907 * @property {ArrayBuffer} [valueHex]
3908 */
3909 constructor(parameters = {}) {
3910 super(parameters);
3911 if ("value" in parameters) this.valueDec = parameters.value;
3912 } //**********************************************************************************
3913
3914 /**
3915 * Setter for "valueHex"
3916 * @param {ArrayBuffer} _value
3917 */
3918
3919
3920 set valueHex(_value) {
3921 this._valueHex = _value.slice(0);
3922
3923 if (_value.byteLength >= 4) {
3924 this.warnings.push("Too big Integer for decoding, hex only");
3925 this.isHexOnly = true;
3926 this._valueDec = 0;
3927 } else {
3928 this.isHexOnly = false;
3929 if (_value.byteLength > 0) this._valueDec = utils.utilDecodeTC.call(this);
3930 }
3931 } //**********************************************************************************
3932
3933 /**
3934 * Getter for "valueHex"
3935 * @returns {ArrayBuffer}
3936 */
3937
3938
3939 get valueHex() {
3940 return this._valueHex;
3941 } //**********************************************************************************
3942
3943 /**
3944 * Getter for "valueDec"
3945 * @param {number} _value
3946 */
3947
3948
3949 set valueDec(_value) {
3950 this._valueDec = _value;
3951 this.isHexOnly = false;
3952 this._valueHex = (0, utils.utilEncodeTC)(_value);
3953 } //**********************************************************************************
3954
3955 /**
3956 * Getter for "valueDec"
3957 * @returns {number}
3958 */
3959
3960
3961 get valueDec() {
3962 return this._valueDec;
3963 } //**********************************************************************************
3964
3965 /**
3966 * Base function for converting block from DER encoded array of bytes
3967 * @param {!ArrayBuffer} inputBuffer ASN.1 DER encoded array
3968 * @param {!number} inputOffset Offset in ASN.1 DER encoded array where decoding should be started
3969 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
3970 * @param {number} [expectedLength=0] Expected length of converted "valueHex" buffer
3971 * @returns {number} Offset after least decoded byte
3972 */
3973
3974
3975 fromDER(inputBuffer, inputOffset, inputLength, expectedLength = 0) {
3976 const offset = this.fromBER(inputBuffer, inputOffset, inputLength);
3977 if (offset === -1) return offset;
3978 const view = new Uint8Array(this._valueHex);
3979
3980 if (view[0] === 0x00 && (view[1] & 0x80) !== 0) {
3981 const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength - 1);
3982 const updatedView = new Uint8Array(updatedValueHex);
3983 updatedView.set(new Uint8Array(this._valueHex, 1, this._valueHex.byteLength - 1));
3984 this._valueHex = updatedValueHex.slice(0);
3985 } else {
3986 if (expectedLength !== 0) {
3987 if (this._valueHex.byteLength < expectedLength) {
3988 if (expectedLength - this._valueHex.byteLength > 1) expectedLength = this._valueHex.byteLength + 1;
3989 const updatedValueHex = new ArrayBuffer(expectedLength);
3990 const updatedView = new Uint8Array(updatedValueHex);
3991 updatedView.set(view, expectedLength - this._valueHex.byteLength);
3992 this._valueHex = updatedValueHex.slice(0);
3993 }
3994 }
3995 }
3996
3997 return offset;
3998 } //**********************************************************************************
3999
4000 /**
4001 * Encoding of current ASN.1 block into ASN.1 encoded array (DER rules)
4002 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
4003 * @returns {ArrayBuffer}
4004 */
4005
4006
4007 toDER(sizeOnly = false) {
4008 const view = new Uint8Array(this._valueHex);
4009
4010 switch (true) {
4011 case (view[0] & 0x80) !== 0:
4012 {
4013 const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength + 1);
4014 const updatedView = new Uint8Array(updatedValueHex);
4015 updatedView[0] = 0x00;
4016 updatedView.set(view, 1);
4017 this._valueHex = updatedValueHex.slice(0);
4018 }
4019 break;
4020
4021 case view[0] === 0x00 && (view[1] & 0x80) === 0:
4022 {
4023 const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength - 1);
4024 const updatedView = new Uint8Array(updatedValueHex);
4025 updatedView.set(new Uint8Array(this._valueHex, 1, this._valueHex.byteLength - 1));
4026 this._valueHex = updatedValueHex.slice(0);
4027 }
4028 break;
4029
4030 default:
4031 }
4032
4033 return this.toBER(sizeOnly);
4034 } //**********************************************************************************
4035
4036 /**
4037 * Base function for converting block from BER encoded array of bytes
4038 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
4039 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
4040 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
4041 * @returns {number} Offset after least decoded byte
4042 */
4043
4044
4045 fromBER(inputBuffer, inputOffset, inputLength) {
4046 const resultOffset = super.fromBER(inputBuffer, inputOffset, inputLength);
4047 if (resultOffset === -1) return resultOffset;
4048 this.blockLength = inputLength;
4049 return inputOffset + inputLength;
4050 } //**********************************************************************************
4051
4052 /**
4053 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
4054 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
4055 * @returns {ArrayBuffer}
4056 */
4057
4058
4059 toBER(sizeOnly = false) {
4060 //noinspection JSCheckFunctionSignatures
4061 return this.valueHex.slice(0);
4062 } //**********************************************************************************
4063
4064 /**
4065 * Aux function, need to get a block name. Need to have it here for inhiritence
4066 * @returns {string}
4067 */
4068
4069
4070 static blockName() {
4071 return "IntegerValueBlock";
4072 } //**********************************************************************************
4073 //noinspection JSUnusedGlobalSymbols
4074
4075 /**
4076 * Convertion for the block to JSON object
4077 * @returns {Object}
4078 */
4079
4080
4081 toJSON() {
4082 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
4083
4084 try {
4085 object = super.toJSON();
4086 } catch (ex) {} //endregion
4087
4088
4089 object.valueDec = this.valueDec;
4090 return object;
4091 } //**********************************************************************************
4092
4093 /**
4094 * Convert current value to decimal string representation
4095 */
4096
4097
4098 toString() {
4099 //region Aux functions
4100 function viewAdd(first, second) {
4101 //region Initial variables
4102 const c = new Uint8Array([0]);
4103 let firstView = new Uint8Array(first);
4104 let secondView = new Uint8Array(second);
4105 let firstViewCopy = firstView.slice(0);
4106 const firstViewCopyLength = firstViewCopy.length - 1;
4107 let secondViewCopy = secondView.slice(0);
4108 const secondViewCopyLength = secondViewCopy.length - 1;
4109 let value = 0;
4110 const max = secondViewCopyLength < firstViewCopyLength ? firstViewCopyLength : secondViewCopyLength;
4111 let counter = 0; //endregion
4112
4113 for (let i = max; i >= 0; i--, counter++) {
4114 switch (true) {
4115 case counter < secondViewCopy.length:
4116 value = firstViewCopy[firstViewCopyLength - counter] + secondViewCopy[secondViewCopyLength - counter] + c[0];
4117 break;
4118
4119 default:
4120 value = firstViewCopy[firstViewCopyLength - counter] + c[0];
4121 }
4122
4123 c[0] = value / 10;
4124
4125 switch (true) {
4126 case counter >= firstViewCopy.length:
4127 firstViewCopy = (0, utils.utilConcatView)(new Uint8Array([value % 10]), firstViewCopy);
4128 break;
4129
4130 default:
4131 firstViewCopy[firstViewCopyLength - counter] = value % 10;
4132 }
4133 }
4134
4135 if (c[0] > 0) firstViewCopy = (0, utils.utilConcatView)(c, firstViewCopy);
4136 return firstViewCopy.slice(0);
4137 }
4138
4139 function power2(n) {
4140 if (n >= powers2.length) {
4141 for (let p = powers2.length; p <= n; p++) {
4142 const c = new Uint8Array([0]);
4143 let digits = powers2[p - 1].slice(0);
4144
4145 for (let i = digits.length - 1; i >= 0; i--) {
4146 const newValue = new Uint8Array([(digits[i] << 1) + c[0]]);
4147 c[0] = newValue[0] / 10;
4148 digits[i] = newValue[0] % 10;
4149 }
4150
4151 if (c[0] > 0) digits = (0, utils.utilConcatView)(c, digits);
4152 powers2.push(digits);
4153 }
4154 }
4155
4156 return powers2[n];
4157 }
4158
4159 function viewSub(first, second) {
4160 //region Initial variables
4161 let b = 0;
4162 let firstView = new Uint8Array(first);
4163 let secondView = new Uint8Array(second);
4164 let firstViewCopy = firstView.slice(0);
4165 const firstViewCopyLength = firstViewCopy.length - 1;
4166 let secondViewCopy = secondView.slice(0);
4167 const secondViewCopyLength = secondViewCopy.length - 1;
4168 let value;
4169 let counter = 0; //endregion
4170
4171 for (let i = secondViewCopyLength; i >= 0; i--, counter++) {
4172 value = firstViewCopy[firstViewCopyLength - counter] - secondViewCopy[secondViewCopyLength - counter] - b;
4173
4174 switch (true) {
4175 case value < 0:
4176 b = 1;
4177 firstViewCopy[firstViewCopyLength - counter] = value + 10;
4178 break;
4179
4180 default:
4181 b = 0;
4182 firstViewCopy[firstViewCopyLength - counter] = value;
4183 }
4184 }
4185
4186 if (b > 0) {
4187 for (let i = firstViewCopyLength - secondViewCopyLength + 1; i >= 0; i--, counter++) {
4188 value = firstViewCopy[firstViewCopyLength - counter] - b;
4189
4190 if (value < 0) {
4191 b = 1;
4192 firstViewCopy[firstViewCopyLength - counter] = value + 10;
4193 } else {
4194 b = 0;
4195 firstViewCopy[firstViewCopyLength - counter] = value;
4196 break;
4197 }
4198 }
4199 }
4200
4201 return firstViewCopy.slice();
4202 } //endregion
4203 //region Initial variables
4204
4205
4206 const firstBit = this._valueHex.byteLength * 8 - 1;
4207 let digits = new Uint8Array(this._valueHex.byteLength * 8 / 3);
4208 let bitNumber = 0;
4209 let currentByte;
4210 const asn1View = new Uint8Array(this._valueHex);
4211 let result = "";
4212 let flag = false; //endregion
4213 //region Calculate number
4214
4215 for (let byteNumber = this._valueHex.byteLength - 1; byteNumber >= 0; byteNumber--) {
4216 currentByte = asn1View[byteNumber];
4217
4218 for (let i = 0; i < 8; i++) {
4219 if ((currentByte & 1) === 1) {
4220 switch (bitNumber) {
4221 case firstBit:
4222 digits = viewSub(power2(bitNumber), digits);
4223 result = "-";
4224 break;
4225
4226 default:
4227 digits = viewAdd(digits, power2(bitNumber));
4228 }
4229 }
4230
4231 bitNumber++;
4232 currentByte >>= 1;
4233 }
4234 } //endregion
4235 //region Print number
4236
4237
4238 for (let i = 0; i < digits.length; i++) {
4239 if (digits[i]) flag = true;
4240 if (flag) result += digitsString.charAt(digits[i]);
4241 }
4242
4243 if (flag === false) result += digitsString.charAt(0); //endregion
4244
4245 return result;
4246 } //**********************************************************************************
4247
4248
4249 } //**************************************************************************************
4250
4251
4252 class Integer extends BaseBlock {
4253 //**********************************************************************************
4254
4255 /**
4256 * Constructor for "Integer" class
4257 * @param {Object} [parameters={}]
4258 */
4259 constructor(parameters = {}) {
4260 super(parameters, LocalIntegerValueBlock);
4261 this.idBlock.tagClass = 1; // UNIVERSAL
4262
4263 this.idBlock.tagNumber = 2; // Integer
4264 } //**********************************************************************************
4265
4266 /**
4267 * Aux function, need to get a block name. Need to have it here for inhiritence
4268 * @returns {string}
4269 */
4270
4271
4272 static blockName() {
4273 return "Integer";
4274 } //**********************************************************************************
4275 //noinspection JSUnusedGlobalSymbols
4276
4277 /**
4278 * Compare two Integer object, or Integer and ArrayBuffer objects
4279 * @param {!Integer|ArrayBuffer} otherValue
4280 * @returns {boolean}
4281 */
4282
4283
4284 isEqual(otherValue) {
4285 if (otherValue instanceof Integer) {
4286 if (this.valueBlock.isHexOnly && otherValue.valueBlock.isHexOnly) // Compare two ArrayBuffers
4287 return (0, utils.isEqualBuffer)(this.valueBlock.valueHex, otherValue.valueBlock.valueHex);
4288 if (this.valueBlock.isHexOnly === otherValue.valueBlock.isHexOnly) return this.valueBlock.valueDec === otherValue.valueBlock.valueDec;
4289 return false;
4290 }
4291
4292 if (otherValue instanceof ArrayBuffer) return (0, utils.isEqualBuffer)(this.valueBlock.valueHex, otherValue);
4293 return false;
4294 } //**********************************************************************************
4295
4296 /**
4297 * Convert current Integer value from BER into DER format
4298 * @returns {Integer}
4299 */
4300
4301
4302 convertToDER() {
4303 const integer = new Integer({
4304 valueHex: this.valueBlock.valueHex
4305 });
4306 integer.valueBlock.toDER();
4307 return integer;
4308 } //**********************************************************************************
4309
4310 /**
4311 * Convert current Integer value from DER to BER format
4312 * @returns {Integer}
4313 */
4314
4315
4316 convertFromDER() {
4317 const expectedLength = this.valueBlock.valueHex.byteLength % 2 ? this.valueBlock.valueHex.byteLength + 1 : this.valueBlock.valueHex.byteLength;
4318 const integer = new Integer({
4319 valueHex: this.valueBlock.valueHex
4320 });
4321 integer.valueBlock.fromDER(integer.valueBlock.valueHex, 0, integer.valueBlock.valueHex.byteLength, expectedLength);
4322 return integer;
4323 } //**********************************************************************************
4324
4325
4326 }
4327
4328 exports.Integer = Integer; //**************************************************************************************
4329 //endregion
4330 //**************************************************************************************
4331 //region Declaration of ASN.1 Enumerated type class
4332 //**************************************************************************************
4333
4334 class Enumerated extends Integer {
4335 //**********************************************************************************
4336
4337 /**
4338 * Constructor for "Enumerated" class
4339 * @param {Object} [parameters={}]
4340 */
4341 constructor(parameters = {}) {
4342 super(parameters);
4343 this.idBlock.tagClass = 1; // UNIVERSAL
4344
4345 this.idBlock.tagNumber = 10; // Enumerated
4346 } //**********************************************************************************
4347
4348 /**
4349 * Aux function, need to get a block name. Need to have it here for inhiritence
4350 * @returns {string}
4351 */
4352
4353
4354 static blockName() {
4355 return "Enumerated";
4356 } //**********************************************************************************
4357
4358
4359 }
4360
4361 exports.Enumerated = Enumerated; //**************************************************************************************
4362 //endregion
4363 //**************************************************************************************
4364 //region Declaration of ASN.1 ObjectIdentifier type class
4365 //**************************************************************************************
4366
4367 class LocalSidValueBlock extends LocalHexBlock(LocalBaseBlock) {
4368 //**********************************************************************************
4369
4370 /**
4371 * Constructor for "LocalSidValueBlock" class
4372 * @param {Object} [parameters={}]
4373 * @property {number} [valueDec]
4374 * @property {boolean} [isFirstSid]
4375 */
4376 constructor(parameters = {}) {
4377 super(parameters);
4378 this.valueDec = (0, utils.getParametersValue)(parameters, "valueDec", -1);
4379 this.isFirstSid = (0, utils.getParametersValue)(parameters, "isFirstSid", false);
4380 } //**********************************************************************************
4381
4382 /**
4383 * Aux function, need to get a block name. Need to have it here for inhiritence
4384 * @returns {string}
4385 */
4386
4387
4388 static blockName() {
4389 return "sidBlock";
4390 } //**********************************************************************************
4391
4392 /**
4393 * Base function for converting block from BER encoded array of bytes
4394 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
4395 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
4396 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
4397 * @returns {number} Offset after least decoded byte
4398 */
4399
4400
4401 fromBER(inputBuffer, inputOffset, inputLength) {
4402 if (inputLength === 0) return inputOffset; //region Basic check for parameters
4403 //noinspection JSCheckFunctionSignatures
4404
4405 if ((0, utils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
4406
4407 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
4408 this.valueHex = new ArrayBuffer(inputLength);
4409 let view = new Uint8Array(this.valueHex);
4410
4411 for (let i = 0; i < inputLength; i++) {
4412 view[i] = intBuffer[i] & 0x7F;
4413 this.blockLength++;
4414 if ((intBuffer[i] & 0x80) === 0x00) break;
4415 } //region Ajust size of valueHex buffer
4416
4417
4418 const tempValueHex = new ArrayBuffer(this.blockLength);
4419 const tempView = new Uint8Array(tempValueHex);
4420
4421 for (let i = 0; i < this.blockLength; i++) tempView[i] = view[i]; //noinspection JSCheckFunctionSignatures
4422
4423
4424 this.valueHex = tempValueHex.slice(0);
4425 view = new Uint8Array(this.valueHex); //endregion
4426
4427 if ((intBuffer[this.blockLength - 1] & 0x80) !== 0x00) {
4428 this.error = "End of input reached before message was fully decoded";
4429 return -1;
4430 }
4431
4432 if (view[0] === 0x00) this.warnings.push("Needlessly long format of SID encoding");
4433 if (this.blockLength <= 8) this.valueDec = (0, utils.utilFromBase)(view, 7);else {
4434 this.isHexOnly = true;
4435 this.warnings.push("Too big SID for decoding, hex only");
4436 }
4437 return inputOffset + this.blockLength;
4438 } //**********************************************************************************
4439
4440 /**
4441 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
4442 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
4443 * @returns {ArrayBuffer}
4444 */
4445
4446
4447 toBER(sizeOnly = false) {
4448 //region Initial variables
4449 let retBuf;
4450 let retView; //endregion
4451
4452 if (this.isHexOnly) {
4453 if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength);
4454 const curView = new Uint8Array(this.valueHex);
4455 retBuf = new ArrayBuffer(this.blockLength);
4456 retView = new Uint8Array(retBuf);
4457
4458 for (let i = 0; i < this.blockLength - 1; i++) retView[i] = curView[i] | 0x80;
4459
4460 retView[this.blockLength - 1] = curView[this.blockLength - 1];
4461 return retBuf;
4462 }
4463
4464 const encodedBuf = (0, utils.utilToBase)(this.valueDec, 7);
4465
4466 if (encodedBuf.byteLength === 0) {
4467 this.error = "Error during encoding SID value";
4468 return new ArrayBuffer(0);
4469 }
4470
4471 retBuf = new ArrayBuffer(encodedBuf.byteLength);
4472
4473 if (sizeOnly === false) {
4474 const encodedView = new Uint8Array(encodedBuf);
4475 retView = new Uint8Array(retBuf);
4476
4477 for (let i = 0; i < encodedBuf.byteLength - 1; i++) retView[i] = encodedView[i] | 0x80;
4478
4479 retView[encodedBuf.byteLength - 1] = encodedView[encodedBuf.byteLength - 1];
4480 }
4481
4482 return retBuf;
4483 } //**********************************************************************************
4484
4485 /**
4486 * Create string representation of current SID block
4487 * @returns {string}
4488 */
4489
4490
4491 toString() {
4492 let result = "";
4493 if (this.isHexOnly === true) result = (0, utils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);else {
4494 if (this.isFirstSid) {
4495 let sidValue = this.valueDec;
4496 if (this.valueDec <= 39) result = "0.";else {
4497 if (this.valueDec <= 79) {
4498 result = "1.";
4499 sidValue -= 40;
4500 } else {
4501 result = "2.";
4502 sidValue -= 80;
4503 }
4504 }
4505 result += sidValue.toString();
4506 } else result = this.valueDec.toString();
4507 }
4508 return result;
4509 } //**********************************************************************************
4510 //noinspection JSUnusedGlobalSymbols
4511
4512 /**
4513 * Convertion for the block to JSON object
4514 * @returns {Object}
4515 */
4516
4517
4518 toJSON() {
4519 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
4520
4521 try {
4522 object = super.toJSON();
4523 } catch (ex) {} //endregion
4524
4525
4526 object.valueDec = this.valueDec;
4527 object.isFirstSid = this.isFirstSid;
4528 return object;
4529 } //**********************************************************************************
4530
4531
4532 } //**************************************************************************************
4533
4534
4535 class LocalObjectIdentifierValueBlock extends LocalValueBlock {
4536 //**********************************************************************************
4537
4538 /**
4539 * Constructor for "LocalObjectIdentifierValueBlock" class
4540 * @param {Object} [parameters={}]
4541 * @property {ArrayBuffer} [valueHex]
4542 */
4543 constructor(parameters = {}) {
4544 super(parameters);
4545 this.fromString((0, utils.getParametersValue)(parameters, "value", ""));
4546 } //**********************************************************************************
4547
4548 /**
4549 * Base function for converting block from BER encoded array of bytes
4550 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
4551 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
4552 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
4553 * @returns {number} Offset after least decoded byte
4554 */
4555
4556
4557 fromBER(inputBuffer, inputOffset, inputLength) {
4558 let resultOffset = inputOffset;
4559
4560 while (inputLength > 0) {
4561 const sidBlock = new LocalSidValueBlock();
4562 resultOffset = sidBlock.fromBER(inputBuffer, resultOffset, inputLength);
4563
4564 if (resultOffset === -1) {
4565 this.blockLength = 0;
4566 this.error = sidBlock.error;
4567 return resultOffset;
4568 }
4569
4570 if (this.value.length === 0) sidBlock.isFirstSid = true;
4571 this.blockLength += sidBlock.blockLength;
4572 inputLength -= sidBlock.blockLength;
4573 this.value.push(sidBlock);
4574 }
4575
4576 return resultOffset;
4577 } //**********************************************************************************
4578
4579 /**
4580 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
4581 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
4582 * @returns {ArrayBuffer}
4583 */
4584
4585
4586 toBER(sizeOnly = false) {
4587 let retBuf = new ArrayBuffer(0);
4588
4589 for (let i = 0; i < this.value.length; i++) {
4590 const valueBuf = this.value[i].toBER(sizeOnly);
4591
4592 if (valueBuf.byteLength === 0) {
4593 this.error = this.value[i].error;
4594 return new ArrayBuffer(0);
4595 }
4596
4597 retBuf = (0, utils.utilConcatBuf)(retBuf, valueBuf);
4598 }
4599
4600 return retBuf;
4601 } //**********************************************************************************
4602
4603 /**
4604 * Create "LocalObjectIdentifierValueBlock" class from string
4605 * @param {string} string Input string to convert from
4606 * @returns {boolean}
4607 */
4608
4609
4610 fromString(string) {
4611 this.value = []; // Clear existing SID values
4612
4613 let pos1 = 0;
4614 let pos2 = 0;
4615 let sid = "";
4616 let flag = false;
4617
4618 do {
4619 pos2 = string.indexOf(".", pos1);
4620 if (pos2 === -1) sid = string.substr(pos1);else sid = string.substr(pos1, pos2 - pos1);
4621 pos1 = pos2 + 1;
4622
4623 if (flag) {
4624 const sidBlock = this.value[0];
4625 let plus = 0;
4626
4627 switch (sidBlock.valueDec) {
4628 case 0:
4629 break;
4630
4631 case 1:
4632 plus = 40;
4633 break;
4634
4635 case 2:
4636 plus = 80;
4637 break;
4638
4639 default:
4640 this.value = []; // clear SID array
4641
4642 return false;
4643 // ???
4644 }
4645
4646 const parsedSID = parseInt(sid, 10);
4647 if (isNaN(parsedSID)) return true;
4648 sidBlock.valueDec = parsedSID + plus;
4649 flag = false;
4650 } else {
4651 const sidBlock = new LocalSidValueBlock();
4652 sidBlock.valueDec = parseInt(sid, 10);
4653 if (isNaN(sidBlock.valueDec)) return true;
4654
4655 if (this.value.length === 0) {
4656 sidBlock.isFirstSid = true;
4657 flag = true;
4658 }
4659
4660 this.value.push(sidBlock);
4661 }
4662 } while (pos2 !== -1);
4663
4664 return true;
4665 } //**********************************************************************************
4666
4667 /**
4668 * Converts "LocalObjectIdentifierValueBlock" class to string
4669 * @returns {string}
4670 */
4671
4672
4673 toString() {
4674 let result = "";
4675 let isHexOnly = false;
4676
4677 for (let i = 0; i < this.value.length; i++) {
4678 isHexOnly = this.value[i].isHexOnly;
4679 let sidStr = this.value[i].toString();
4680 if (i !== 0) result = `${result}.`;
4681
4682 if (isHexOnly) {
4683 sidStr = `{${sidStr}}`;
4684 if (this.value[i].isFirstSid) result = `2.{${sidStr} - 80}`;else result += sidStr;
4685 } else result += sidStr;
4686 }
4687
4688 return result;
4689 } //**********************************************************************************
4690
4691 /**
4692 * Aux function, need to get a block name. Need to have it here for inhiritence
4693 * @returns {string}
4694 */
4695
4696
4697 static blockName() {
4698 return "ObjectIdentifierValueBlock";
4699 } //**********************************************************************************
4700
4701 /**
4702 * Convertion for the block to JSON object
4703 * @returns {Object}
4704 */
4705
4706
4707 toJSON() {
4708 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
4709
4710 try {
4711 object = super.toJSON();
4712 } catch (ex) {} //endregion
4713
4714
4715 object.value = this.toString();
4716 object.sidArray = [];
4717
4718 for (let i = 0; i < this.value.length; i++) object.sidArray.push(this.value[i].toJSON());
4719
4720 return object;
4721 } //**********************************************************************************
4722
4723
4724 } //**************************************************************************************
4725
4726 /**
4727 * @extends BaseBlock
4728 */
4729
4730
4731 class ObjectIdentifier extends BaseBlock {
4732 //**********************************************************************************
4733
4734 /**
4735 * Constructor for "ObjectIdentifier" class
4736 * @param {Object} [parameters={}]
4737 * @property {ArrayBuffer} [valueHex]
4738 */
4739 constructor(parameters = {}) {
4740 super(parameters, LocalObjectIdentifierValueBlock);
4741 this.idBlock.tagClass = 1; // UNIVERSAL
4742
4743 this.idBlock.tagNumber = 6; // OBJECT IDENTIFIER
4744 } //**********************************************************************************
4745
4746 /**
4747 * Aux function, need to get a block name. Need to have it here for inhiritence
4748 * @returns {string}
4749 */
4750
4751
4752 static blockName() {
4753 return "ObjectIdentifier";
4754 } //**********************************************************************************
4755
4756
4757 }
4758
4759 exports.ObjectIdentifier = ObjectIdentifier; //**************************************************************************************
4760 //endregion
4761 //**************************************************************************************
4762 //region Declaration of all string's classes
4763 //**************************************************************************************
4764
4765 class LocalUtf8StringValueBlock extends LocalHexBlock(LocalBaseBlock) {
4766 //**********************************************************************************
4767 //noinspection JSUnusedGlobalSymbols
4768
4769 /**
4770 * Constructor for "LocalUtf8StringValueBlock" class
4771 * @param {Object} [parameters={}]
4772 */
4773 constructor(parameters = {}) {
4774 super(parameters);
4775 this.isHexOnly = true;
4776 this.value = ""; // String representation of decoded ArrayBuffer
4777 } //**********************************************************************************
4778
4779 /**
4780 * Aux function, need to get a block name. Need to have it here for inhiritence
4781 * @returns {string}
4782 */
4783
4784
4785 static blockName() {
4786 return "Utf8StringValueBlock";
4787 } //**********************************************************************************
4788 //noinspection JSUnusedGlobalSymbols
4789
4790 /**
4791 * Convertion for the block to JSON object
4792 * @returns {Object}
4793 */
4794
4795
4796 toJSON() {
4797 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
4798
4799 try {
4800 object = super.toJSON();
4801 } catch (ex) {} //endregion
4802
4803
4804 object.value = this.value;
4805 return object;
4806 } //**********************************************************************************
4807
4808
4809 } //**************************************************************************************
4810
4811 /**
4812 * @extends BaseBlock
4813 */
4814
4815
4816 class Utf8String extends BaseBlock {
4817 //**********************************************************************************
4818
4819 /**
4820 * Constructor for "Utf8String" class
4821 * @param {Object} [parameters={}]
4822 * @property {ArrayBuffer} [valueHex]
4823 */
4824 constructor(parameters = {}) {
4825 super(parameters, LocalUtf8StringValueBlock);
4826 if ("value" in parameters) this.fromString(parameters.value);
4827 this.idBlock.tagClass = 1; // UNIVERSAL
4828
4829 this.idBlock.tagNumber = 12; // Utf8String
4830 } //**********************************************************************************
4831
4832 /**
4833 * Aux function, need to get a block name. Need to have it here for inhiritence
4834 * @returns {string}
4835 */
4836
4837
4838 static blockName() {
4839 return "Utf8String";
4840 } //**********************************************************************************
4841
4842 /**
4843 * Base function for converting block from BER encoded array of bytes
4844 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
4845 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
4846 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
4847 * @returns {number} Offset after least decoded byte
4848 */
4849
4850
4851 fromBER(inputBuffer, inputOffset, inputLength) {
4852 const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
4853
4854 if (resultOffset === -1) {
4855 this.error = this.valueBlock.error;
4856 return resultOffset;
4857 }
4858
4859 this.fromBuffer(this.valueBlock.valueHex);
4860 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
4861 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
4862 if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
4863 return resultOffset;
4864 } //**********************************************************************************
4865
4866 /**
4867 * Function converting ArrayBuffer into ASN.1 internal string
4868 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
4869 */
4870
4871
4872 fromBuffer(inputBuffer) {
4873 this.valueBlock.value = String.fromCharCode.apply(null, new Uint8Array(inputBuffer));
4874
4875 try {
4876 //noinspection JSDeprecatedSymbols
4877 this.valueBlock.value = decodeURIComponent(escape(this.valueBlock.value));
4878 } catch (ex) {
4879 this.warnings.push(`Error during "decodeURIComponent": ${ex}, using raw string`);
4880 }
4881 } //**********************************************************************************
4882
4883 /**
4884 * Function converting JavaScript string into ASN.1 internal class
4885 * @param {!string} inputString ASN.1 BER encoded array
4886 */
4887
4888
4889 fromString(inputString) {
4890 //noinspection JSDeprecatedSymbols
4891 const str = unescape(encodeURIComponent(inputString));
4892 const strLen = str.length;
4893 this.valueBlock.valueHex = new ArrayBuffer(strLen);
4894 const view = new Uint8Array(this.valueBlock.valueHex);
4895
4896 for (let i = 0; i < strLen; i++) view[i] = str.charCodeAt(i);
4897
4898 this.valueBlock.value = inputString;
4899 } //**********************************************************************************
4900
4901
4902 }
4903
4904 exports.Utf8String = Utf8String; //**************************************************************************************
4905
4906 /**
4907 * @extends LocalBaseBlock
4908 * @extends LocalHexBlock
4909 */
4910
4911 class LocalBmpStringValueBlock extends LocalHexBlock(LocalBaseBlock) {
4912 //**********************************************************************************
4913
4914 /**
4915 * Constructor for "LocalBmpStringValueBlock" class
4916 * @param {Object} [parameters={}]
4917 */
4918 constructor(parameters = {}) {
4919 super(parameters);
4920 this.isHexOnly = true;
4921 this.value = "";
4922 } //**********************************************************************************
4923
4924 /**
4925 * Aux function, need to get a block name. Need to have it here for inhiritence
4926 * @returns {string}
4927 */
4928
4929
4930 static blockName() {
4931 return "BmpStringValueBlock";
4932 } //**********************************************************************************
4933 //noinspection JSUnusedGlobalSymbols
4934
4935 /**
4936 * Convertion for the block to JSON object
4937 * @returns {Object}
4938 */
4939
4940
4941 toJSON() {
4942 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
4943
4944 try {
4945 object = super.toJSON();
4946 } catch (ex) {} //endregion
4947
4948
4949 object.value = this.value;
4950 return object;
4951 } //**********************************************************************************
4952
4953
4954 } //**************************************************************************************
4955
4956 /**
4957 * @extends BaseBlock
4958 */
4959
4960
4961 class BmpString extends BaseBlock {
4962 //**********************************************************************************
4963
4964 /**
4965 * Constructor for "BmpString" class
4966 * @param {Object} [parameters={}]
4967 */
4968 constructor(parameters = {}) {
4969 super(parameters, LocalBmpStringValueBlock);
4970 if ("value" in parameters) this.fromString(parameters.value);
4971 this.idBlock.tagClass = 1; // UNIVERSAL
4972
4973 this.idBlock.tagNumber = 30; // BmpString
4974 } //**********************************************************************************
4975
4976 /**
4977 * Aux function, need to get a block name. Need to have it here for inhiritence
4978 * @returns {string}
4979 */
4980
4981
4982 static blockName() {
4983 return "BmpString";
4984 } //**********************************************************************************
4985
4986 /**
4987 * Base function for converting block from BER encoded array of bytes
4988 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
4989 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
4990 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
4991 * @returns {number} Offset after least decoded byte
4992 */
4993
4994
4995 fromBER(inputBuffer, inputOffset, inputLength) {
4996 const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
4997
4998 if (resultOffset === -1) {
4999 this.error = this.valueBlock.error;
5000 return resultOffset;
5001 }
5002
5003 this.fromBuffer(this.valueBlock.valueHex);
5004 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
5005 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
5006 if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
5007 return resultOffset;
5008 } //**********************************************************************************
5009
5010 /**
5011 * Function converting ArrayBuffer into ASN.1 internal string
5012 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5013 */
5014
5015
5016 fromBuffer(inputBuffer) {
5017 //noinspection JSCheckFunctionSignatures
5018 const copyBuffer = inputBuffer.slice(0);
5019 const valueView = new Uint8Array(copyBuffer);
5020
5021 for (let i = 0; i < valueView.length; i += 2) {
5022 const temp = valueView[i];
5023 valueView[i] = valueView[i + 1];
5024 valueView[i + 1] = temp;
5025 }
5026
5027 this.valueBlock.value = String.fromCharCode.apply(null, new Uint16Array(copyBuffer));
5028 } //**********************************************************************************
5029
5030 /**
5031 * Function converting JavaScript string into ASN.1 internal class
5032 * @param {!string} inputString ASN.1 BER encoded array
5033 */
5034
5035
5036 fromString(inputString) {
5037 const strLength = inputString.length;
5038 this.valueBlock.valueHex = new ArrayBuffer(strLength * 2);
5039 const valueHexView = new Uint8Array(this.valueBlock.valueHex);
5040
5041 for (let i = 0; i < strLength; i++) {
5042 const codeBuf = (0, utils.utilToBase)(inputString.charCodeAt(i), 8);
5043 const codeView = new Uint8Array(codeBuf);
5044 if (codeView.length > 2) continue;
5045 const dif = 2 - codeView.length;
5046
5047 for (let j = codeView.length - 1; j >= 0; j--) valueHexView[i * 2 + j + dif] = codeView[j];
5048 }
5049
5050 this.valueBlock.value = inputString;
5051 } //**********************************************************************************
5052
5053
5054 }
5055
5056 exports.BmpString = BmpString; //**************************************************************************************
5057
5058 class LocalUniversalStringValueBlock extends LocalHexBlock(LocalBaseBlock) {
5059 //**********************************************************************************
5060
5061 /**
5062 * Constructor for "LocalUniversalStringValueBlock" class
5063 * @param {Object} [parameters={}]
5064 */
5065 constructor(parameters = {}) {
5066 super(parameters);
5067 this.isHexOnly = true;
5068 this.value = "";
5069 } //**********************************************************************************
5070
5071 /**
5072 * Aux function, need to get a block name. Need to have it here for inhiritence
5073 * @returns {string}
5074 */
5075
5076
5077 static blockName() {
5078 return "UniversalStringValueBlock";
5079 } //**********************************************************************************
5080 //noinspection JSUnusedGlobalSymbols
5081
5082 /**
5083 * Convertion for the block to JSON object
5084 * @returns {Object}
5085 */
5086
5087
5088 toJSON() {
5089 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
5090
5091 try {
5092 object = super.toJSON();
5093 } catch (ex) {} //endregion
5094
5095
5096 object.value = this.value;
5097 return object;
5098 } //**********************************************************************************
5099
5100
5101 } //**************************************************************************************
5102
5103 /**
5104 * @extends BaseBlock
5105 */
5106
5107
5108 class UniversalString extends BaseBlock {
5109 //**********************************************************************************
5110
5111 /**
5112 * Constructor for "UniversalString" class
5113 * @param {Object} [parameters={}]
5114 */
5115 constructor(parameters = {}) {
5116 super(parameters, LocalUniversalStringValueBlock);
5117 if ("value" in parameters) this.fromString(parameters.value);
5118 this.idBlock.tagClass = 1; // UNIVERSAL
5119
5120 this.idBlock.tagNumber = 28; // UniversalString
5121 } //**********************************************************************************
5122
5123 /**
5124 * Aux function, need to get a block name. Need to have it here for inhiritence
5125 * @returns {string}
5126 */
5127
5128
5129 static blockName() {
5130 return "UniversalString";
5131 } //**********************************************************************************
5132
5133 /**
5134 * Base function for converting block from BER encoded array of bytes
5135 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5136 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
5137 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
5138 * @returns {number} Offset after least decoded byte
5139 */
5140
5141
5142 fromBER(inputBuffer, inputOffset, inputLength) {
5143 const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
5144
5145 if (resultOffset === -1) {
5146 this.error = this.valueBlock.error;
5147 return resultOffset;
5148 }
5149
5150 this.fromBuffer(this.valueBlock.valueHex);
5151 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
5152 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
5153 if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
5154 return resultOffset;
5155 } //**********************************************************************************
5156
5157 /**
5158 * Function converting ArrayBuffer into ASN.1 internal string
5159 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5160 */
5161
5162
5163 fromBuffer(inputBuffer) {
5164 //noinspection JSCheckFunctionSignatures
5165 const copyBuffer = inputBuffer.slice(0);
5166 const valueView = new Uint8Array(copyBuffer);
5167
5168 for (let i = 0; i < valueView.length; i += 4) {
5169 valueView[i] = valueView[i + 3];
5170 valueView[i + 1] = valueView[i + 2];
5171 valueView[i + 2] = 0x00;
5172 valueView[i + 3] = 0x00;
5173 }
5174
5175 this.valueBlock.value = String.fromCharCode.apply(null, new Uint32Array(copyBuffer));
5176 } //**********************************************************************************
5177
5178 /**
5179 * Function converting JavaScript string into ASN.1 internal class
5180 * @param {!string} inputString ASN.1 BER encoded array
5181 */
5182
5183
5184 fromString(inputString) {
5185 const strLength = inputString.length;
5186 this.valueBlock.valueHex = new ArrayBuffer(strLength * 4);
5187 const valueHexView = new Uint8Array(this.valueBlock.valueHex);
5188
5189 for (let i = 0; i < strLength; i++) {
5190 const codeBuf = (0, utils.utilToBase)(inputString.charCodeAt(i), 8);
5191 const codeView = new Uint8Array(codeBuf);
5192 if (codeView.length > 4) continue;
5193 const dif = 4 - codeView.length;
5194
5195 for (let j = codeView.length - 1; j >= 0; j--) valueHexView[i * 4 + j + dif] = codeView[j];
5196 }
5197
5198 this.valueBlock.value = inputString;
5199 } //**********************************************************************************
5200
5201
5202 }
5203
5204 exports.UniversalString = UniversalString; //**************************************************************************************
5205
5206 class LocalSimpleStringValueBlock extends LocalHexBlock(LocalBaseBlock) {
5207 //**********************************************************************************
5208
5209 /**
5210 * Constructor for "LocalSimpleStringValueBlock" class
5211 * @param {Object} [parameters={}]
5212 */
5213 constructor(parameters = {}) {
5214 super(parameters);
5215 this.value = "";
5216 this.isHexOnly = true;
5217 } //**********************************************************************************
5218
5219 /**
5220 * Aux function, need to get a block name. Need to have it here for inhiritence
5221 * @returns {string}
5222 */
5223
5224
5225 static blockName() {
5226 return "SimpleStringValueBlock";
5227 } //**********************************************************************************
5228 //noinspection JSUnusedGlobalSymbols
5229
5230 /**
5231 * Convertion for the block to JSON object
5232 * @returns {Object}
5233 */
5234
5235
5236 toJSON() {
5237 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
5238
5239 try {
5240 object = super.toJSON();
5241 } catch (ex) {} //endregion
5242
5243
5244 object.value = this.value;
5245 return object;
5246 } //**********************************************************************************
5247
5248
5249 } //**************************************************************************************
5250
5251 /**
5252 * @extends BaseBlock
5253 */
5254
5255
5256 class LocalSimpleStringBlock extends BaseBlock {
5257 //**********************************************************************************
5258
5259 /**
5260 * Constructor for "LocalSimpleStringBlock" class
5261 * @param {Object} [parameters={}]
5262 */
5263 constructor(parameters = {}) {
5264 super(parameters, LocalSimpleStringValueBlock);
5265 if ("value" in parameters) this.fromString(parameters.value);
5266 } //**********************************************************************************
5267
5268 /**
5269 * Aux function, need to get a block name. Need to have it here for inhiritence
5270 * @returns {string}
5271 */
5272
5273
5274 static blockName() {
5275 return "SIMPLESTRING";
5276 } //**********************************************************************************
5277
5278 /**
5279 * Base function for converting block from BER encoded array of bytes
5280 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5281 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
5282 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
5283 * @returns {number} Offset after least decoded byte
5284 */
5285
5286
5287 fromBER(inputBuffer, inputOffset, inputLength) {
5288 const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
5289
5290 if (resultOffset === -1) {
5291 this.error = this.valueBlock.error;
5292 return resultOffset;
5293 }
5294
5295 this.fromBuffer(this.valueBlock.valueHex);
5296 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
5297 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
5298 if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
5299 return resultOffset;
5300 } //**********************************************************************************
5301
5302 /**
5303 * Function converting ArrayBuffer into ASN.1 internal string
5304 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5305 */
5306
5307
5308 fromBuffer(inputBuffer) {
5309 this.valueBlock.value = String.fromCharCode.apply(null, new Uint8Array(inputBuffer));
5310 } //**********************************************************************************
5311
5312 /**
5313 * Function converting JavaScript string into ASN.1 internal class
5314 * @param {!string} inputString ASN.1 BER encoded array
5315 */
5316
5317
5318 fromString(inputString) {
5319 const strLen = inputString.length;
5320 this.valueBlock.valueHex = new ArrayBuffer(strLen);
5321 const view = new Uint8Array(this.valueBlock.valueHex);
5322
5323 for (let i = 0; i < strLen; i++) view[i] = inputString.charCodeAt(i);
5324
5325 this.valueBlock.value = inputString;
5326 } //**********************************************************************************
5327
5328
5329 } //**************************************************************************************
5330
5331 /**
5332 * @extends LocalSimpleStringBlock
5333 */
5334
5335
5336 class NumericString extends LocalSimpleStringBlock {
5337 //**********************************************************************************
5338
5339 /**
5340 * Constructor for "NumericString" class
5341 * @param {Object} [parameters={}]
5342 */
5343 constructor(parameters = {}) {
5344 super(parameters);
5345 this.idBlock.tagClass = 1; // UNIVERSAL
5346
5347 this.idBlock.tagNumber = 18; // NumericString
5348 } //**********************************************************************************
5349
5350 /**
5351 * Aux function, need to get a block name. Need to have it here for inhiritence
5352 * @returns {string}
5353 */
5354
5355
5356 static blockName() {
5357 return "NumericString";
5358 } //**********************************************************************************
5359
5360
5361 }
5362
5363 exports.NumericString = NumericString; //**************************************************************************************
5364
5365 /**
5366 * @extends LocalSimpleStringBlock
5367 */
5368
5369 class PrintableString extends LocalSimpleStringBlock {
5370 //**********************************************************************************
5371
5372 /**
5373 * Constructor for "PrintableString" class
5374 * @param {Object} [parameters={}]
5375 */
5376 constructor(parameters = {}) {
5377 super(parameters);
5378 this.idBlock.tagClass = 1; // UNIVERSAL
5379
5380 this.idBlock.tagNumber = 19; // PrintableString
5381 } //**********************************************************************************
5382
5383 /**
5384 * Aux function, need to get a block name. Need to have it here for inhiritence
5385 * @returns {string}
5386 */
5387
5388
5389 static blockName() {
5390 return "PrintableString";
5391 } //**********************************************************************************
5392
5393
5394 }
5395
5396 exports.PrintableString = PrintableString; //**************************************************************************************
5397
5398 /**
5399 * @extends LocalSimpleStringBlock
5400 */
5401
5402 class TeletexString extends LocalSimpleStringBlock {
5403 //**********************************************************************************
5404
5405 /**
5406 * Constructor for "TeletexString" class
5407 * @param {Object} [parameters={}]
5408 */
5409 constructor(parameters = {}) {
5410 super(parameters);
5411 this.idBlock.tagClass = 1; // UNIVERSAL
5412
5413 this.idBlock.tagNumber = 20; // TeletexString
5414 } //**********************************************************************************
5415
5416 /**
5417 * Aux function, need to get a block name. Need to have it here for inhiritence
5418 * @returns {string}
5419 */
5420
5421
5422 static blockName() {
5423 return "TeletexString";
5424 } //**********************************************************************************
5425
5426
5427 }
5428
5429 exports.TeletexString = TeletexString; //**************************************************************************************
5430
5431 /**
5432 * @extends LocalSimpleStringBlock
5433 */
5434
5435 class VideotexString extends LocalSimpleStringBlock {
5436 //**********************************************************************************
5437
5438 /**
5439 * Constructor for "VideotexString" class
5440 * @param {Object} [parameters={}]
5441 */
5442 constructor(parameters = {}) {
5443 super(parameters);
5444 this.idBlock.tagClass = 1; // UNIVERSAL
5445
5446 this.idBlock.tagNumber = 21; // VideotexString
5447 } //**********************************************************************************
5448
5449 /**
5450 * Aux function, need to get a block name. Need to have it here for inhiritence
5451 * @returns {string}
5452 */
5453
5454
5455 static blockName() {
5456 return "VideotexString";
5457 } //**********************************************************************************
5458
5459
5460 }
5461
5462 exports.VideotexString = VideotexString; //**************************************************************************************
5463
5464 /**
5465 * @extends LocalSimpleStringBlock
5466 */
5467
5468 class IA5String extends LocalSimpleStringBlock {
5469 //**********************************************************************************
5470
5471 /**
5472 * Constructor for "IA5String" class
5473 * @param {Object} [parameters={}]
5474 */
5475 constructor(parameters = {}) {
5476 super(parameters);
5477 this.idBlock.tagClass = 1; // UNIVERSAL
5478
5479 this.idBlock.tagNumber = 22; // IA5String
5480 } //**********************************************************************************
5481
5482 /**
5483 * Aux function, need to get a block name. Need to have it here for inhiritence
5484 * @returns {string}
5485 */
5486
5487
5488 static blockName() {
5489 return "IA5String";
5490 } //**********************************************************************************
5491
5492
5493 }
5494
5495 exports.IA5String = IA5String; //**************************************************************************************
5496
5497 /**
5498 * @extends LocalSimpleStringBlock
5499 */
5500
5501 class GraphicString extends LocalSimpleStringBlock {
5502 //**********************************************************************************
5503
5504 /**
5505 * Constructor for "GraphicString" class
5506 * @param {Object} [parameters={}]
5507 */
5508 constructor(parameters = {}) {
5509 super(parameters);
5510 this.idBlock.tagClass = 1; // UNIVERSAL
5511
5512 this.idBlock.tagNumber = 25; // GraphicString
5513 } //**********************************************************************************
5514
5515 /**
5516 * Aux function, need to get a block name. Need to have it here for inhiritence
5517 * @returns {string}
5518 */
5519
5520
5521 static blockName() {
5522 return "GraphicString";
5523 } //**********************************************************************************
5524
5525
5526 }
5527
5528 exports.GraphicString = GraphicString; //**************************************************************************************
5529
5530 /**
5531 * @extends LocalSimpleStringBlock
5532 */
5533
5534 class VisibleString extends LocalSimpleStringBlock {
5535 //**********************************************************************************
5536
5537 /**
5538 * Constructor for "VisibleString" class
5539 * @param {Object} [parameters={}]
5540 */
5541 constructor(parameters = {}) {
5542 super(parameters);
5543 this.idBlock.tagClass = 1; // UNIVERSAL
5544
5545 this.idBlock.tagNumber = 26; // VisibleString
5546 } //**********************************************************************************
5547
5548 /**
5549 * Aux function, need to get a block name. Need to have it here for inhiritence
5550 * @returns {string}
5551 */
5552
5553
5554 static blockName() {
5555 return "VisibleString";
5556 } //**********************************************************************************
5557
5558
5559 }
5560
5561 exports.VisibleString = VisibleString; //**************************************************************************************
5562
5563 /**
5564 * @extends LocalSimpleStringBlock
5565 */
5566
5567 class GeneralString extends LocalSimpleStringBlock {
5568 //**********************************************************************************
5569
5570 /**
5571 * Constructor for "GeneralString" class
5572 * @param {Object} [parameters={}]
5573 */
5574 constructor(parameters = {}) {
5575 super(parameters);
5576 this.idBlock.tagClass = 1; // UNIVERSAL
5577
5578 this.idBlock.tagNumber = 27; // GeneralString
5579 } //**********************************************************************************
5580
5581 /**
5582 * Aux function, need to get a block name. Need to have it here for inhiritence
5583 * @returns {string}
5584 */
5585
5586
5587 static blockName() {
5588 return "GeneralString";
5589 } //**********************************************************************************
5590
5591
5592 }
5593
5594 exports.GeneralString = GeneralString; //**************************************************************************************
5595
5596 /**
5597 * @extends LocalSimpleStringBlock
5598 */
5599
5600 class CharacterString extends LocalSimpleStringBlock {
5601 //**********************************************************************************
5602
5603 /**
5604 * Constructor for "CharacterString" class
5605 * @param {Object} [parameters={}]
5606 */
5607 constructor(parameters = {}) {
5608 super(parameters);
5609 this.idBlock.tagClass = 1; // UNIVERSAL
5610
5611 this.idBlock.tagNumber = 29; // CharacterString
5612 } //**********************************************************************************
5613
5614 /**
5615 * Aux function, need to get a block name. Need to have it here for inhiritence
5616 * @returns {string}
5617 */
5618
5619
5620 static blockName() {
5621 return "CharacterString";
5622 } //**********************************************************************************
5623
5624
5625 }
5626
5627 exports.CharacterString = CharacterString; //**************************************************************************************
5628 //endregion
5629 //**************************************************************************************
5630 //region Declaration of all date and time classes
5631 //**************************************************************************************
5632
5633 /**
5634 * @extends VisibleString
5635 */
5636
5637 class UTCTime extends VisibleString {
5638 //**********************************************************************************
5639
5640 /**
5641 * Constructor for "UTCTime" class
5642 * @param {Object} [parameters={}]
5643 * @property {string} [value] String representatio of the date
5644 * @property {Date} [valueDate] JavaScript "Date" object
5645 */
5646 constructor(parameters = {}) {
5647 super(parameters);
5648 this.year = 0;
5649 this.month = 0;
5650 this.day = 0;
5651 this.hour = 0;
5652 this.minute = 0;
5653 this.second = 0; //region Create UTCTime from ASN.1 UTC string value
5654
5655 if ("value" in parameters) {
5656 this.fromString(parameters.value);
5657 this.valueBlock.valueHex = new ArrayBuffer(parameters.value.length);
5658 const view = new Uint8Array(this.valueBlock.valueHex);
5659
5660 for (let i = 0; i < parameters.value.length; i++) view[i] = parameters.value.charCodeAt(i);
5661 } //endregion
5662 //region Create GeneralizedTime from JavaScript Date type
5663
5664
5665 if ("valueDate" in parameters) {
5666 this.fromDate(parameters.valueDate);
5667 this.valueBlock.valueHex = this.toBuffer();
5668 } //endregion
5669
5670
5671 this.idBlock.tagClass = 1; // UNIVERSAL
5672
5673 this.idBlock.tagNumber = 23; // UTCTime
5674 } //**********************************************************************************
5675
5676 /**
5677 * Base function for converting block from BER encoded array of bytes
5678 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5679 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
5680 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
5681 * @returns {number} Offset after least decoded byte
5682 */
5683
5684
5685 fromBER(inputBuffer, inputOffset, inputLength) {
5686 const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
5687
5688 if (resultOffset === -1) {
5689 this.error = this.valueBlock.error;
5690 return resultOffset;
5691 }
5692
5693 this.fromBuffer(this.valueBlock.valueHex);
5694 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
5695 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
5696 if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
5697 return resultOffset;
5698 } //**********************************************************************************
5699
5700 /**
5701 * Function converting ArrayBuffer into ASN.1 internal string
5702 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5703 */
5704
5705
5706 fromBuffer(inputBuffer) {
5707 this.fromString(String.fromCharCode.apply(null, new Uint8Array(inputBuffer)));
5708 } //**********************************************************************************
5709
5710 /**
5711 * Function converting ASN.1 internal string into ArrayBuffer
5712 * @returns {ArrayBuffer}
5713 */
5714
5715
5716 toBuffer() {
5717 const str = this.toString();
5718 const buffer = new ArrayBuffer(str.length);
5719 const view = new Uint8Array(buffer);
5720
5721 for (let i = 0; i < str.length; i++) view[i] = str.charCodeAt(i);
5722
5723 return buffer;
5724 } //**********************************************************************************
5725
5726 /**
5727 * Function converting "Date" object into ASN.1 internal string
5728 * @param {!Date} inputDate JavaScript "Date" object
5729 */
5730
5731
5732 fromDate(inputDate) {
5733 this.year = inputDate.getUTCFullYear();
5734 this.month = inputDate.getUTCMonth() + 1;
5735 this.day = inputDate.getUTCDate();
5736 this.hour = inputDate.getUTCHours();
5737 this.minute = inputDate.getUTCMinutes();
5738 this.second = inputDate.getUTCSeconds();
5739 } //**********************************************************************************
5740 //noinspection JSUnusedGlobalSymbols
5741
5742 /**
5743 * Function converting ASN.1 internal string into "Date" object
5744 * @returns {Date}
5745 */
5746
5747
5748 toDate() {
5749 return new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second));
5750 } //**********************************************************************************
5751
5752 /**
5753 * Function converting JavaScript string into ASN.1 internal class
5754 * @param {!string} inputString ASN.1 BER encoded array
5755 */
5756
5757
5758 fromString(inputString) {
5759 //region Parse input string
5760 const parser = /(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z/ig;
5761 const parserArray = parser.exec(inputString);
5762
5763 if (parserArray === null) {
5764 this.error = "Wrong input string for convertion";
5765 return;
5766 } //endregion
5767 //region Store parsed values
5768
5769
5770 const year = parseInt(parserArray[1], 10);
5771 if (year >= 50) this.year = 1900 + year;else this.year = 2000 + year;
5772 this.month = parseInt(parserArray[2], 10);
5773 this.day = parseInt(parserArray[3], 10);
5774 this.hour = parseInt(parserArray[4], 10);
5775 this.minute = parseInt(parserArray[5], 10);
5776 this.second = parseInt(parserArray[6], 10); //endregion
5777 } //**********************************************************************************
5778
5779 /**
5780 * Function converting ASN.1 internal class into JavaScript string
5781 * @returns {string}
5782 */
5783
5784
5785 toString() {
5786 const outputArray = new Array(7);
5787 outputArray[0] = (0, utils.padNumber)(this.year < 2000 ? this.year - 1900 : this.year - 2000, 2);
5788 outputArray[1] = (0, utils.padNumber)(this.month, 2);
5789 outputArray[2] = (0, utils.padNumber)(this.day, 2);
5790 outputArray[3] = (0, utils.padNumber)(this.hour, 2);
5791 outputArray[4] = (0, utils.padNumber)(this.minute, 2);
5792 outputArray[5] = (0, utils.padNumber)(this.second, 2);
5793 outputArray[6] = "Z";
5794 return outputArray.join("");
5795 } //**********************************************************************************
5796
5797 /**
5798 * Aux function, need to get a block name. Need to have it here for inhiritence
5799 * @returns {string}
5800 */
5801
5802
5803 static blockName() {
5804 return "UTCTime";
5805 } //**********************************************************************************
5806
5807 /**
5808 * Convertion for the block to JSON object
5809 * @returns {Object}
5810 */
5811
5812
5813 toJSON() {
5814 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
5815
5816 try {
5817 object = super.toJSON();
5818 } catch (ex) {} //endregion
5819
5820
5821 object.year = this.year;
5822 object.month = this.month;
5823 object.day = this.day;
5824 object.hour = this.hour;
5825 object.minute = this.minute;
5826 object.second = this.second;
5827 return object;
5828 } //**********************************************************************************
5829
5830
5831 }
5832
5833 exports.UTCTime = UTCTime; //**************************************************************************************
5834
5835 /**
5836 * @extends VisibleString
5837 */
5838
5839 class GeneralizedTime extends VisibleString {
5840 //**********************************************************************************
5841
5842 /**
5843 * Constructor for "GeneralizedTime" class
5844 * @param {Object} [parameters={}]
5845 * @property {string} [value] String representatio of the date
5846 * @property {Date} [valueDate] JavaScript "Date" object
5847 */
5848 constructor(parameters = {}) {
5849 super(parameters);
5850 this.year = 0;
5851 this.month = 0;
5852 this.day = 0;
5853 this.hour = 0;
5854 this.minute = 0;
5855 this.second = 0;
5856 this.millisecond = 0; //region Create UTCTime from ASN.1 UTC string value
5857
5858 if ("value" in parameters) {
5859 this.fromString(parameters.value);
5860 this.valueBlock.valueHex = new ArrayBuffer(parameters.value.length);
5861 const view = new Uint8Array(this.valueBlock.valueHex);
5862
5863 for (let i = 0; i < parameters.value.length; i++) view[i] = parameters.value.charCodeAt(i);
5864 } //endregion
5865 //region Create GeneralizedTime from JavaScript Date type
5866
5867
5868 if ("valueDate" in parameters) {
5869 this.fromDate(parameters.valueDate);
5870 this.valueBlock.valueHex = this.toBuffer();
5871 } //endregion
5872
5873
5874 this.idBlock.tagClass = 1; // UNIVERSAL
5875
5876 this.idBlock.tagNumber = 24; // GeneralizedTime
5877 } //**********************************************************************************
5878
5879 /**
5880 * Base function for converting block from BER encoded array of bytes
5881 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5882 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
5883 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
5884 * @returns {number} Offset after least decoded byte
5885 */
5886
5887
5888 fromBER(inputBuffer, inputOffset, inputLength) {
5889 const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
5890
5891 if (resultOffset === -1) {
5892 this.error = this.valueBlock.error;
5893 return resultOffset;
5894 }
5895
5896 this.fromBuffer(this.valueBlock.valueHex);
5897 if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
5898 if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
5899 if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
5900 return resultOffset;
5901 } //**********************************************************************************
5902
5903 /**
5904 * Function converting ArrayBuffer into ASN.1 internal string
5905 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
5906 */
5907
5908
5909 fromBuffer(inputBuffer) {
5910 this.fromString(String.fromCharCode.apply(null, new Uint8Array(inputBuffer)));
5911 } //**********************************************************************************
5912
5913 /**
5914 * Function converting ASN.1 internal string into ArrayBuffer
5915 * @returns {ArrayBuffer}
5916 */
5917
5918
5919 toBuffer() {
5920 const str = this.toString();
5921 const buffer = new ArrayBuffer(str.length);
5922 const view = new Uint8Array(buffer);
5923
5924 for (let i = 0; i < str.length; i++) view[i] = str.charCodeAt(i);
5925
5926 return buffer;
5927 } //**********************************************************************************
5928
5929 /**
5930 * Function converting "Date" object into ASN.1 internal string
5931 * @param {!Date} inputDate JavaScript "Date" object
5932 */
5933
5934
5935 fromDate(inputDate) {
5936 this.year = inputDate.getUTCFullYear();
5937 this.month = inputDate.getUTCMonth() + 1;
5938 this.day = inputDate.getUTCDate();
5939 this.hour = inputDate.getUTCHours();
5940 this.minute = inputDate.getUTCMinutes();
5941 this.second = inputDate.getUTCSeconds();
5942 this.millisecond = inputDate.getUTCMilliseconds();
5943 } //**********************************************************************************
5944 //noinspection JSUnusedGlobalSymbols
5945
5946 /**
5947 * Function converting ASN.1 internal string into "Date" object
5948 * @returns {Date}
5949 */
5950
5951
5952 toDate() {
5953 return new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond));
5954 } //**********************************************************************************
5955
5956 /**
5957 * Function converting JavaScript string into ASN.1 internal class
5958 * @param {!string} inputString ASN.1 BER encoded array
5959 */
5960
5961
5962 fromString(inputString) {
5963 //region Initial variables
5964 let isUTC = false;
5965 let timeString = "";
5966 let dateTimeString = "";
5967 let fractionPart = 0;
5968 let parser;
5969 let hourDifference = 0;
5970 let minuteDifference = 0; //endregion
5971 //region Convert as UTC time
5972
5973 if (inputString[inputString.length - 1] === "Z") {
5974 timeString = inputString.substr(0, inputString.length - 1);
5975 isUTC = true;
5976 } //endregion
5977 //region Convert as local time
5978 else {
5979 //noinspection JSPrimitiveTypeWrapperUsage
5980 const number = new Number(inputString[inputString.length - 1]);
5981 if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
5982 timeString = inputString;
5983 } //endregion
5984 //region Check that we do not have a "+" and "-" symbols inside UTC time
5985
5986
5987 if (isUTC) {
5988 if (timeString.indexOf("+") !== -1) throw new Error("Wrong input string for convertion");
5989 if (timeString.indexOf("-") !== -1) throw new Error("Wrong input string for convertion");
5990 } //endregion
5991 //region Get "UTC time difference" in case of local time
5992 else {
5993 let multiplier = 1;
5994 let differencePosition = timeString.indexOf("+");
5995 let differenceString = "";
5996
5997 if (differencePosition === -1) {
5998 differencePosition = timeString.indexOf("-");
5999 multiplier = -1;
6000 }
6001
6002 if (differencePosition !== -1) {
6003 differenceString = timeString.substr(differencePosition + 1);
6004 timeString = timeString.substr(0, differencePosition);
6005 if (differenceString.length !== 2 && differenceString.length !== 4) throw new Error("Wrong input string for convertion"); //noinspection JSPrimitiveTypeWrapperUsage
6006
6007 let number = new Number(differenceString.substr(0, 2));
6008 if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
6009 hourDifference = multiplier * number;
6010
6011 if (differenceString.length === 4) {
6012 //noinspection JSPrimitiveTypeWrapperUsage
6013 number = new Number(differenceString.substr(2, 2));
6014 if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
6015 minuteDifference = multiplier * number;
6016 }
6017 }
6018 } //endregion
6019 //region Get position of fraction point
6020
6021
6022 let fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol
6023
6024 if (fractionPointPosition === -1) fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol
6025 //endregion
6026 //region Get fraction part
6027
6028 if (fractionPointPosition !== -1) {
6029 //noinspection JSPrimitiveTypeWrapperUsage
6030 const fractionPartCheck = new Number(`0${timeString.substr(fractionPointPosition)}`);
6031 if (isNaN(fractionPartCheck.valueOf())) throw new Error("Wrong input string for convertion");
6032 fractionPart = fractionPartCheck.valueOf();
6033 dateTimeString = timeString.substr(0, fractionPointPosition);
6034 } else dateTimeString = timeString; //endregion
6035 //region Parse internal date
6036
6037
6038 switch (true) {
6039 case dateTimeString.length === 8:
6040 // "YYYYMMDD"
6041 parser = /(\d{4})(\d{2})(\d{2})/ig;
6042 if (fractionPointPosition !== -1) throw new Error("Wrong input string for convertion"); // Here we should not have a "fraction point"
6043
6044 break;
6045
6046 case dateTimeString.length === 10:
6047 // "YYYYMMDDHH"
6048 parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig;
6049
6050 if (fractionPointPosition !== -1) {
6051 let fractionResult = 60 * fractionPart;
6052 this.minute = Math.floor(fractionResult);
6053 fractionResult = 60 * (fractionResult - this.minute);
6054 this.second = Math.floor(fractionResult);
6055 fractionResult = 1000 * (fractionResult - this.second);
6056 this.millisecond = Math.floor(fractionResult);
6057 }
6058
6059 break;
6060
6061 case dateTimeString.length === 12:
6062 // "YYYYMMDDHHMM"
6063 parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
6064
6065 if (fractionPointPosition !== -1) {
6066 let fractionResult = 60 * fractionPart;
6067 this.second = Math.floor(fractionResult);
6068 fractionResult = 1000 * (fractionResult - this.second);
6069 this.millisecond = Math.floor(fractionResult);
6070 }
6071
6072 break;
6073
6074 case dateTimeString.length === 14:
6075 // "YYYYMMDDHHMMSS"
6076 parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
6077
6078 if (fractionPointPosition !== -1) {
6079 const fractionResult = 1000 * fractionPart;
6080 this.millisecond = Math.floor(fractionResult);
6081 }
6082
6083 break;
6084
6085 default:
6086 throw new Error("Wrong input string for convertion");
6087 } //endregion
6088 //region Put parsed values at right places
6089
6090
6091 const parserArray = parser.exec(dateTimeString);
6092 if (parserArray === null) throw new Error("Wrong input string for convertion");
6093
6094 for (let j = 1; j < parserArray.length; j++) {
6095 switch (j) {
6096 case 1:
6097 this.year = parseInt(parserArray[j], 10);
6098 break;
6099
6100 case 2:
6101 this.month = parseInt(parserArray[j], 10);
6102 break;
6103
6104 case 3:
6105 this.day = parseInt(parserArray[j], 10);
6106 break;
6107
6108 case 4:
6109 this.hour = parseInt(parserArray[j], 10) + hourDifference;
6110 break;
6111
6112 case 5:
6113 this.minute = parseInt(parserArray[j], 10) + minuteDifference;
6114 break;
6115
6116 case 6:
6117 this.second = parseInt(parserArray[j], 10);
6118 break;
6119
6120 default:
6121 throw new Error("Wrong input string for convertion");
6122 }
6123 } //endregion
6124 //region Get final date
6125
6126
6127 if (isUTC === false) {
6128 const tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
6129 this.year = tempDate.getUTCFullYear();
6130 this.month = tempDate.getUTCMonth();
6131 this.day = tempDate.getUTCDay();
6132 this.hour = tempDate.getUTCHours();
6133 this.minute = tempDate.getUTCMinutes();
6134 this.second = tempDate.getUTCSeconds();
6135 this.millisecond = tempDate.getUTCMilliseconds();
6136 } //endregion
6137
6138 } //**********************************************************************************
6139
6140 /**
6141 * Function converting ASN.1 internal class into JavaScript string
6142 * @returns {string}
6143 */
6144
6145
6146 toString() {
6147 const outputArray = [];
6148 outputArray.push((0, utils.padNumber)(this.year, 4));
6149 outputArray.push((0, utils.padNumber)(this.month, 2));
6150 outputArray.push((0, utils.padNumber)(this.day, 2));
6151 outputArray.push((0, utils.padNumber)(this.hour, 2));
6152 outputArray.push((0, utils.padNumber)(this.minute, 2));
6153 outputArray.push((0, utils.padNumber)(this.second, 2));
6154
6155 if (this.millisecond !== 0) {
6156 outputArray.push(".");
6157 outputArray.push((0, utils.padNumber)(this.millisecond, 3));
6158 }
6159
6160 outputArray.push("Z");
6161 return outputArray.join("");
6162 } //**********************************************************************************
6163
6164 /**
6165 * Aux function, need to get a block name. Need to have it here for inhiritence
6166 * @returns {string}
6167 */
6168
6169
6170 static blockName() {
6171 return "GeneralizedTime";
6172 } //**********************************************************************************
6173
6174 /**
6175 * Convertion for the block to JSON object
6176 * @returns {Object}
6177 */
6178
6179
6180 toJSON() {
6181 let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
6182
6183 try {
6184 object = super.toJSON();
6185 } catch (ex) {} //endregion
6186
6187
6188 object.year = this.year;
6189 object.month = this.month;
6190 object.day = this.day;
6191 object.hour = this.hour;
6192 object.minute = this.minute;
6193 object.second = this.second;
6194 object.millisecond = this.millisecond;
6195 return object;
6196 } //**********************************************************************************
6197
6198
6199 }
6200
6201 exports.GeneralizedTime = GeneralizedTime; //**************************************************************************************
6202
6203 /**
6204 * @extends Utf8String
6205 */
6206
6207 class DATE extends Utf8String {
6208 //**********************************************************************************
6209
6210 /**
6211 * Constructor for "DATE" class
6212 * @param {Object} [parameters={}]
6213 */
6214 constructor(parameters = {}) {
6215 super(parameters);
6216 this.idBlock.tagClass = 1; // UNIVERSAL
6217
6218 this.idBlock.tagNumber = 31; // DATE
6219 } //**********************************************************************************
6220
6221 /**
6222 * Aux function, need to get a block name. Need to have it here for inhiritence
6223 * @returns {string}
6224 */
6225
6226
6227 static blockName() {
6228 return "DATE";
6229 } //**********************************************************************************
6230
6231
6232 }
6233
6234 exports.DATE = DATE; //**************************************************************************************
6235
6236 /**
6237 * @extends Utf8String
6238 */
6239
6240 class TimeOfDay extends Utf8String {
6241 //**********************************************************************************
6242
6243 /**
6244 * Constructor for "TimeOfDay" class
6245 * @param {Object} [parameters={}]
6246 */
6247 constructor(parameters = {}) {
6248 super(parameters);
6249 this.idBlock.tagClass = 1; // UNIVERSAL
6250
6251 this.idBlock.tagNumber = 32; // TimeOfDay
6252 } //**********************************************************************************
6253
6254 /**
6255 * Aux function, need to get a block name. Need to have it here for inhiritence
6256 * @returns {string}
6257 */
6258
6259
6260 static blockName() {
6261 return "TimeOfDay";
6262 } //**********************************************************************************
6263
6264
6265 }
6266
6267 exports.TimeOfDay = TimeOfDay; //**************************************************************************************
6268
6269 /**
6270 * @extends Utf8String
6271 */
6272
6273 class DateTime extends Utf8String {
6274 //**********************************************************************************
6275
6276 /**
6277 * Constructor for "DateTime" class
6278 * @param {Object} [parameters={}]
6279 */
6280 constructor(parameters = {}) {
6281 super(parameters);
6282 this.idBlock.tagClass = 1; // UNIVERSAL
6283
6284 this.idBlock.tagNumber = 33; // DateTime
6285 } //**********************************************************************************
6286
6287 /**
6288 * Aux function, need to get a block name. Need to have it here for inhiritence
6289 * @returns {string}
6290 */
6291
6292
6293 static blockName() {
6294 return "DateTime";
6295 } //**********************************************************************************
6296
6297
6298 }
6299
6300 exports.DateTime = DateTime; //**************************************************************************************
6301
6302 /**
6303 * @extends Utf8String
6304 */
6305
6306 class Duration extends Utf8String {
6307 //**********************************************************************************
6308
6309 /**
6310 * Constructor for "Duration" class
6311 * @param {Object} [parameters={}]
6312 */
6313 constructor(parameters = {}) {
6314 super(parameters);
6315 this.idBlock.tagClass = 1; // UNIVERSAL
6316
6317 this.idBlock.tagNumber = 34; // Duration
6318 } //**********************************************************************************
6319
6320 /**
6321 * Aux function, need to get a block name. Need to have it here for inhiritence
6322 * @returns {string}
6323 */
6324
6325
6326 static blockName() {
6327 return "Duration";
6328 } //**********************************************************************************
6329
6330
6331 }
6332
6333 exports.Duration = Duration; //**************************************************************************************
6334
6335 /**
6336 * @extends Utf8String
6337 */
6338
6339 class TIME extends Utf8String {
6340 //**********************************************************************************
6341
6342 /**
6343 * Constructor for "Time" class
6344 * @param {Object} [parameters={}]
6345 */
6346 constructor(parameters = {}) {
6347 super(parameters);
6348 this.idBlock.tagClass = 1; // UNIVERSAL
6349
6350 this.idBlock.tagNumber = 14; // Time
6351 } //**********************************************************************************
6352
6353 /**
6354 * Aux function, need to get a block name. Need to have it here for inhiritence
6355 * @returns {string}
6356 */
6357
6358
6359 static blockName() {
6360 return "TIME";
6361 } //**********************************************************************************
6362
6363
6364 }
6365
6366 exports.TIME = TIME; //**************************************************************************************
6367 //endregion
6368 //**************************************************************************************
6369 //region Declaration of special ASN.1 schema type Choice
6370 //**************************************************************************************
6371
6372 class Choice {
6373 //**********************************************************************************
6374
6375 /**
6376 * Constructor for "Choice" class
6377 * @param {Object} [parameters={}]
6378 * @property {Array} [value] Array of ASN.1 types for make a choice from
6379 * @property {boolean} [optional]
6380 */
6381 constructor(parameters = {}) {
6382 this.value = (0, utils.getParametersValue)(parameters, "value", []);
6383 this.optional = (0, utils.getParametersValue)(parameters, "optional", false);
6384 } //**********************************************************************************
6385
6386
6387 }
6388
6389 exports.Choice = Choice; //**************************************************************************************
6390 //endregion
6391 //**************************************************************************************
6392 //region Declaration of special ASN.1 schema type Any
6393 //**************************************************************************************
6394
6395 class Any {
6396 //**********************************************************************************
6397
6398 /**
6399 * Constructor for "Any" class
6400 * @param {Object} [parameters={}]
6401 * @property {string} [name]
6402 * @property {boolean} [optional]
6403 */
6404 constructor(parameters = {}) {
6405 this.name = (0, utils.getParametersValue)(parameters, "name", "");
6406 this.optional = (0, utils.getParametersValue)(parameters, "optional", false);
6407 } //**********************************************************************************
6408
6409
6410 }
6411
6412 exports.Any = Any; //**************************************************************************************
6413 //endregion
6414 //**************************************************************************************
6415 //region Declaration of special ASN.1 schema type Repeated
6416 //**************************************************************************************
6417
6418 class Repeated {
6419 //**********************************************************************************
6420
6421 /**
6422 * Constructor for "Repeated" class
6423 * @param {Object} [parameters={}]
6424 * @property {string} [name]
6425 * @property {boolean} [optional]
6426 */
6427 constructor(parameters = {}) {
6428 this.name = (0, utils.getParametersValue)(parameters, "name", "");
6429 this.optional = (0, utils.getParametersValue)(parameters, "optional", false);
6430 this.value = (0, utils.getParametersValue)(parameters, "value", new Any());
6431 this.local = (0, utils.getParametersValue)(parameters, "local", false); // Could local or global array to store elements
6432 } //**********************************************************************************
6433
6434
6435 }
6436
6437 exports.Repeated = Repeated; //**************************************************************************************
6438 //endregion
6439 //**************************************************************************************
6440 //region Declaration of special ASN.1 schema type RawData
6441 //**************************************************************************************
6442
6443 /**
6444 * @description Special class providing ability to have "toBER/fromBER" for raw ArrayBuffer
6445 */
6446
6447 class RawData {
6448 //**********************************************************************************
6449
6450 /**
6451 * Constructor for "Repeated" class
6452 * @param {Object} [parameters={}]
6453 * @property {string} [name]
6454 * @property {boolean} [optional]
6455 */
6456 constructor(parameters = {}) {
6457 this.data = (0, utils.getParametersValue)(parameters, "data", new ArrayBuffer(0));
6458 } //**********************************************************************************
6459
6460 /**
6461 * Base function for converting block from BER encoded array of bytes
6462 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
6463 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
6464 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
6465 * @returns {number} Offset after least decoded byte
6466 */
6467
6468
6469 fromBER(inputBuffer, inputOffset, inputLength) {
6470 this.data = inputBuffer.slice(inputOffset, inputLength);
6471 return inputOffset + inputLength;
6472 } //**********************************************************************************
6473
6474 /**
6475 * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
6476 * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
6477 * @returns {ArrayBuffer}
6478 */
6479
6480
6481 toBER(sizeOnly = false) {
6482 return this.data;
6483 } //**********************************************************************************
6484
6485
6486 }
6487
6488 exports.RawData = RawData; //**************************************************************************************
6489 //endregion
6490 //**************************************************************************************
6491 //region Major ASN.1 BER decoding function
6492 //**************************************************************************************
6493
6494 /**
6495 * Internal library function for decoding ASN.1 BER
6496 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
6497 * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
6498 * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
6499 * @returns {{offset: number, result: Object}}
6500 */
6501
6502 function LocalFromBER(inputBuffer, inputOffset, inputLength) {
6503 const incomingOffset = inputOffset; // Need to store initial offset since "inputOffset" is changing in the function
6504 //region Local function changing a type for ASN.1 classes
6505
6506 function localChangeType(inputObject, newType) {
6507 if (inputObject instanceof newType) return inputObject;
6508 const newObject = new newType();
6509 newObject.idBlock = inputObject.idBlock;
6510 newObject.lenBlock = inputObject.lenBlock;
6511 newObject.warnings = inputObject.warnings; //noinspection JSCheckFunctionSignatures
6512
6513 newObject.valueBeforeDecode = inputObject.valueBeforeDecode.slice(0);
6514 return newObject;
6515 } //endregion
6516 //region Create a basic ASN.1 type since we need to return errors and warnings from the function
6517
6518
6519 let returnObject = new BaseBlock({}, Object); //endregion
6520 //region Basic check for parameters
6521
6522 if ((0, utils.checkBufferParams)(new LocalBaseBlock(), inputBuffer, inputOffset, inputLength) === false) {
6523 returnObject.error = "Wrong input parameters";
6524 return {
6525 offset: -1,
6526 result: returnObject
6527 };
6528 } //endregion
6529 //region Getting Uint8Array from ArrayBuffer
6530
6531
6532 const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
6533 //region Initial checks
6534
6535 if (intBuffer.length === 0) {
6536 this.error = "Zero buffer length";
6537 return {
6538 offset: -1,
6539 result: returnObject
6540 };
6541 } //endregion
6542 //region Decode indentifcation block of ASN.1 BER structure
6543
6544
6545 let resultOffset = returnObject.idBlock.fromBER(inputBuffer, inputOffset, inputLength);
6546 returnObject.warnings.concat(returnObject.idBlock.warnings);
6547
6548 if (resultOffset === -1) {
6549 returnObject.error = returnObject.idBlock.error;
6550 return {
6551 offset: -1,
6552 result: returnObject
6553 };
6554 }
6555
6556 inputOffset = resultOffset;
6557 inputLength -= returnObject.idBlock.blockLength; //endregion
6558 //region Decode length block of ASN.1 BER structure
6559
6560 resultOffset = returnObject.lenBlock.fromBER(inputBuffer, inputOffset, inputLength);
6561 returnObject.warnings.concat(returnObject.lenBlock.warnings);
6562
6563 if (resultOffset === -1) {
6564 returnObject.error = returnObject.lenBlock.error;
6565 return {
6566 offset: -1,
6567 result: returnObject
6568 };
6569 }
6570
6571 inputOffset = resultOffset;
6572 inputLength -= returnObject.lenBlock.blockLength; //endregion
6573 //region Check for usign indefinite length form in encoding for primitive types
6574
6575 if (returnObject.idBlock.isConstructed === false && returnObject.lenBlock.isIndefiniteForm === true) {
6576 returnObject.error = "Indefinite length form used for primitive encoding form";
6577 return {
6578 offset: -1,
6579 result: returnObject
6580 };
6581 } //endregion
6582 //region Switch ASN.1 block type
6583
6584
6585 let newASN1Type = BaseBlock;
6586
6587 switch (returnObject.idBlock.tagClass) {
6588 //region UNIVERSAL
6589 case 1:
6590 //region Check for reserved tag numbers
6591 if (returnObject.idBlock.tagNumber >= 37 && returnObject.idBlock.isHexOnly === false) {
6592 returnObject.error = "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard";
6593 return {
6594 offset: -1,
6595 result: returnObject
6596 };
6597 } //endregion
6598
6599
6600 switch (returnObject.idBlock.tagNumber) {
6601 //region EndOfContent type
6602 case 0:
6603 //region Check for EndOfContent type
6604 if (returnObject.idBlock.isConstructed === true && returnObject.lenBlock.length > 0) {
6605 returnObject.error = "Type [UNIVERSAL 0] is reserved";
6606 return {
6607 offset: -1,
6608 result: returnObject
6609 };
6610 } //endregion
6611
6612
6613 newASN1Type = EndOfContent;
6614 break;
6615 //endregion
6616 //region Boolean type
6617
6618 case 1:
6619 newASN1Type = Boolean;
6620 break;
6621 //endregion
6622 //region Integer type
6623
6624 case 2:
6625 newASN1Type = Integer;
6626 break;
6627 //endregion
6628 //region BitString type
6629
6630 case 3:
6631 newASN1Type = BitString;
6632 break;
6633 //endregion
6634 //region OctetString type
6635
6636 case 4:
6637 newASN1Type = OctetString;
6638 break;
6639 //endregion
6640 //region Null type
6641
6642 case 5:
6643 newASN1Type = Null;
6644 break;
6645 //endregion
6646 //region OBJECT IDENTIFIER type
6647
6648 case 6:
6649 newASN1Type = ObjectIdentifier;
6650 break;
6651 //endregion
6652 //region Enumerated type
6653
6654 case 10:
6655 newASN1Type = Enumerated;
6656 break;
6657 //endregion
6658 //region Utf8String type
6659
6660 case 12:
6661 newASN1Type = Utf8String;
6662 break;
6663 //endregion
6664 //region Time type
6665
6666 case 14:
6667 newASN1Type = TIME;
6668 break;
6669 //endregion
6670 //region ASN.1 reserved type
6671
6672 case 15:
6673 returnObject.error = "[UNIVERSAL 15] is reserved by ASN.1 standard";
6674 return {
6675 offset: -1,
6676 result: returnObject
6677 };
6678 //endregion
6679 //region Sequence type
6680
6681 case 16:
6682 newASN1Type = Sequence;
6683 break;
6684 //endregion
6685 //region Set type
6686
6687 case 17:
6688 newASN1Type = Set;
6689 break;
6690 //endregion
6691 //region NumericString type
6692
6693 case 18:
6694 newASN1Type = NumericString;
6695 break;
6696 //endregion
6697 //region PrintableString type
6698
6699 case 19:
6700 newASN1Type = PrintableString;
6701 break;
6702 //endregion
6703 //region TeletexString type
6704
6705 case 20:
6706 newASN1Type = TeletexString;
6707 break;
6708 //endregion
6709 //region VideotexString type
6710
6711 case 21:
6712 newASN1Type = VideotexString;
6713 break;
6714 //endregion
6715 //region IA5String type
6716
6717 case 22:
6718 newASN1Type = IA5String;
6719 break;
6720 //endregion
6721 //region UTCTime type
6722
6723 case 23:
6724 newASN1Type = UTCTime;
6725 break;
6726 //endregion
6727 //region GeneralizedTime type
6728
6729 case 24:
6730 newASN1Type = GeneralizedTime;
6731 break;
6732 //endregion
6733 //region GraphicString type
6734
6735 case 25:
6736 newASN1Type = GraphicString;
6737 break;
6738 //endregion
6739 //region VisibleString type
6740
6741 case 26:
6742 newASN1Type = VisibleString;
6743 break;
6744 //endregion
6745 //region GeneralString type
6746
6747 case 27:
6748 newASN1Type = GeneralString;
6749 break;
6750 //endregion
6751 //region UniversalString type
6752
6753 case 28:
6754 newASN1Type = UniversalString;
6755 break;
6756 //endregion
6757 //region CharacterString type
6758
6759 case 29:
6760 newASN1Type = CharacterString;
6761 break;
6762 //endregion
6763 //region BmpString type
6764
6765 case 30:
6766 newASN1Type = BmpString;
6767 break;
6768 //endregion
6769 //region DATE type
6770
6771 case 31:
6772 newASN1Type = DATE;
6773 break;
6774 //endregion
6775 //region TimeOfDay type
6776
6777 case 32:
6778 newASN1Type = TimeOfDay;
6779 break;
6780 //endregion
6781 //region Date-Time type
6782
6783 case 33:
6784 newASN1Type = DateTime;
6785 break;
6786 //endregion
6787 //region Duration type
6788
6789 case 34:
6790 newASN1Type = Duration;
6791 break;
6792 //endregion
6793 //region default
6794
6795 default:
6796 {
6797 let newObject;
6798 if (returnObject.idBlock.isConstructed === true) newObject = new Constructed();else newObject = new Primitive();
6799 newObject.idBlock = returnObject.idBlock;
6800 newObject.lenBlock = returnObject.lenBlock;
6801 newObject.warnings = returnObject.warnings;
6802 returnObject = newObject;
6803 resultOffset = returnObject.fromBER(inputBuffer, inputOffset, inputLength);
6804 }
6805 //endregion
6806 }
6807
6808 break;
6809 //endregion
6810 //region All other tag classes
6811
6812 case 2: // APPLICATION
6813
6814 case 3: // CONTEXT-SPECIFIC
6815
6816 case 4: // PRIVATE
6817
6818 default:
6819 {
6820 if (returnObject.idBlock.isConstructed === true) newASN1Type = Constructed;else newASN1Type = Primitive;
6821 }
6822 //endregion
6823 } //endregion
6824 //region Change type and perform BER decoding
6825
6826
6827 returnObject = localChangeType(returnObject, newASN1Type);
6828 resultOffset = returnObject.fromBER(inputBuffer, inputOffset, returnObject.lenBlock.isIndefiniteForm === true ? inputLength : returnObject.lenBlock.length); //endregion
6829 //region Coping incoming buffer for entire ASN.1 block
6830
6831 returnObject.valueBeforeDecode = inputBuffer.slice(incomingOffset, incomingOffset + returnObject.blockLength); //endregion
6832
6833 return {
6834 offset: resultOffset,
6835 result: returnObject
6836 };
6837 } //**************************************************************************************
6838
6839 /**
6840 * Major function for decoding ASN.1 BER array into internal library structuries
6841 * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array of bytes
6842 */
6843
6844
6845 function fromBER(inputBuffer) {
6846 if (inputBuffer.byteLength === 0) {
6847 const result = new BaseBlock({}, Object);
6848 result.error = "Input buffer has zero length";
6849 return {
6850 offset: -1,
6851 result
6852 };
6853 }
6854
6855 return LocalFromBER(inputBuffer, 0, inputBuffer.byteLength);
6856 } //**************************************************************************************
6857 //endregion
6858 //**************************************************************************************
6859 //region Major scheme verification function
6860 //**************************************************************************************
6861
6862 /**
6863 * Compare of two ASN.1 object trees
6864 * @param {!Object} root Root of input ASN.1 object tree
6865 * @param {!Object} inputData Input ASN.1 object tree
6866 * @param {!Object} inputSchema Input ASN.1 schema to compare with
6867 * @return {{verified: boolean}|{verified:boolean, result: Object}}
6868 */
6869
6870
6871 function compareSchema(root, inputData, inputSchema) {
6872 //region Special case for Choice schema element type
6873 if (inputSchema instanceof Choice) {
6874 for (let j = 0; j < inputSchema.value.length; j++) {
6875 const result = compareSchema(root, inputData, inputSchema.value[j]);
6876
6877 if (result.verified === true) {
6878 return {
6879 verified: true,
6880 result: root
6881 };
6882 }
6883 }
6884
6885 {
6886 const _result = {
6887 verified: false,
6888 result: {
6889 error: "Wrong values for Choice type"
6890 }
6891 };
6892 if (inputSchema.hasOwnProperty("name")) _result.name = inputSchema.name;
6893 return _result;
6894 }
6895 } //endregion
6896 //region Special case for Any schema element type
6897
6898
6899 if (inputSchema instanceof Any) {
6900 //region Add named component of ASN.1 schema
6901 if (inputSchema.hasOwnProperty("name")) root[inputSchema.name] = inputData; //endregion
6902
6903 return {
6904 verified: true,
6905 result: root
6906 };
6907 } //endregion
6908 //region Initial check
6909
6910
6911 if (root instanceof Object === false) {
6912 return {
6913 verified: false,
6914 result: {
6915 error: "Wrong root object"
6916 }
6917 };
6918 }
6919
6920 if (inputData instanceof Object === false) {
6921 return {
6922 verified: false,
6923 result: {
6924 error: "Wrong ASN.1 data"
6925 }
6926 };
6927 }
6928
6929 if (inputSchema instanceof Object === false) {
6930 return {
6931 verified: false,
6932 result: {
6933 error: "Wrong ASN.1 schema"
6934 }
6935 };
6936 }
6937
6938 if ("idBlock" in inputSchema === false) {
6939 return {
6940 verified: false,
6941 result: {
6942 error: "Wrong ASN.1 schema"
6943 }
6944 };
6945 } //endregion
6946 //region Comparing idBlock properties in ASN.1 data and ASN.1 schema
6947 //region Encode and decode ASN.1 schema idBlock
6948 /// <remarks>This encoding/decoding is neccessary because could be an errors in schema definition</remarks>
6949
6950
6951 if ("fromBER" in inputSchema.idBlock === false) {
6952 return {
6953 verified: false,
6954 result: {
6955 error: "Wrong ASN.1 schema"
6956 }
6957 };
6958 }
6959
6960 if ("toBER" in inputSchema.idBlock === false) {
6961 return {
6962 verified: false,
6963 result: {
6964 error: "Wrong ASN.1 schema"
6965 }
6966 };
6967 }
6968
6969 const encodedId = inputSchema.idBlock.toBER(false);
6970
6971 if (encodedId.byteLength === 0) {
6972 return {
6973 verified: false,
6974 result: {
6975 error: "Error encoding idBlock for ASN.1 schema"
6976 }
6977 };
6978 }
6979
6980 const decodedOffset = inputSchema.idBlock.fromBER(encodedId, 0, encodedId.byteLength);
6981
6982 if (decodedOffset === -1) {
6983 return {
6984 verified: false,
6985 result: {
6986 error: "Error decoding idBlock for ASN.1 schema"
6987 }
6988 };
6989 } //endregion
6990 //region tagClass
6991
6992
6993 if (inputSchema.idBlock.hasOwnProperty("tagClass") === false) {
6994 return {
6995 verified: false,
6996 result: {
6997 error: "Wrong ASN.1 schema"
6998 }
6999 };
7000 }
7001
7002 if (inputSchema.idBlock.tagClass !== inputData.idBlock.tagClass) {
7003 return {
7004 verified: false,
7005 result: root
7006 };
7007 } //endregion
7008 //region tagNumber
7009
7010
7011 if (inputSchema.idBlock.hasOwnProperty("tagNumber") === false) {
7012 return {
7013 verified: false,
7014 result: {
7015 error: "Wrong ASN.1 schema"
7016 }
7017 };
7018 }
7019
7020 if (inputSchema.idBlock.tagNumber !== inputData.idBlock.tagNumber) {
7021 return {
7022 verified: false,
7023 result: root
7024 };
7025 } //endregion
7026 //region isConstructed
7027
7028
7029 if (inputSchema.idBlock.hasOwnProperty("isConstructed") === false) {
7030 return {
7031 verified: false,
7032 result: {
7033 error: "Wrong ASN.1 schema"
7034 }
7035 };
7036 }
7037
7038 if (inputSchema.idBlock.isConstructed !== inputData.idBlock.isConstructed) {
7039 return {
7040 verified: false,
7041 result: root
7042 };
7043 } //endregion
7044 //region isHexOnly
7045
7046
7047 if ("isHexOnly" in inputSchema.idBlock === false) // Since 'isHexOnly' is an inhirited property
7048 {
7049 return {
7050 verified: false,
7051 result: {
7052 error: "Wrong ASN.1 schema"
7053 }
7054 };
7055 }
7056
7057 if (inputSchema.idBlock.isHexOnly !== inputData.idBlock.isHexOnly) {
7058 return {
7059 verified: false,
7060 result: root
7061 };
7062 } //endregion
7063 //region valueHex
7064
7065
7066 if (inputSchema.idBlock.isHexOnly === true) {
7067 if ("valueHex" in inputSchema.idBlock === false) // Since 'valueHex' is an inhirited property
7068 {
7069 return {
7070 verified: false,
7071 result: {
7072 error: "Wrong ASN.1 schema"
7073 }
7074 };
7075 }
7076
7077 const schemaView = new Uint8Array(inputSchema.idBlock.valueHex);
7078 const asn1View = new Uint8Array(inputData.idBlock.valueHex);
7079
7080 if (schemaView.length !== asn1View.length) {
7081 return {
7082 verified: false,
7083 result: root
7084 };
7085 }
7086
7087 for (let i = 0; i < schemaView.length; i++) {
7088 if (schemaView[i] !== asn1View[1]) {
7089 return {
7090 verified: false,
7091 result: root
7092 };
7093 }
7094 }
7095 } //endregion
7096 //endregion
7097 //region Add named component of ASN.1 schema
7098
7099
7100 if (inputSchema.hasOwnProperty("name")) {
7101 inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
7102 if (inputSchema.name !== "") root[inputSchema.name] = inputData;
7103 } //endregion
7104 //region Getting next ASN.1 block for comparition
7105
7106
7107 if (inputSchema.idBlock.isConstructed === true) {
7108 let admission = 0;
7109 let result = {
7110 verified: false
7111 };
7112 let maxLength = inputSchema.valueBlock.value.length;
7113
7114 if (maxLength > 0) {
7115 if (inputSchema.valueBlock.value[0] instanceof Repeated) maxLength = inputData.valueBlock.value.length;
7116 } //region Special case when constructive value has no elements
7117
7118
7119 if (maxLength === 0) {
7120 return {
7121 verified: true,
7122 result: root
7123 };
7124 } //endregion
7125 //region Special case when "inputData" has no values and "inputSchema" has all optional values
7126
7127
7128 if (inputData.valueBlock.value.length === 0 && inputSchema.valueBlock.value.length !== 0) {
7129 let _optional = true;
7130
7131 for (let i = 0; i < inputSchema.valueBlock.value.length; i++) _optional = _optional && (inputSchema.valueBlock.value[i].optional || false);
7132
7133 if (_optional === true) {
7134 return {
7135 verified: true,
7136 result: root
7137 };
7138 } //region Delete early added name of block
7139
7140
7141 if (inputSchema.hasOwnProperty("name")) {
7142 inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
7143 if (inputSchema.name !== "") delete root[inputSchema.name];
7144 } //endregion
7145
7146
7147 root.error = "Inconsistent object length";
7148 return {
7149 verified: false,
7150 result: root
7151 };
7152 } //endregion
7153
7154
7155 for (let i = 0; i < maxLength; i++) {
7156 //region Special case when there is an "optional" element of ASN.1 schema at the end
7157 if (i - admission >= inputData.valueBlock.value.length) {
7158 if (inputSchema.valueBlock.value[i].optional === false) {
7159 const _result = {
7160 verified: false,
7161 result: root
7162 };
7163 root.error = "Inconsistent length between ASN.1 data and schema"; //region Delete early added name of block
7164
7165 if (inputSchema.hasOwnProperty("name")) {
7166 inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
7167
7168 if (inputSchema.name !== "") {
7169 delete root[inputSchema.name];
7170 _result.name = inputSchema.name;
7171 }
7172 } //endregion
7173
7174
7175 return _result;
7176 }
7177 } //endregion
7178 else {
7179 //region Special case for Repeated type of ASN.1 schema element
7180 if (inputSchema.valueBlock.value[0] instanceof Repeated) {
7181 result = compareSchema(root, inputData.valueBlock.value[i], inputSchema.valueBlock.value[0].value);
7182
7183 if (result.verified === false) {
7184 if (inputSchema.valueBlock.value[0].optional === true) admission++;else {
7185 //region Delete early added name of block
7186 if (inputSchema.hasOwnProperty("name")) {
7187 inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
7188 if (inputSchema.name !== "") delete root[inputSchema.name];
7189 } //endregion
7190
7191
7192 return result;
7193 }
7194 }
7195
7196 if ("name" in inputSchema.valueBlock.value[0] && inputSchema.valueBlock.value[0].name.length > 0) {
7197 let arrayRoot = {};
7198 if ("local" in inputSchema.valueBlock.value[0] && inputSchema.valueBlock.value[0].local === true) arrayRoot = inputData;else arrayRoot = root;
7199 if (typeof arrayRoot[inputSchema.valueBlock.value[0].name] === "undefined") arrayRoot[inputSchema.valueBlock.value[0].name] = [];
7200 arrayRoot[inputSchema.valueBlock.value[0].name].push(inputData.valueBlock.value[i]);
7201 }
7202 } //endregion
7203 else {
7204 result = compareSchema(root, inputData.valueBlock.value[i - admission], inputSchema.valueBlock.value[i]);
7205
7206 if (result.verified === false) {
7207 if (inputSchema.valueBlock.value[i].optional === true) admission++;else {
7208 //region Delete early added name of block
7209 if (inputSchema.hasOwnProperty("name")) {
7210 inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
7211 if (inputSchema.name !== "") delete root[inputSchema.name];
7212 } //endregion
7213
7214
7215 return result;
7216 }
7217 }
7218 }
7219 }
7220 }
7221
7222 if (result.verified === false) // The situation may take place if last element is "optional" and verification failed
7223 {
7224 const _result = {
7225 verified: false,
7226 result: root
7227 }; //region Delete early added name of block
7228
7229 if (inputSchema.hasOwnProperty("name")) {
7230 inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
7231
7232 if (inputSchema.name !== "") {
7233 delete root[inputSchema.name];
7234 _result.name = inputSchema.name;
7235 }
7236 } //endregion
7237
7238
7239 return _result;
7240 }
7241
7242 return {
7243 verified: true,
7244 result: root
7245 };
7246 } //endregion
7247 //region Ability to parse internal value for primitive-encoded value (value of OctetString, for example)
7248
7249
7250 if ("primitiveSchema" in inputSchema && "valueHex" in inputData.valueBlock) {
7251 //region Decoding of raw ASN.1 data
7252 const asn1 = fromBER(inputData.valueBlock.valueHex);
7253
7254 if (asn1.offset === -1) {
7255 const _result = {
7256 verified: false,
7257 result: asn1.result
7258 }; //region Delete early added name of block
7259
7260 if (inputSchema.hasOwnProperty("name")) {
7261 inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
7262
7263 if (inputSchema.name !== "") {
7264 delete root[inputSchema.name];
7265 _result.name = inputSchema.name;
7266 }
7267 } //endregion
7268
7269
7270 return _result;
7271 } //endregion
7272
7273
7274 return compareSchema(root, asn1.result, inputSchema.primitiveSchema);
7275 }
7276
7277 return {
7278 verified: true,
7279 result: root
7280 }; //endregion
7281 } //**************************************************************************************
7282 //noinspection JSUnusedGlobalSymbols
7283
7284 /**
7285 * ASN.1 schema verification for ArrayBuffer data
7286 * @param {!ArrayBuffer} inputBuffer Input BER-encoded ASN.1 data
7287 * @param {!Object} inputSchema Input ASN.1 schema to verify against to
7288 * @return {{verified: boolean}|{verified:boolean, result: Object}}
7289 */
7290
7291
7292 function verifySchema(inputBuffer, inputSchema) {
7293 //region Initial check
7294 if (inputSchema instanceof Object === false) {
7295 return {
7296 verified: false,
7297 result: {
7298 error: "Wrong ASN.1 schema type"
7299 }
7300 };
7301 } //endregion
7302 //region Decoding of raw ASN.1 data
7303
7304
7305 const asn1 = fromBER(inputBuffer);
7306
7307 if (asn1.offset === -1) {
7308 return {
7309 verified: false,
7310 result: asn1.result
7311 };
7312 } //endregion
7313 //region Compare ASN.1 struct with input schema
7314
7315
7316 return compareSchema(asn1.result, asn1.result, inputSchema); //endregion
7317 } //**************************************************************************************
7318 //endregion
7319 //**************************************************************************************
7320 //region Major function converting JSON to ASN.1 objects
7321 //**************************************************************************************
7322 //noinspection JSUnusedGlobalSymbols
7323
7324 /**
7325 * Converting from JSON to ASN.1 objects
7326 * @param {string|Object} json JSON string or object to convert to ASN.1 objects
7327 */
7328
7329
7330 function fromJSON(json) {} // TODO Implement
7331 //**************************************************************************************
7332 //endregion
7333 //**************************************************************************************
7334
7335 });
7336 unwrapExports(asn1);
7337 var asn1_1 = asn1.RawData;
7338 var asn1_2 = asn1.Repeated;
7339 var asn1_3 = asn1.Any;
7340 var asn1_4 = asn1.Choice;
7341 var asn1_5 = asn1.TIME;
7342 var asn1_6 = asn1.Duration;
7343 var asn1_7 = asn1.DateTime;
7344 var asn1_8 = asn1.TimeOfDay;
7345 var asn1_9 = asn1.DATE;
7346 var asn1_10 = asn1.GeneralizedTime;
7347 var asn1_11 = asn1.UTCTime;
7348 var asn1_12 = asn1.CharacterString;
7349 var asn1_13 = asn1.GeneralString;
7350 var asn1_14 = asn1.VisibleString;
7351 var asn1_15 = asn1.GraphicString;
7352 var asn1_16 = asn1.IA5String;
7353 var asn1_17 = asn1.VideotexString;
7354 var asn1_18 = asn1.TeletexString;
7355 var asn1_19 = asn1.PrintableString;
7356 var asn1_20 = asn1.NumericString;
7357 var asn1_21 = asn1.UniversalString;
7358 var asn1_22 = asn1.BmpString;
7359 var asn1_23 = asn1.Utf8String;
7360 var asn1_24 = asn1.ObjectIdentifier;
7361 var asn1_25 = asn1.Enumerated;
7362 var asn1_26 = asn1.Integer;
7363 var asn1_27 = asn1.BitString;
7364 var asn1_28 = asn1.OctetString;
7365 var asn1_29 = asn1.Null;
7366 var asn1_30 = asn1.Set;
7367 var asn1_31 = asn1.Sequence;
7368 var asn1_32 = asn1.Boolean;
7369 var asn1_33 = asn1.EndOfContent;
7370 var asn1_34 = asn1.Constructed;
7371 var asn1_35 = asn1.Primitive;
7372 var asn1_36 = asn1.BaseBlock;
7373 var asn1_37 = asn1.fromBER;
7374 var asn1_38 = asn1.compareSchema;
7375 var asn1_39 = asn1.verifySchema;
7376 var asn1_40 = asn1.fromJSON;
7377 var build = createCommonjsModule(function (module, exports) {
7378 Object.defineProperty(exports, '__esModule', {
7379 value: true
7380 });
7381 const AsnAnyConverter = {
7382 fromASN: value => value instanceof asn1.Null ? null : value.valueBeforeDecode,
7383 toASN: value => {
7384 if (value === null) {
7385 return new asn1.Null();
7386 }
7387
7388 const schema = asn1.fromBER(value);
7389
7390 if (schema.result.error) {
7391 throw new Error(schema.result.error);
7392 }
7393
7394 return schema.result;
7395 }
7396 };
7397 const AsnIntegerConverter = {
7398 fromASN: value => !value.valueBlock.valueDec && value.valueBlock.valueHex.byteLength > 0 ? value.valueBlock.toString() : value.valueBlock.valueDec,
7399 toASN: value => new asn1.Integer({
7400 value
7401 })
7402 };
7403 const AsnEnumeratedConverter = {
7404 fromASN: value => value.valueBlock.valueDec,
7405 toASN: value => new asn1.Enumerated({
7406 value
7407 })
7408 };
7409 const AsnIntegerArrayBufferConverter = {
7410 fromASN: value => value.valueBlock.valueHex,
7411 toASN: value => new asn1.Integer({
7412 valueHex: value
7413 })
7414 };
7415 const AsnBitStringConverter = {
7416 fromASN: value => value.valueBlock.valueHex,
7417 toASN: value => new asn1.BitString({
7418 valueHex: value
7419 })
7420 };
7421 const AsnObjectIdentifierConverter = {
7422 fromASN: value => value.valueBlock.toString(),
7423 toASN: value => new asn1.ObjectIdentifier({
7424 value
7425 })
7426 };
7427 const AsnBooleanConverter = {
7428 fromASN: value => value.valueBlock.value,
7429 toASN: value => new asn1.Boolean({
7430 value
7431 })
7432 };
7433 const AsnOctetStringConverter = {
7434 fromASN: value => value.valueBlock.valueHex,
7435 toASN: value => new asn1.OctetString({
7436 valueHex: value
7437 })
7438 };
7439
7440 function createStringConverter(Asn1Type) {
7441 return {
7442 fromASN: value => value.valueBlock.value,
7443 toASN: value => new Asn1Type({
7444 value
7445 })
7446 };
7447 }
7448
7449 const AsnUtf8StringConverter = createStringConverter(asn1.Utf8String);
7450 const AsnBmpStringConverter = createStringConverter(asn1.BmpString);
7451 const AsnUniversalStringConverter = createStringConverter(asn1.UniversalString);
7452 const AsnNumericStringConverter = createStringConverter(asn1.NumericString);
7453 const AsnPrintableStringConverter = createStringConverter(asn1.PrintableString);
7454 const AsnTeletexStringConverter = createStringConverter(asn1.TeletexString);
7455 const AsnVideotexStringConverter = createStringConverter(asn1.VideotexString);
7456 const AsnIA5StringConverter = createStringConverter(asn1.IA5String);
7457 const AsnGraphicStringConverter = createStringConverter(asn1.GraphicString);
7458 const AsnVisibleStringConverter = createStringConverter(asn1.VisibleString);
7459 const AsnGeneralStringConverter = createStringConverter(asn1.GeneralString);
7460 const AsnCharacterStringConverter = createStringConverter(asn1.CharacterString);
7461 const AsnUTCTimeConverter = {
7462 fromASN: value => value.toDate(),
7463 toASN: value => new asn1.UTCTime({
7464 valueDate: value
7465 })
7466 };
7467 const AsnGeneralizedTimeConverter = {
7468 fromASN: value => value.toDate(),
7469 toASN: value => new asn1.GeneralizedTime({
7470 valueDate: value
7471 })
7472 };
7473 var defaultConverters =
7474 /*#__PURE__*/
7475 Object.freeze({
7476 AsnAnyConverter: AsnAnyConverter,
7477 AsnIntegerConverter: AsnIntegerConverter,
7478 AsnEnumeratedConverter: AsnEnumeratedConverter,
7479 AsnIntegerArrayBufferConverter: AsnIntegerArrayBufferConverter,
7480 AsnBitStringConverter: AsnBitStringConverter,
7481 AsnObjectIdentifierConverter: AsnObjectIdentifierConverter,
7482 AsnBooleanConverter: AsnBooleanConverter,
7483 AsnOctetStringConverter: AsnOctetStringConverter,
7484 AsnUtf8StringConverter: AsnUtf8StringConverter,
7485 AsnBmpStringConverter: AsnBmpStringConverter,
7486 AsnUniversalStringConverter: AsnUniversalStringConverter,
7487 AsnNumericStringConverter: AsnNumericStringConverter,
7488 AsnPrintableStringConverter: AsnPrintableStringConverter,
7489 AsnTeletexStringConverter: AsnTeletexStringConverter,
7490 AsnVideotexStringConverter: AsnVideotexStringConverter,
7491 AsnIA5StringConverter: AsnIA5StringConverter,
7492 AsnGraphicStringConverter: AsnGraphicStringConverter,
7493 AsnVisibleStringConverter: AsnVisibleStringConverter,
7494 AsnGeneralStringConverter: AsnGeneralStringConverter,
7495 AsnCharacterStringConverter: AsnCharacterStringConverter,
7496 AsnUTCTimeConverter: AsnUTCTimeConverter,
7497 AsnGeneralizedTimeConverter: AsnGeneralizedTimeConverter
7498 });
7499
7500 (function (AsnTypeTypes) {
7501 AsnTypeTypes[AsnTypeTypes["Sequence"] = 0] = "Sequence";
7502 AsnTypeTypes[AsnTypeTypes["Set"] = 1] = "Set";
7503 AsnTypeTypes[AsnTypeTypes["Choice"] = 2] = "Choice";
7504 })(exports.AsnTypeTypes || (exports.AsnTypeTypes = {}));
7505
7506 (function (AsnPropTypes) {
7507 AsnPropTypes[AsnPropTypes["Any"] = 0] = "Any";
7508 AsnPropTypes[AsnPropTypes["Boolean"] = 1] = "Boolean";
7509 AsnPropTypes[AsnPropTypes["OctetString"] = 2] = "OctetString";
7510 AsnPropTypes[AsnPropTypes["BitString"] = 3] = "BitString";
7511 AsnPropTypes[AsnPropTypes["Integer"] = 4] = "Integer";
7512 AsnPropTypes[AsnPropTypes["Enumerated"] = 5] = "Enumerated";
7513 AsnPropTypes[AsnPropTypes["ObjectIdentifier"] = 6] = "ObjectIdentifier";
7514 AsnPropTypes[AsnPropTypes["Utf8String"] = 7] = "Utf8String";
7515 AsnPropTypes[AsnPropTypes["BmpString"] = 8] = "BmpString";
7516 AsnPropTypes[AsnPropTypes["UniversalString"] = 9] = "UniversalString";
7517 AsnPropTypes[AsnPropTypes["NumericString"] = 10] = "NumericString";
7518 AsnPropTypes[AsnPropTypes["PrintableString"] = 11] = "PrintableString";
7519 AsnPropTypes[AsnPropTypes["TeletexString"] = 12] = "TeletexString";
7520 AsnPropTypes[AsnPropTypes["VideotexString"] = 13] = "VideotexString";
7521 AsnPropTypes[AsnPropTypes["IA5String"] = 14] = "IA5String";
7522 AsnPropTypes[AsnPropTypes["GraphicString"] = 15] = "GraphicString";
7523 AsnPropTypes[AsnPropTypes["VisibleString"] = 16] = "VisibleString";
7524 AsnPropTypes[AsnPropTypes["GeneralString"] = 17] = "GeneralString";
7525 AsnPropTypes[AsnPropTypes["CharacterString"] = 18] = "CharacterString";
7526 AsnPropTypes[AsnPropTypes["UTCTime"] = 19] = "UTCTime";
7527 AsnPropTypes[AsnPropTypes["GeneralizedTime"] = 20] = "GeneralizedTime";
7528 AsnPropTypes[AsnPropTypes["DATE"] = 21] = "DATE";
7529 AsnPropTypes[AsnPropTypes["TimeOfDay"] = 22] = "TimeOfDay";
7530 AsnPropTypes[AsnPropTypes["DateTime"] = 23] = "DateTime";
7531 AsnPropTypes[AsnPropTypes["Duration"] = 24] = "Duration";
7532 AsnPropTypes[AsnPropTypes["TIME"] = 25] = "TIME";
7533 AsnPropTypes[AsnPropTypes["Null"] = 26] = "Null";
7534 })(exports.AsnPropTypes || (exports.AsnPropTypes = {}));
7535
7536 const asn1$1 = asn1;
7537
7538 class AsnSchemaStorage {
7539 constructor() {
7540 this.items = new Map();
7541 }
7542
7543 has(target) {
7544 return this.items.has(target);
7545 }
7546
7547 get(target) {
7548 const schema = this.items.get(target);
7549
7550 if (!schema) {
7551 throw new Error("Cannot get schema for current target");
7552 }
7553
7554 return schema;
7555 }
7556
7557 cache(target) {
7558 const schema = this.get(target);
7559
7560 if (!schema.schema) {
7561 schema.schema = this.create(target, true);
7562 }
7563 }
7564
7565 createDefault(target) {
7566 const schema = {
7567 type: exports.AsnTypeTypes.Sequence,
7568 items: {}
7569 };
7570 const parentSchema = this.findParentSchema(target);
7571
7572 if (parentSchema) {
7573 Object.assign(schema, parentSchema);
7574 schema.items = Object.assign({}, schema.items, parentSchema.items);
7575 }
7576
7577 return schema;
7578 }
7579
7580 create(target, useNames) {
7581 const schema = this.items.get(target) || this.createDefault(target);
7582 const asn1Value = [];
7583
7584 for (const key in schema.items) {
7585 const item = schema.items[key];
7586 const name = useNames ? key : "";
7587 let asn1Item;
7588
7589 if (typeof item.type === "number") {
7590 const Asn1TypeName = exports.AsnPropTypes[item.type];
7591 const Asn1Type = asn1$1[Asn1TypeName];
7592
7593 if (!Asn1Type) {
7594 throw new Error(`Cannot get ASN1 class by name '${Asn1TypeName}'`);
7595 }
7596
7597 asn1Item = new Asn1Type({
7598 name
7599 });
7600 } else {
7601 asn1Item = new asn1$1.Any({
7602 name
7603 });
7604 }
7605
7606 const optional = !!item.optional || item.defaultValue !== undefined;
7607
7608 if (item.repeated) {
7609 asn1Item.name = "";
7610 asn1Item = new asn1$1.Repeated({
7611 name,
7612 value: asn1Item
7613 });
7614 }
7615
7616 if (item.context !== null && item.context !== undefined) {
7617 if (item.implicit) {
7618 if (typeof item.type === "number") {
7619 asn1Value.push(new asn1$1.Primitive({
7620 name,
7621 optional,
7622 idBlock: {
7623 tagClass: 3,
7624 tagNumber: item.context
7625 }
7626 }));
7627 } else {
7628 this.cache(item.type);
7629 const value = this.get(item.type).schema.valueBlock.value;
7630 asn1Value.push(new asn1$1.Constructed({
7631 name,
7632 optional,
7633 idBlock: {
7634 tagClass: 3,
7635 tagNumber: item.context
7636 },
7637 value
7638 }));
7639 }
7640 } else {
7641 asn1Value.push(new asn1$1.Constructed({
7642 optional,
7643 idBlock: {
7644 tagClass: 3,
7645 tagNumber: item.context
7646 },
7647 value: [asn1Item]
7648 }));
7649 }
7650 } else {
7651 asn1Item.optional = optional;
7652 asn1Value.push(asn1Item);
7653 }
7654 }
7655
7656 switch (schema.type) {
7657 case exports.AsnTypeTypes.Sequence:
7658 return new asn1$1.Sequence({
7659 value: asn1Value,
7660 name: ""
7661 });
7662
7663 case exports.AsnTypeTypes.Set:
7664 return new asn1$1.Set({
7665 value: asn1Value,
7666 name: ""
7667 });
7668
7669 case exports.AsnTypeTypes.Choice:
7670 return new asn1$1.Choice({
7671 value: asn1Value,
7672 name: ""
7673 });
7674
7675 default:
7676 throw new Error(`Unsupported ASN1 type in use`);
7677 }
7678 }
7679
7680 set(target, schema) {
7681 this.items.set(target, schema);
7682 return this;
7683 }
7684
7685 findParentSchema(target) {
7686 const parent = target.__proto__;
7687
7688 if (parent) {
7689 const schema = this.items.get(parent);
7690 return schema || this.findParentSchema(parent);
7691 }
7692
7693 return null;
7694 }
7695
7696 }
7697
7698 const schemaStorage = new AsnSchemaStorage();
7699
7700 const AsnType = options => target => {
7701 const schema = schemaStorage.get(target);
7702 Object.assign(schema, options);
7703 };
7704
7705 const AsnProp = options => (target, propertyKey) => {
7706 let schema;
7707
7708 if (!schemaStorage.has(target.constructor)) {
7709 schema = schemaStorage.createDefault(target.constructor);
7710 schemaStorage.set(target.constructor, schema);
7711 } else {
7712 schema = schemaStorage.get(target.constructor);
7713 }
7714
7715 const copyOptions = Object.assign({}, options);
7716
7717 if (typeof copyOptions.type === "number" && !copyOptions.converter) {
7718 const converterName = `Asn${exports.AsnPropTypes[options.type]}Converter`;
7719 const defaultConverter = defaultConverters[converterName];
7720
7721 if (!defaultConverter) {
7722 throw new Error(`Cannot get '${converterName}' for property '${propertyKey}' of ${target.constructor.name}`);
7723 }
7724
7725 copyOptions.converter = defaultConverter;
7726 }
7727
7728 schema.items[propertyKey] = copyOptions;
7729 };
7730
7731 function isConvertible(target) {
7732 if (target && target.prototype) {
7733 if (target.prototype.toASN && target.prototype.fromASN) {
7734 return true;
7735 } else {
7736 return isConvertible(target.prototype);
7737 }
7738 } else {
7739 return !!(target && target.toASN && target.fromASN);
7740 }
7741 }
7742
7743 const asn1$2 = asn1;
7744
7745 class AsnParser {
7746 static parse(data, target, obj) {
7747 let buf;
7748
7749 if (data instanceof ArrayBuffer) {
7750 buf = data;
7751 } else if (typeof Buffer !== undefined && Buffer.isBuffer(data)) {
7752 buf = new Uint8Array(data).buffer;
7753 } else if (ArrayBuffer.isView(data)) {
7754 buf = data.buffer;
7755 } else {
7756 throw new TypeError("Wrong type of 'data' argument");
7757 }
7758
7759 const asn1Parsed = asn1$2.fromBER(buf);
7760
7761 if (asn1Parsed.result.error) {
7762 throw new Error(asn1Parsed.result.error);
7763 }
7764
7765 const res = this.fromASN(asn1Parsed.result, target, obj);
7766 return res;
7767 }
7768
7769 static fromASN(asn1Schema, target, obj) {
7770 if (isConvertible(target)) {
7771 const value = obj || new target();
7772 return value.fromASN(asn1Schema);
7773 }
7774
7775 const schema = schemaStorage.get(target);
7776 schemaStorage.cache(target);
7777 let targetSchema = schema.schema;
7778
7779 if (asn1Schema.constructor === asn1$2.Constructed && schema.type !== exports.AsnTypeTypes.Choice) {
7780 targetSchema = new asn1$2.Constructed({
7781 idBlock: {
7782 tagClass: 3,
7783 tagNumber: asn1Schema.idBlock.tagNumber
7784 },
7785 value: schema.schema.valueBlock.value
7786 });
7787
7788 for (const key in schema.items) {
7789 delete asn1Schema[key];
7790 }
7791 }
7792
7793 const asn1ComparedSchema = asn1$2.compareSchema(asn1Schema, asn1Schema, targetSchema);
7794
7795 if (!asn1ComparedSchema.verified) {
7796 throw new Error(`Data does not match to ${target.name} ASN1 schema. ${asn1ComparedSchema.result.error}`);
7797 }
7798
7799 const res = obj || new target();
7800
7801 for (const key in schema.items) {
7802 if (!asn1Schema[key]) {
7803 continue;
7804 }
7805
7806 const schemaItem = schema.items[key];
7807
7808 if (typeof schemaItem.type === "number") {
7809 const converter = schemaItem.converter;
7810
7811 if (!converter) {
7812 throw new Error("Converter is empty");
7813 }
7814
7815 if (schemaItem.repeated) {
7816 res[key] = Array.from(asn1Schema[key], element => converter.fromASN(element));
7817 } else {
7818 let value = asn1Schema[key];
7819
7820 if (schemaItem.implicit) {
7821 const Asn1TypeName = exports.AsnPropTypes[schemaItem.type];
7822 const Asn1Type = asn1$2[Asn1TypeName];
7823
7824 if (!Asn1Type) {
7825 throw new Error(`Cannot get '${Asn1TypeName}' class from asn1js module`);
7826 }
7827
7828 const newItem = new Asn1Type();
7829 newItem.valueBlock = value.valueBlock;
7830 value = asn1$2.fromBER(newItem.toBER(false)).result;
7831 }
7832
7833 res[key] = converter.fromASN(value);
7834 }
7835 } else {
7836 if (schemaItem.repeated) {
7837 res[key] = Array.from(asn1Schema[key], element => this.fromASN(element, schemaItem.type));
7838 } else {
7839 res[key] = this.fromASN(asn1Schema[key], schemaItem.type);
7840 }
7841 }
7842 }
7843
7844 res._cache = {
7845 asn1: asn1Schema
7846 };
7847 return res;
7848 }
7849
7850 }
7851
7852 const asn1$3 = asn1;
7853
7854 class AsnSerializer {
7855 static serialize(obj) {
7856 return this.toASN(obj).toBER(false);
7857 }
7858
7859 static toASN(obj) {
7860 if (obj && isConvertible(obj.constructor)) {
7861 return obj.toASN();
7862 }
7863
7864 const target = obj.constructor;
7865 const schema = schemaStorage.get(target);
7866 schemaStorage.cache(target);
7867 let asn1Value = [];
7868
7869 for (const key in schema.items) {
7870 const item = schema.items[key];
7871 const objProp = obj[key];
7872
7873 if (objProp === undefined || item.defaultValue === objProp) {
7874 continue;
7875 }
7876
7877 let asn1Item;
7878
7879 if (typeof item.type === "number") {
7880 const converter = item.converter;
7881
7882 if (!converter) {
7883 throw new Error(`Property '${key}' doesn't have converter for type ${exports.AsnPropTypes[item.type]} in schema '${target.name}'`);
7884 }
7885
7886 if (item.repeated) {
7887 asn1Item = Array.from(objProp, element => converter.toASN(element));
7888 } else {
7889 asn1Item = converter.toASN(objProp);
7890 }
7891 } else {
7892 if (item.repeated) {
7893 asn1Item = Array.from(objProp, element => this.toASN(element));
7894 } else {
7895 asn1Item = this.toASN(objProp);
7896 }
7897 }
7898
7899 if (item.context !== null && item.context !== undefined) {
7900 if (item.implicit) {
7901 if (typeof item.type === "number") {
7902 const value = {};
7903 value.valueHex = asn1Item.valueBlock.toBER();
7904 asn1Value.push(new asn1$3.Primitive(_objectSpread({
7905 optional: item.optional,
7906 idBlock: {
7907 tagClass: 3,
7908 tagNumber: item.context
7909 }
7910 }, value)));
7911 } else {
7912 asn1Value.push(new asn1$3.Constructed({
7913 optional: item.optional,
7914 idBlock: {
7915 tagClass: 3,
7916 tagNumber: item.context
7917 },
7918 value: asn1Item.valueBlock.value
7919 }));
7920 }
7921 } else {
7922 asn1Value.push(new asn1$3.Constructed({
7923 optional: item.optional,
7924 idBlock: {
7925 tagClass: 3,
7926 tagNumber: item.context
7927 },
7928 value: [asn1Item]
7929 }));
7930 }
7931 } else if (item.repeated) {
7932 asn1Value = asn1Value.concat(asn1Item);
7933 } else {
7934 asn1Value.push(asn1Item);
7935 }
7936 }
7937
7938 let asnSchema;
7939
7940 switch (schema.type) {
7941 case exports.AsnTypeTypes.Sequence:
7942 asnSchema = new asn1$3.Sequence({
7943 value: asn1Value
7944 });
7945 break;
7946
7947 case exports.AsnTypeTypes.Set:
7948 asnSchema = new asn1$3.Set({
7949 value: asn1Value
7950 });
7951 break;
7952
7953 case exports.AsnTypeTypes.Choice:
7954 if (!asn1Value[0]) {
7955 throw new Error(`Schema '${target.name}' has wrong data. Choice cannot be empty.`);
7956 }
7957
7958 asnSchema = asn1Value[0];
7959 break;
7960 }
7961
7962 return asnSchema;
7963 }
7964
7965 }
7966
7967 exports.AsnProp = AsnProp;
7968 exports.AsnType = AsnType;
7969 exports.AsnParser = AsnParser;
7970 exports.AsnSerializer = AsnSerializer;
7971 exports.AsnAnyConverter = AsnAnyConverter;
7972 exports.AsnIntegerConverter = AsnIntegerConverter;
7973 exports.AsnEnumeratedConverter = AsnEnumeratedConverter;
7974 exports.AsnIntegerArrayBufferConverter = AsnIntegerArrayBufferConverter;
7975 exports.AsnBitStringConverter = AsnBitStringConverter;
7976 exports.AsnObjectIdentifierConverter = AsnObjectIdentifierConverter;
7977 exports.AsnBooleanConverter = AsnBooleanConverter;
7978 exports.AsnOctetStringConverter = AsnOctetStringConverter;
7979 exports.AsnUtf8StringConverter = AsnUtf8StringConverter;
7980 exports.AsnBmpStringConverter = AsnBmpStringConverter;
7981 exports.AsnUniversalStringConverter = AsnUniversalStringConverter;
7982 exports.AsnNumericStringConverter = AsnNumericStringConverter;
7983 exports.AsnPrintableStringConverter = AsnPrintableStringConverter;
7984 exports.AsnTeletexStringConverter = AsnTeletexStringConverter;
7985 exports.AsnVideotexStringConverter = AsnVideotexStringConverter;
7986 exports.AsnIA5StringConverter = AsnIA5StringConverter;
7987 exports.AsnGraphicStringConverter = AsnGraphicStringConverter;
7988 exports.AsnVisibleStringConverter = AsnVisibleStringConverter;
7989 exports.AsnGeneralStringConverter = AsnGeneralStringConverter;
7990 exports.AsnCharacterStringConverter = AsnCharacterStringConverter;
7991 exports.AsnUTCTimeConverter = AsnUTCTimeConverter;
7992 exports.AsnGeneralizedTimeConverter = AsnGeneralizedTimeConverter;
7993 });
7994 unwrapExports(build);
7995 var build_1 = build.AsnTypeTypes;
7996 var build_2 = build.AsnPropTypes;
7997 var build_3 = build.AsnProp;
7998 var build_4 = build.AsnType;
7999 var build_5 = build.AsnParser;
8000 var build_6 = build.AsnSerializer;
8001 var build_7 = build.AsnAnyConverter;
8002 var build_8 = build.AsnIntegerConverter;
8003 var build_9 = build.AsnEnumeratedConverter;
8004 var build_10 = build.AsnIntegerArrayBufferConverter;
8005 var build_11 = build.AsnBitStringConverter;
8006 var build_12 = build.AsnObjectIdentifierConverter;
8007 var build_13 = build.AsnBooleanConverter;
8008 var build_14 = build.AsnOctetStringConverter;
8009 var build_15 = build.AsnUtf8StringConverter;
8010 var build_16 = build.AsnBmpStringConverter;
8011 var build_17 = build.AsnUniversalStringConverter;
8012 var build_18 = build.AsnNumericStringConverter;
8013 var build_19 = build.AsnPrintableStringConverter;
8014 var build_20 = build.AsnTeletexStringConverter;
8015 var build_21 = build.AsnVideotexStringConverter;
8016 var build_22 = build.AsnIA5StringConverter;
8017 var build_23 = build.AsnGraphicStringConverter;
8018 var build_24 = build.AsnVisibleStringConverter;
8019 var build_25 = build.AsnGeneralStringConverter;
8020 var build_26 = build.AsnCharacterStringConverter;
8021 var build_27 = build.AsnUTCTimeConverter;
8022 var build_28 = build.AsnGeneralizedTimeConverter;
8023 var build$1 = createCommonjsModule(function (module, exports) {
8024 Object.defineProperty(exports, '__esModule', {
8025 value: true
8026 });
8027
8028 class JsonError extends Error {
8029 constructor(message, innerError) {
8030 super(innerError ? `${message}. See the inner exception for more details.` : message);
8031 this.message = message;
8032 this.innerError = innerError;
8033 }
8034
8035 }
8036
8037 class TransformError extends JsonError {
8038 constructor(schema, message, innerError) {
8039 super(message, innerError);
8040 this.schema = schema;
8041 }
8042
8043 }
8044
8045 class ParserError extends TransformError {
8046 constructor(schema, message, innerError) {
8047 super(schema, `JSON doesn't match to '${schema.target.name}' schema. ${message}`, innerError);
8048 }
8049
8050 }
8051
8052 class ValidationError extends JsonError {}
8053
8054 class SerializerError extends JsonError {
8055 constructor(schemaName, message, innerError) {
8056 super(`Cannot serialize by '${schemaName}' schema. ${message}`, innerError);
8057 this.schemaName = schemaName;
8058 }
8059
8060 }
8061
8062 class KeyError extends ParserError {
8063 constructor(schema, keys, errors = {}) {
8064 super(schema, "Some keys doesn't match to schema");
8065 this.keys = keys;
8066 this.errors = errors;
8067 }
8068
8069 }
8070
8071 (function (JsonPropTypes) {
8072 JsonPropTypes[JsonPropTypes["Any"] = 0] = "Any";
8073 JsonPropTypes[JsonPropTypes["Boolean"] = 1] = "Boolean";
8074 JsonPropTypes[JsonPropTypes["Number"] = 2] = "Number";
8075 JsonPropTypes[JsonPropTypes["String"] = 3] = "String";
8076 })(exports.JsonPropTypes || (exports.JsonPropTypes = {}));
8077
8078 function checkType(value, type) {
8079 switch (type) {
8080 case exports.JsonPropTypes.Boolean:
8081 return typeof value === "boolean";
8082
8083 case exports.JsonPropTypes.Number:
8084 return typeof value === "number";
8085
8086 case exports.JsonPropTypes.String:
8087 return typeof value === "string";
8088 }
8089
8090 return true;
8091 }
8092
8093 function throwIfTypeIsWrong(value, type) {
8094 if (!checkType(value, type)) {
8095 throw new TypeError(`Value must be ${exports.JsonPropTypes[type]}`);
8096 }
8097 }
8098
8099 function isConvertible(target) {
8100 if (target && target.prototype) {
8101 if (target.prototype.toJSON && target.prototype.fromJSON) {
8102 return true;
8103 } else {
8104 return isConvertible(target.prototype);
8105 }
8106 } else {
8107 return !!(target && target.toJSON && target.fromJSON);
8108 }
8109 }
8110
8111 class JsonSchemaStorage {
8112 constructor() {
8113 this.items = new Map();
8114 }
8115
8116 has(target) {
8117 return this.items.has(target) || !!this.findParentSchema(target);
8118 }
8119
8120 get(target) {
8121 const schema = this.items.get(target) || this.findParentSchema(target);
8122
8123 if (!schema) {
8124 throw new Error("Cannot get schema for current target");
8125 }
8126
8127 return schema;
8128 }
8129
8130 create(target) {
8131 const schema = {
8132 names: {}
8133 };
8134 const parentSchema = this.findParentSchema(target);
8135
8136 if (parentSchema) {
8137 Object.assign(schema, parentSchema);
8138 schema.names = {};
8139
8140 for (const name in parentSchema.names) {
8141 schema.names[name] = Object.assign({}, parentSchema.names[name]);
8142 }
8143 }
8144
8145 schema.target = target;
8146 return schema;
8147 }
8148
8149 set(target, schema) {
8150 this.items.set(target, schema);
8151 return this;
8152 }
8153
8154 findParentSchema(target) {
8155 const parent = target.__proto__;
8156
8157 if (parent) {
8158 const schema = this.items.get(parent);
8159 return schema || this.findParentSchema(parent);
8160 }
8161
8162 return null;
8163 }
8164
8165 }
8166
8167 const DEFAULT_SCHEMA = "default";
8168 const schemaStorage = new JsonSchemaStorage();
8169
8170 class PatternValidation {
8171 constructor(pattern) {
8172 this.pattern = new RegExp(pattern);
8173 }
8174
8175 validate(value) {
8176 const pattern = new RegExp(this.pattern.source, this.pattern.flags);
8177
8178 if (typeof value !== "string") {
8179 throw new ValidationError("Incoming value must be string");
8180 }
8181
8182 if (!pattern.exec(value)) {
8183 throw new ValidationError(`Value doesn't match to pattern '${pattern.toString()}'`);
8184 }
8185 }
8186
8187 }
8188
8189 class InclusiveValidation {
8190 constructor(min = Number.MIN_VALUE, max = Number.MAX_VALUE) {
8191 this.min = min;
8192 this.max = max;
8193 }
8194
8195 validate(value) {
8196 throwIfTypeIsWrong(value, exports.JsonPropTypes.Number);
8197
8198 if (!(this.min <= value && value <= this.max)) {
8199 const min = this.min === Number.MIN_VALUE ? "MIN" : this.min;
8200 const max = this.max === Number.MAX_VALUE ? "MAX" : this.max;
8201 throw new ValidationError(`Value doesn't match to diapason [${min},${max}]`);
8202 }
8203 }
8204
8205 }
8206
8207 class ExclusiveValidation {
8208 constructor(min = Number.MIN_VALUE, max = Number.MAX_VALUE) {
8209 this.min = min;
8210 this.max = max;
8211 }
8212
8213 validate(value) {
8214 throwIfTypeIsWrong(value, exports.JsonPropTypes.Number);
8215
8216 if (!(this.min < value && value < this.max)) {
8217 const min = this.min === Number.MIN_VALUE ? "MIN" : this.min;
8218 const max = this.max === Number.MAX_VALUE ? "MAX" : this.max;
8219 throw new ValidationError(`Value doesn't match to diapason (${min},${max})`);
8220 }
8221 }
8222
8223 }
8224
8225 class LengthValidation {
8226 constructor(length, minLength, maxLength) {
8227 this.length = length;
8228 this.minLength = minLength;
8229 this.maxLength = maxLength;
8230 }
8231
8232 validate(value) {
8233 if (this.length !== undefined) {
8234 if (value.length !== this.length) {
8235 throw new ValidationError(`Value length must be exactly ${this.length}.`);
8236 }
8237
8238 return;
8239 }
8240
8241 if (this.minLength !== undefined) {
8242 if (value.length < this.minLength) {
8243 throw new ValidationError(`Value length must be more than ${this.minLength}.`);
8244 }
8245 }
8246
8247 if (this.maxLength !== undefined) {
8248 if (value.length > this.maxLength) {
8249 throw new ValidationError(`Value length must be less than ${this.maxLength}.`);
8250 }
8251 }
8252 }
8253
8254 }
8255
8256 class EnumerationValidation {
8257 constructor(enumeration) {
8258 this.enumeration = enumeration;
8259 }
8260
8261 validate(value) {
8262 throwIfTypeIsWrong(value, exports.JsonPropTypes.String);
8263
8264 if (!this.enumeration.includes(value)) {
8265 throw new ValidationError(`Value must be one of ${this.enumeration.map(v => `'${v}'`).join(", ")}`);
8266 }
8267 }
8268
8269 }
8270
8271 class JsonTransform {
8272 static checkValues(data, schemaItem) {
8273 const values = Array.isArray(data) ? data : [data];
8274
8275 for (const value of values) {
8276 for (const validation of schemaItem.validations) {
8277 if (validation instanceof LengthValidation && schemaItem.repeated) {
8278 validation.validate(data);
8279 } else {
8280 validation.validate(value);
8281 }
8282 }
8283 }
8284 }
8285
8286 static checkTypes(value, schemaItem) {
8287 if (schemaItem.repeated && !Array.isArray(value)) {
8288 throw new TypeError("Value must be Array");
8289 }
8290
8291 if (typeof schemaItem.type === "number") {
8292 const values = Array.isArray(value) ? value : [value];
8293
8294 for (const v of values) {
8295 throwIfTypeIsWrong(v, schemaItem.type);
8296 }
8297 }
8298 }
8299
8300 static getSchemaByName(schema, name = DEFAULT_SCHEMA) {
8301 return _objectSpread({}, schema.names[DEFAULT_SCHEMA], schema.names[name]);
8302 }
8303
8304 }
8305
8306 class JsonSerializer extends JsonTransform {
8307 static serialize(obj, options, replacer, space) {
8308 const json = this.toJSON(obj, options);
8309 return JSON.stringify(json, replacer, space);
8310 }
8311
8312 static toJSON(obj, options = {}) {
8313 let res;
8314 let targetSchema = options.targetSchema;
8315 const schemaName = options.schemaName || DEFAULT_SCHEMA;
8316
8317 if (isConvertible(obj)) {
8318 return obj.toJSON();
8319 }
8320
8321 if (Array.isArray(obj)) {
8322 res = [];
8323
8324 for (const item of obj) {
8325 res.push(this.toJSON(item, options));
8326 }
8327 } else if (typeof obj === "object") {
8328 if (targetSchema && !schemaStorage.has(targetSchema)) {
8329 throw new JsonError("Cannot get schema for `targetSchema` param");
8330 }
8331
8332 targetSchema = targetSchema || obj.constructor;
8333
8334 if (schemaStorage.has(targetSchema)) {
8335 const schema = schemaStorage.get(targetSchema);
8336 res = {};
8337 const namedSchema = this.getSchemaByName(schema, schemaName);
8338
8339 for (const key in namedSchema) {
8340 try {
8341 const item = namedSchema[key];
8342 const objItem = obj[key];
8343 let value;
8344
8345 if (item.optional && objItem === undefined || item.defaultValue !== undefined && objItem === item.defaultValue) {
8346 continue;
8347 }
8348
8349 if (!item.optional && objItem === undefined) {
8350 throw new SerializerError(targetSchema.name, `Property '${key}' is required.`);
8351 }
8352
8353 if (typeof item.type === "number") {
8354 if (item.converter) {
8355 if (item.repeated) {
8356 value = objItem.map(el => item.converter.toJSON(el, obj));
8357 } else {
8358 value = item.converter.toJSON(objItem, obj);
8359 }
8360 } else {
8361 value = objItem;
8362 }
8363 } else {
8364 if (item.repeated) {
8365 value = objItem.map(el => this.toJSON(el, {
8366 schemaName
8367 }));
8368 } else {
8369 value = this.toJSON(objItem, {
8370 schemaName
8371 });
8372 }
8373 }
8374
8375 this.checkTypes(value, item);
8376 this.checkValues(value, item);
8377 res[item.name || key] = value;
8378 } catch (e) {
8379 if (e instanceof SerializerError) {
8380 throw e;
8381 } else {
8382 throw new SerializerError(schema.target.name, `Property '${key}' is wrong. ${e.message}`, e);
8383 }
8384 }
8385 }
8386 } else {
8387 res = {};
8388
8389 for (const key in obj) {
8390 res[key] = this.toJSON(obj[key], {
8391 schemaName
8392 });
8393 }
8394 }
8395 } else {
8396 res = obj;
8397 }
8398
8399 return res;
8400 }
8401
8402 }
8403
8404 class JsonParser extends JsonTransform {
8405 static parse(data, options) {
8406 const obj = JSON.parse(data);
8407 return this.fromJSON(obj, options);
8408 }
8409
8410 static fromJSON(target, options) {
8411 const targetSchema = options.targetSchema;
8412 const schemaName = options.schemaName || DEFAULT_SCHEMA;
8413 const obj = new targetSchema();
8414
8415 if (isConvertible(obj)) {
8416 return obj.fromJSON(target);
8417 }
8418
8419 const schema = schemaStorage.get(targetSchema);
8420 const namedSchema = this.getSchemaByName(schema, schemaName);
8421 const keyErrors = {};
8422
8423 if (options.strictProperty && !Array.isArray(target)) {
8424 JsonParser.checkStrictProperty(target, namedSchema, schema);
8425 }
8426
8427 for (const key in namedSchema) {
8428 try {
8429 const item = namedSchema[key];
8430 const name = item.name || key;
8431 const value = target[name];
8432
8433 if (value === undefined && (item.optional || item.defaultValue !== undefined)) {
8434 continue;
8435 }
8436
8437 if (!item.optional && value === undefined) {
8438 throw new ParserError(schema, `Property '${name}' is required.`);
8439 }
8440
8441 this.checkTypes(value, item);
8442 this.checkValues(value, item);
8443
8444 if (typeof item.type === "number") {
8445 if (item.converter) {
8446 if (item.repeated) {
8447 obj[key] = value.map(el => item.converter.fromJSON(el, obj));
8448 } else {
8449 obj[key] = item.converter.fromJSON(value, obj);
8450 }
8451 } else {
8452 obj[key] = value;
8453 }
8454 } else {
8455 const newOptions = _objectSpread({}, options, {
8456 targetSchema: item.type,
8457 schemaName
8458 });
8459
8460 if (item.repeated) {
8461 obj[key] = value.map(el => this.fromJSON(el, newOptions));
8462 } else {
8463 obj[key] = this.fromJSON(value, newOptions);
8464 }
8465 }
8466 } catch (e) {
8467 if (!(e instanceof ParserError)) {
8468 e = new ParserError(schema, `Property '${key}' is wrong. ${e.message}`, e);
8469 }
8470
8471 if (options.strictAllKeys) {
8472 keyErrors[key] = e;
8473 } else {
8474 throw e;
8475 }
8476 }
8477 }
8478
8479 const keys = Object.keys(keyErrors);
8480
8481 if (keys.length) {
8482 throw new KeyError(schema, keys, keyErrors);
8483 }
8484
8485 return obj;
8486 }
8487
8488 static checkStrictProperty(target, namedSchema, schema) {
8489 const jsonProps = Object.keys(target);
8490 const schemaProps = Object.keys(namedSchema);
8491 const keys = [];
8492
8493 for (const key of jsonProps) {
8494 if (schemaProps.indexOf(key) === -1) {
8495 keys.push(key);
8496 }
8497 }
8498
8499 if (keys.length) {
8500 throw new KeyError(schema, keys);
8501 }
8502 }
8503
8504 }
8505
8506 function getValidations(item) {
8507 const validations = [];
8508
8509 if (item.pattern) {
8510 validations.push(new PatternValidation(item.pattern));
8511 }
8512
8513 if (item.type === exports.JsonPropTypes.Number || item.type === exports.JsonPropTypes.Any) {
8514 if (item.minInclusive !== undefined || item.maxInclusive !== undefined) {
8515 validations.push(new InclusiveValidation(item.minInclusive, item.maxInclusive));
8516 }
8517
8518 if (item.minExclusive !== undefined || item.maxExclusive !== undefined) {
8519 validations.push(new ExclusiveValidation(item.minExclusive, item.maxExclusive));
8520 }
8521
8522 if (item.enumeration !== undefined) {
8523 validations.push(new EnumerationValidation(item.enumeration));
8524 }
8525 }
8526
8527 if (item.type === exports.JsonPropTypes.String || item.repeated || item.type === exports.JsonPropTypes.Any) {
8528 if (item.length !== undefined || item.minLength !== undefined || item.maxLength !== undefined) {
8529 validations.push(new LengthValidation(item.length, item.minLength, item.maxLength));
8530 }
8531 }
8532
8533 return validations;
8534 }
8535
8536 const JsonProp = (options = {}) => (target, propertyKey) => {
8537 const errorMessage = `Cannot set type for ${propertyKey} property of ${target.constructor.name} schema`;
8538 let schema;
8539
8540 if (!schemaStorage.has(target.constructor)) {
8541 schema = schemaStorage.create(target.constructor);
8542 schemaStorage.set(target.constructor, schema);
8543 } else {
8544 schema = schemaStorage.get(target.constructor);
8545
8546 if (schema.target !== target.constructor) {
8547 schema = schemaStorage.create(target.constructor);
8548 schemaStorage.set(target.constructor, schema);
8549 }
8550 }
8551
8552 const defaultSchema = {
8553 type: exports.JsonPropTypes.Any,
8554 validations: []
8555 };
8556 const copyOptions = Object.assign(defaultSchema, options);
8557 copyOptions.validations = getValidations(copyOptions);
8558
8559 if (typeof copyOptions.type !== "number") {
8560 if (!schemaStorage.has(copyOptions.type) && !isConvertible(copyOptions.type)) {
8561 throw new Error(`${errorMessage}. Assigning type doesn't have schema.`);
8562 }
8563 }
8564
8565 let schemaNames;
8566
8567 if (Array.isArray(options.schema)) {
8568 schemaNames = options.schema;
8569 } else {
8570 schemaNames = [options.schema || DEFAULT_SCHEMA];
8571 }
8572
8573 for (const schemaName of schemaNames) {
8574 if (!schema.names[schemaName]) {
8575 schema.names[schemaName] = {};
8576 }
8577
8578 const namedSchema = schema.names[schemaName];
8579 namedSchema[propertyKey] = copyOptions;
8580 }
8581 };
8582
8583 exports.JsonSerializer = JsonSerializer;
8584 exports.JsonParser = JsonParser;
8585 exports.JsonProp = JsonProp;
8586 });
8587 unwrapExports(build$1);
8588 var build_1$1 = build$1.JsonPropTypes;
8589 var build_2$1 = build$1.JsonSerializer;
8590 var build_3$1 = build$1.JsonParser;
8591 var build_4$1 = build$1.JsonProp;
8592 let ObjectIdentifier = class ObjectIdentifier {
8593 constructor(value) {
8594 if (value) {
8595 this.value = value;
8596 }
8597 }
8598
8599 };
8600
8601 __decorate([build_3({
8602 type: build_2.ObjectIdentifier
8603 })], ObjectIdentifier.prototype, "value", void 0);
8604
8605 ObjectIdentifier = __decorate([build_4({
8606 type: build_1.Choice
8607 })], ObjectIdentifier);
8608
8609 class AlgorithmIdentifier {
8610 constructor(params) {
8611 Object.assign(this, params);
8612 }
8613
8614 }
8615
8616 __decorate([build_3({
8617 type: build_2.ObjectIdentifier
8618 })], AlgorithmIdentifier.prototype, "algorithm", void 0);
8619
8620 __decorate([build_3({
8621 type: build_2.Any,
8622 optional: true
8623 })], AlgorithmIdentifier.prototype, "parameters", void 0);
8624
8625 class PrivateKeyInfo {
8626 constructor() {
8627 this.version = 0;
8628 this.privateKeyAlgorithm = new AlgorithmIdentifier();
8629 this.privateKey = new ArrayBuffer(0);
8630 }
8631
8632 }
8633
8634 __decorate([build_3({
8635 type: build_2.Integer
8636 })], PrivateKeyInfo.prototype, "version", void 0);
8637
8638 __decorate([build_3({
8639 type: AlgorithmIdentifier
8640 })], PrivateKeyInfo.prototype, "privateKeyAlgorithm", void 0);
8641
8642 __decorate([build_3({
8643 type: build_2.OctetString
8644 })], PrivateKeyInfo.prototype, "privateKey", void 0);
8645
8646 __decorate([build_3({
8647 type: build_2.Any,
8648 optional: true
8649 })], PrivateKeyInfo.prototype, "attributes", void 0);
8650
8651 class PublicKeyInfo {
8652 constructor() {
8653 this.publicKeyAlgorithm = new AlgorithmIdentifier();
8654 this.publicKey = new ArrayBuffer(0);
8655 }
8656
8657 }
8658
8659 __decorate([build_3({
8660 type: AlgorithmIdentifier
8661 })], PublicKeyInfo.prototype, "publicKeyAlgorithm", void 0);
8662
8663 __decorate([build_3({
8664 type: build_2.BitString
8665 })], PublicKeyInfo.prototype, "publicKey", void 0);
8666
8667 const JsonBase64UrlArrayBufferConverter = {
8668 fromJSON: value => Convert.FromBase64Url(value),
8669 toJSON: value => Convert.ToBase64Url(new Uint8Array(value))
8670 };
8671 var Browser;
8672
8673 (function (Browser) {
8674 Browser["Unknown"] = "Unknown";
8675 Browser["IE"] = "Internet Explorer";
8676 Browser["Safari"] = "Safari";
8677 Browser["Edge"] = "Edge";
8678 Browser["Chrome"] = "Chrome";
8679 Browser["Firefox"] = "Firefox Mozilla";
8680 Browser["Mobile"] = "Mobile";
8681 })(Browser || (Browser = {}));
8682
8683 function BrowserInfo() {
8684 const res = {
8685 name: Browser.Unknown,
8686 version: "0"
8687 };
8688 const userAgent = window.navigator.userAgent;
8689 let reg;
8690
8691 if (reg = /edge\/([\d\.]+)/i.exec(userAgent)) {
8692 res.name = Browser.Edge;
8693 res.version = reg[1];
8694 } else if (/msie/i.test(userAgent)) {
8695 res.name = Browser.IE;
8696 res.version = /msie ([\d\.]+)/i.exec(userAgent)[1];
8697 } else if (/Trident/i.test(userAgent)) {
8698 res.name = Browser.IE;
8699 res.version = /rv:([\d\.]+)/i.exec(userAgent)[1];
8700 } else if (/chrome/i.test(userAgent)) {
8701 res.name = Browser.Chrome;
8702 res.version = /chrome\/([\d\.]+)/i.exec(userAgent)[1];
8703 } else if (/firefox/i.test(userAgent)) {
8704 res.name = Browser.Firefox;
8705 res.version = /firefox\/([\d\.]+)/i.exec(userAgent)[1];
8706 } else if (/mobile/i.test(userAgent)) {
8707 res.name = Browser.Mobile;
8708 res.version = /mobile\/([\w]+)/i.exec(userAgent)[1];
8709 } else if (/safari/i.test(userAgent)) {
8710 res.name = Browser.Safari;
8711 res.version = /version\/([\d\.]+)/i.exec(userAgent)[1];
8712 }
8713
8714 return res;
8715 }
8716
8717 function concat(...buf) {
8718 const res = new Uint8Array(buf.map(item => item.length).reduce((prev, cur) => prev + cur));
8719 let offset = 0;
8720 buf.forEach((item, index) => {
8721 for (let i = 0; i < item.length; i++) {
8722 res[offset + i] = item[i];
8723 }
8724
8725 offset += item.length;
8726 });
8727 return res;
8728 }
8729
8730 const AsnIntegerArrayBufferConverter = {
8731 fromASN: value => {
8732 const valueHex = value.valueBlock.valueHex;
8733 return !new Uint8Array(valueHex)[0] ? value.valueBlock.valueHex.slice(1) : value.valueBlock.valueHex;
8734 },
8735 toASN: value => {
8736 const valueHex = new Uint8Array(value)[0] > 127 ? concat(new Uint8Array([0]), new Uint8Array(value)) : new Uint8Array(value);
8737 return new asn1_26({
8738 valueHex: new Uint8Array(valueHex).buffer
8739 });
8740 }
8741 };
8742
8743 class RsaPrivateKey {
8744 constructor() {
8745 this.version = 0;
8746 this.modulus = new ArrayBuffer(0);
8747 this.publicExponent = new ArrayBuffer(0);
8748 this.privateExponent = new ArrayBuffer(0);
8749 this.prime1 = new ArrayBuffer(0);
8750 this.prime2 = new ArrayBuffer(0);
8751 this.exponent1 = new ArrayBuffer(0);
8752 this.exponent2 = new ArrayBuffer(0);
8753 this.coefficient = new ArrayBuffer(0);
8754 }
8755
8756 }
8757
8758 __decorate([build_3({
8759 type: build_2.Integer,
8760 converter: build_8
8761 })], RsaPrivateKey.prototype, "version", void 0);
8762
8763 __decorate([build_3({
8764 type: build_2.Integer,
8765 converter: AsnIntegerArrayBufferConverter
8766 }), build_4$1({
8767 name: "n",
8768 converter: JsonBase64UrlArrayBufferConverter
8769 })], RsaPrivateKey.prototype, "modulus", void 0);
8770
8771 __decorate([build_3({
8772 type: build_2.Integer,
8773 converter: AsnIntegerArrayBufferConverter
8774 }), build_4$1({
8775 name: "e",
8776 converter: JsonBase64UrlArrayBufferConverter
8777 })], RsaPrivateKey.prototype, "publicExponent", void 0);
8778
8779 __decorate([build_3({
8780 type: build_2.Integer,
8781 converter: AsnIntegerArrayBufferConverter
8782 }), build_4$1({
8783 name: "d",
8784 converter: JsonBase64UrlArrayBufferConverter
8785 })], RsaPrivateKey.prototype, "privateExponent", void 0);
8786
8787 __decorate([build_3({
8788 type: build_2.Integer,
8789 converter: AsnIntegerArrayBufferConverter
8790 }), build_4$1({
8791 name: "p",
8792 converter: JsonBase64UrlArrayBufferConverter
8793 })], RsaPrivateKey.prototype, "prime1", void 0);
8794
8795 __decorate([build_3({
8796 type: build_2.Integer,
8797 converter: AsnIntegerArrayBufferConverter
8798 }), build_4$1({
8799 name: "q",
8800 converter: JsonBase64UrlArrayBufferConverter
8801 })], RsaPrivateKey.prototype, "prime2", void 0);
8802
8803 __decorate([build_3({
8804 type: build_2.Integer,
8805 converter: AsnIntegerArrayBufferConverter
8806 }), build_4$1({
8807 name: "dp",
8808 converter: JsonBase64UrlArrayBufferConverter
8809 })], RsaPrivateKey.prototype, "exponent1", void 0);
8810
8811 __decorate([build_3({
8812 type: build_2.Integer,
8813 converter: AsnIntegerArrayBufferConverter
8814 }), build_4$1({
8815 name: "dq",
8816 converter: JsonBase64UrlArrayBufferConverter
8817 })], RsaPrivateKey.prototype, "exponent2", void 0);
8818
8819 __decorate([build_3({
8820 type: build_2.Integer,
8821 converter: AsnIntegerArrayBufferConverter
8822 }), build_4$1({
8823 name: "qi",
8824 converter: JsonBase64UrlArrayBufferConverter
8825 })], RsaPrivateKey.prototype, "coefficient", void 0);
8826
8827 __decorate([build_3({
8828 type: build_2.Any,
8829 optional: true
8830 })], RsaPrivateKey.prototype, "otherPrimeInfos", void 0);
8831
8832 class RsaPublicKey {
8833 constructor() {
8834 this.modulus = new ArrayBuffer(0);
8835 this.publicExponent = new ArrayBuffer(0);
8836 }
8837
8838 }
8839
8840 __decorate([build_3({
8841 type: build_2.Integer,
8842 converter: AsnIntegerArrayBufferConverter
8843 }), build_4$1({
8844 name: "n",
8845 converter: JsonBase64UrlArrayBufferConverter
8846 })], RsaPublicKey.prototype, "modulus", void 0);
8847
8848 __decorate([build_3({
8849 type: build_2.Integer,
8850 converter: AsnIntegerArrayBufferConverter
8851 }), build_4$1({
8852 name: "e",
8853 converter: JsonBase64UrlArrayBufferConverter
8854 })], RsaPublicKey.prototype, "publicExponent", void 0);
8855
8856 let EcPublicKey = class EcPublicKey {
8857 constructor(value) {
8858 this.value = new ArrayBuffer(0);
8859
8860 if (value) {
8861 this.value = value;
8862 }
8863 }
8864
8865 toJSON() {
8866 let bytes = new Uint8Array(this.value);
8867
8868 if (bytes[0] !== 0x04) {
8869 throw new CryptoError("Wrong ECPoint. Current version supports only Uncompressed (0x04) point");
8870 }
8871
8872 bytes = new Uint8Array(this.value.slice(1));
8873 const size = bytes.length / 2;
8874 const offset = 0;
8875 const json = {
8876 x: Convert.ToBase64Url(bytes.buffer.slice(offset, offset + size)),
8877 y: Convert.ToBase64Url(bytes.buffer.slice(offset + size, offset + size + size))
8878 };
8879 return json;
8880 }
8881
8882 fromJSON(json) {
8883 if (!("x" in json)) {
8884 throw new Error("x: Missing required property");
8885 }
8886
8887 if (!("y" in json)) {
8888 throw new Error("y: Missing required property");
8889 }
8890
8891 const x = Convert.FromBase64Url(json.x);
8892 const y = Convert.FromBase64Url(json.y);
8893 const value = concat(new Uint8Array([0x04]), new Uint8Array(x), new Uint8Array(y));
8894 this.value = new Uint8Array(value).buffer;
8895 return this;
8896 }
8897
8898 };
8899
8900 __decorate([build_3({
8901 type: build_2.OctetString
8902 })], EcPublicKey.prototype, "value", void 0);
8903
8904 EcPublicKey = __decorate([build_4({
8905 type: build_1.Choice
8906 })], EcPublicKey);
8907
8908 class EcPrivateKey {
8909 constructor() {
8910 this.version = 1;
8911 this.privateKey = new ArrayBuffer(0);
8912 }
8913
8914 fromJSON(json) {
8915 if (!("d" in json)) {
8916 throw new Error("d: Missing required property");
8917 }
8918
8919 this.privateKey = Convert.FromBase64Url(json.d);
8920
8921 if ("x" in json) {
8922 const publicKey = new EcPublicKey();
8923 publicKey.fromJSON(json);
8924 this.publicKey = build_6.toASN(publicKey).valueBlock.valueHex;
8925 }
8926
8927 return this;
8928 }
8929
8930 toJSON() {
8931 const jwk = {};
8932 jwk.d = Convert.ToBase64Url(this.privateKey);
8933
8934 if (this.publicKey) {
8935 Object.assign(jwk, new EcPublicKey(this.publicKey).toJSON());
8936 }
8937
8938 return jwk;
8939 }
8940
8941 }
8942
8943 __decorate([build_3({
8944 type: build_2.Integer,
8945 converter: build_8
8946 })], EcPrivateKey.prototype, "version", void 0);
8947
8948 __decorate([build_3({
8949 type: build_2.OctetString
8950 })], EcPrivateKey.prototype, "privateKey", void 0);
8951
8952 __decorate([build_3({
8953 context: 0,
8954 type: build_2.Any,
8955 optional: true
8956 })], EcPrivateKey.prototype, "parameters", void 0);
8957
8958 __decorate([build_3({
8959 context: 1,
8960 type: build_2.BitString,
8961 optional: true
8962 })], EcPrivateKey.prototype, "publicKey", void 0);
8963
8964 const AsnIntegerWithoutPaddingConverter = {
8965 fromASN: value => {
8966 const bytes = new Uint8Array(value.valueBlock.valueHex);
8967 return bytes[0] === 0 ? bytes.buffer.slice(1) : bytes.buffer;
8968 },
8969 toASN: value => {
8970 const bytes = new Uint8Array(value);
8971
8972 if (bytes[0] > 127) {
8973 const newValue = new Uint8Array(bytes.length + 1);
8974 newValue.set(bytes, 1);
8975 return new asn1_26({
8976 valueHex: newValue
8977 });
8978 }
8979
8980 return new asn1_26({
8981 valueHex: value
8982 });
8983 }
8984 };
8985
8986 class EcDsaSignature {
8987 constructor() {
8988 this.r = new ArrayBuffer(0);
8989 this.s = new ArrayBuffer(0);
8990 }
8991
8992 }
8993
8994 __decorate([build_3({
8995 type: build_2.Integer,
8996 converter: AsnIntegerWithoutPaddingConverter
8997 })], EcDsaSignature.prototype, "r", void 0);
8998
8999 __decorate([build_3({
9000 type: build_2.Integer,
9001 converter: AsnIntegerWithoutPaddingConverter
9002 })], EcDsaSignature.prototype, "s", void 0);
9003
9004 class CryptoKey$1 extends CryptoKey {
9005 constructor(algorithm, extractable, type, usages) {
9006 super();
9007 this.extractable = extractable;
9008 this.type = type;
9009 this.usages = usages;
9010 this.algorithm = _objectSpread({}, algorithm);
9011 }
9012
9013 }
9014
9015 function isAlgorithm(algorithm, name) {
9016 return algorithm.name.toUpperCase() === name.toUpperCase();
9017 }
9018
9019 class AesCryptoKey extends CryptoKey$1 {
9020 constructor(algorithm, extractable, usages, raw) {
9021 super(algorithm, extractable, "secret", usages);
9022 this.raw = raw;
9023 }
9024
9025 toJSON() {
9026 const jwk = {
9027 kty: "oct",
9028 alg: this.getJwkAlgorithm(),
9029 k: Convert.ToBase64Url(this.raw),
9030 ext: this.extractable,
9031 key_ops: this.usages
9032 };
9033 return jwk;
9034 }
9035
9036 getJwkAlgorithm() {
9037 switch (this.algorithm.name.toUpperCase()) {
9038 case "AES-CBC":
9039 return `A${this.algorithm.length}CBC`;
9040
9041 case "AES-CTR":
9042 return `A${this.algorithm.length}CTR`;
9043
9044 case "AES-GCM":
9045 return `A${this.algorithm.length}GCM`;
9046
9047 case "AES-ECB":
9048 return `A${this.algorithm.length}ECB`;
9049
9050 default:
9051 throw new AlgorithmError("Unsupported algorithm name");
9052 }
9053 }
9054
9055 }
9056
9057 class AesCrypto {
9058 static checkLib() {
9059 if (typeof asmCrypto === "undefined") {
9060 throw new OperationError("Cannot implement DES mechanism. Add 'https://peculiarventures.github.io/pv-webcrypto-tests/src/asmcrypto.js' script to your project");
9061 }
9062 }
9063
9064 static checkCryptoKey(key) {
9065 if (!(key instanceof AesCryptoKey)) {
9066 throw new TypeError("key: Is not AesCryptoKey");
9067 }
9068 }
9069
9070 static async generateKey(algorithm, extractable, usages) {
9071 this.checkLib();
9072 const raw = nativeCrypto.getRandomValues(new Uint8Array(algorithm.length / 8));
9073 return new AesCryptoKey(algorithm, extractable, usages, raw);
9074 }
9075
9076 static async encrypt(algorithm, key, data) {
9077 return this.cipher(algorithm, key, data, true);
9078 }
9079
9080 static async decrypt(algorithm, key, data) {
9081 return this.cipher(algorithm, key, data, false);
9082 }
9083
9084 static async exportKey(format, key) {
9085 this.checkLib();
9086
9087 switch (format) {
9088 case "jwk":
9089 return key.toJSON();
9090
9091 case "raw":
9092 return key.raw.buffer;
9093
9094 default:
9095 throw new OperationError("format: Must be 'jwk' or 'raw'");
9096 }
9097 }
9098
9099 static async importKey(format, keyData, algorithm, extractable, keyUsages) {
9100 this.checkLib();
9101 let raw;
9102
9103 if (isJWK(keyData)) {
9104 raw = Convert.FromBase64Url(keyData.k);
9105 } else {
9106 raw = BufferSourceConverter.toArrayBuffer(keyData);
9107 }
9108
9109 switch (raw.byteLength << 3) {
9110 case 128:
9111 case 192:
9112 case 256:
9113 break;
9114
9115 default:
9116 throw new OperationError("keyData: Is wrong key length");
9117 }
9118
9119 const key = new AesCryptoKey({
9120 name: algorithm.name,
9121 length: raw.byteLength << 3
9122 }, extractable, keyUsages, new Uint8Array(raw));
9123 return key;
9124 }
9125
9126 static async cipher(algorithm, key, data, encrypt) {
9127 this.checkLib();
9128 const action = encrypt ? "encrypt" : "decrypt";
9129 let res;
9130
9131 if (isAlgorithm(algorithm, AesCrypto.AesCBC)) {
9132 const iv = BufferSourceConverter.toArrayBuffer(algorithm.iv);
9133 res = asmCrypto.AES_CBC[action](data, key.raw, undefined, iv);
9134 } else if (isAlgorithm(algorithm, AesCrypto.AesGCM)) {
9135 const iv = BufferSourceConverter.toArrayBuffer(algorithm.iv);
9136 let additionalData;
9137
9138 if (algorithm.additionalData) {
9139 additionalData = BufferSourceConverter.toArrayBuffer(algorithm.additionalData);
9140 }
9141
9142 const tagLength = (algorithm.tagLength || 128) / 8;
9143 res = asmCrypto.AES_GCM[action](data, key.raw, iv, additionalData, tagLength);
9144 } else if (isAlgorithm(algorithm, AesCrypto.AesECB)) {
9145 res = asmCrypto.AES_ECB[action](data, key.raw, true);
9146 } else {
9147 throw new OperationError(`algorithm: Is not recognized`);
9148 }
9149
9150 return res.buffer;
9151 }
9152
9153 }
9154
9155 AesCrypto.AesCBC = "AES-CBC";
9156 AesCrypto.AesECB = "AES-ECB";
9157 AesCrypto.AesGCM = "AES-GCM";
9158
9159 class AesCbcProvider$1 extends AesCbcProvider {
9160 async onGenerateKey(algorithm, extractable, keyUsages) {
9161 return AesCrypto.generateKey(algorithm, extractable, keyUsages);
9162 }
9163
9164 async onEncrypt(algorithm, key, data) {
9165 return AesCrypto.encrypt(algorithm, key, data);
9166 }
9167
9168 async onDecrypt(algorithm, key, data) {
9169 return AesCrypto.decrypt(algorithm, key, data);
9170 }
9171
9172 async onExportKey(format, key) {
9173 return AesCrypto.exportKey(format, key);
9174 }
9175
9176 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9177 return AesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
9178 }
9179
9180 async checkCryptoKey(key, keyUsage) {
9181 super.checkCryptoKey(key, keyUsage);
9182 AesCrypto.checkCryptoKey(key);
9183 }
9184
9185 }
9186
9187 class AesEcbProvider$1 extends AesEcbProvider {
9188 async onGenerateKey(algorithm, extractable, keyUsages) {
9189 return AesCrypto.generateKey(algorithm, extractable, keyUsages);
9190 }
9191
9192 async onEncrypt(algorithm, key, data) {
9193 return AesCrypto.encrypt(algorithm, key, data);
9194 }
9195
9196 async onDecrypt(algorithm, key, data) {
9197 return AesCrypto.decrypt(algorithm, key, data);
9198 }
9199
9200 async onExportKey(format, key) {
9201 return AesCrypto.exportKey(format, key);
9202 }
9203
9204 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9205 return AesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
9206 }
9207
9208 async checkCryptoKey(key, keyUsage) {
9209 super.checkCryptoKey(key, keyUsage);
9210 AesCrypto.checkCryptoKey(key);
9211 }
9212
9213 }
9214
9215 class AesGcmProvider$1 extends AesGcmProvider {
9216 async onGenerateKey(algorithm, extractable, keyUsages) {
9217 return AesCrypto.generateKey(algorithm, extractable, keyUsages);
9218 }
9219
9220 async onEncrypt(algorithm, key, data) {
9221 return AesCrypto.encrypt(algorithm, key, data);
9222 }
9223
9224 async onDecrypt(algorithm, key, data) {
9225 return AesCrypto.decrypt(algorithm, key, data);
9226 }
9227
9228 async onExportKey(format, key) {
9229 return AesCrypto.exportKey(format, key);
9230 }
9231
9232 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9233 return AesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
9234 }
9235
9236 async checkCryptoKey(key, keyUsage) {
9237 super.checkCryptoKey(key, keyUsage);
9238 AesCrypto.checkCryptoKey(key);
9239 }
9240
9241 }
9242
9243 class AesCtrProvider$1 extends AesCtrProvider {
9244 async onEncrypt(algorithm, key, data) {
9245 throw new Error("Method not implemented.");
9246 }
9247
9248 async onDecrypt(algorithm, key, data) {
9249 throw new Error("Method not implemented.");
9250 }
9251
9252 async onGenerateKey(algorithm, extractable, keyUsages) {
9253 throw new Error("Method not implemented.");
9254 }
9255
9256 async onExportKey(format, key) {
9257 throw new Error("Method not implemented.");
9258 }
9259
9260 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9261 throw new Error("Method not implemented.");
9262 }
9263
9264 }
9265
9266 class AesKwProvider$1 extends AesKwProvider {
9267 async onEncrypt(algorithm, key, data) {
9268 throw new Error("Method not implemented.");
9269 }
9270
9271 async onDecrypt(algorithm, key, data) {
9272 throw new Error("Method not implemented.");
9273 }
9274
9275 async onGenerateKey(algorithm, extractable, keyUsages) {
9276 throw new Error("Method not implemented.");
9277 }
9278
9279 async onExportKey(format, key) {
9280 throw new Error("Method not implemented.");
9281 }
9282
9283 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9284 throw new Error("Method not implemented.");
9285 }
9286
9287 }
9288
9289 class RsaCryptoKey extends CryptoKey$1 {
9290 constructor(algorithm, extractable, type, usages, data) {
9291 super(algorithm, extractable, type, usages);
9292 this.data = data;
9293 }
9294
9295 }
9296
9297 class RsaCrypto {
9298 static checkLib() {
9299 if (typeof asmCrypto === "undefined") {
9300 throw new OperationError("Cannot implement DES mechanism. Add 'https://peculiarventures.github.io/pv-webcrypto-tests/src/asmcrypto.js' script to your project");
9301 }
9302 }
9303
9304 static checkCryptoKey(key) {
9305 if (!(key instanceof RsaCryptoKey)) {
9306 throw new TypeError("key: Is not RsaCryptoKey");
9307 }
9308 }
9309
9310 static async generateKey(algorithm, extractable, keyUsages) {
9311 this.checkLib();
9312 const pubExp = algorithm.publicExponent[0] === 3 ? 3 : 65537;
9313 const rsaKey = asmCrypto.RSA.generateKey(algorithm.modulusLength, pubExp);
9314 const hashAlgorithm = algorithm.hash.name.toUpperCase();
9315 const privateKey = new RsaCryptoKey(_objectSpread({}, algorithm, {
9316 hash: {
9317 name: hashAlgorithm
9318 }
9319 }), extractable, "private", keyUsages.filter(usage => ~this.privateUsages.indexOf(usage)), rsaKey);
9320 const publicKey = new RsaCryptoKey(_objectSpread({}, algorithm, {
9321 hash: {
9322 name: hashAlgorithm
9323 }
9324 }), true, "public", keyUsages.filter(usage => ~this.publicUsages.indexOf(usage)), rsaKey);
9325 return {
9326 privateKey,
9327 publicKey
9328 };
9329 }
9330
9331 static async exportKey(format, key) {
9332 this.checkLib();
9333
9334 switch (format) {
9335 case "pkcs8":
9336 return this.exportPkcs8Key(key);
9337
9338 case "spki":
9339 return this.exportSpkiKey(key);
9340
9341 case "jwk":
9342 return this.exportJwkKey(key);
9343
9344 default:
9345 throw new OperationError("format: Must be 'jwk', 'pkcs8' or 'spki'");
9346 }
9347 }
9348
9349 static async importKey(format, keyData, algorithm, extractable, keyUsages) {
9350 this.checkLib();
9351 let asmKey;
9352
9353 switch (format) {
9354 case "pkcs8":
9355 asmKey = this.importPkcs8Key(keyData);
9356 break;
9357
9358 case "spki":
9359 asmKey = this.importSpkiKey(keyData);
9360 break;
9361
9362 case "jwk":
9363 asmKey = this.importJwkKey(keyData);
9364 break;
9365
9366 default:
9367 throw new OperationError("format: Must be 'jwk', 'pkcs8' or 'spki'");
9368 }
9369
9370 const key = new RsaCryptoKey(_objectSpread({
9371 publicExponent: asmKey[1][1] === 1 ? asmKey[1].slice(1) : asmKey[1].slice(3),
9372 modulusLength: asmKey[0].byteLength << 3
9373 }, algorithm), extractable, asmKey.length === 2 ? "public" : "private", keyUsages, asmKey);
9374 return key;
9375 }
9376
9377 static exportPkcs8Key(key) {
9378 const keyInfo = new PrivateKeyInfo();
9379 keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1";
9380 keyInfo.privateKeyAlgorithm.parameters = null;
9381 keyInfo.privateKey = build_6.serialize(this.exportAsmKey(key.data));
9382 return build_6.serialize(keyInfo);
9383 }
9384
9385 static importPkcs8Key(data) {
9386 const keyInfo = build_5.parse(data, PrivateKeyInfo);
9387 const privateKey = build_5.parse(keyInfo.privateKey, RsaPrivateKey);
9388 return this.importAsmKey(privateKey);
9389 }
9390
9391 static importSpkiKey(data) {
9392 const keyInfo = build_5.parse(data, PublicKeyInfo);
9393 const publicKey = build_5.parse(keyInfo.publicKey, RsaPublicKey);
9394 return this.importAsmKey(publicKey);
9395 }
9396
9397 static exportSpkiKey(key) {
9398 const publicKey = new RsaPublicKey();
9399 publicKey.modulus = key.data[0].buffer;
9400 publicKey.publicExponent = key.data[1][1] === 1 ? key.data[1].buffer.slice(1) : key.data[1].buffer.slice(3);
9401 const keyInfo = new PublicKeyInfo();
9402 keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1";
9403 keyInfo.publicKeyAlgorithm.parameters = null;
9404 keyInfo.publicKey = build_6.serialize(publicKey);
9405 return build_6.serialize(keyInfo);
9406 }
9407
9408 static importJwkKey(data) {
9409 let key;
9410
9411 if (data.d) {
9412 key = build_3$1.fromJSON(data, {
9413 targetSchema: RsaPrivateKey
9414 });
9415 } else {
9416 key = build_3$1.fromJSON(data, {
9417 targetSchema: RsaPublicKey
9418 });
9419 }
9420
9421 return this.importAsmKey(key);
9422 }
9423
9424 static exportJwkKey(key) {
9425 const asnKey = this.exportAsmKey(key.data);
9426 const jwk = build_2$1.toJSON(asnKey);
9427 jwk.ext = true;
9428 jwk.key_ops = key.usages;
9429 jwk.kty = "RSA";
9430 jwk.alg = this.getJwkAlgorithm(key.algorithm);
9431 return jwk;
9432 }
9433
9434 static getJwkAlgorithm(algorithm) {
9435 switch (algorithm.name.toUpperCase()) {
9436 case "RSA-OAEP":
9437 const mdSize = /(\d+)$/.exec(algorithm.hash.name)[1];
9438 return `RSA-OAEP${mdSize !== "1" ? `-${mdSize}` : ""}`;
9439
9440 case "RSASSA-PKCS1-V1_5":
9441 return `RS${/(\d+)$/.exec(algorithm.hash.name)[1]}`;
9442
9443 case "RSA-PSS":
9444 return `PS${/(\d+)$/.exec(algorithm.hash.name)[1]}`;
9445
9446 default:
9447 throw new OperationError("algorithm: Is not recognized");
9448 }
9449 }
9450
9451 static exportAsmKey(asmKey) {
9452 let key;
9453
9454 if (asmKey.length > 2) {
9455 const privateKey = new RsaPrivateKey();
9456 privateKey.privateExponent = asmKey[2].buffer;
9457 privateKey.prime1 = asmKey[3].buffer;
9458 privateKey.prime2 = asmKey[4].buffer;
9459 privateKey.exponent1 = asmKey[5].buffer;
9460 privateKey.exponent2 = asmKey[6].buffer;
9461 privateKey.coefficient = asmKey[7].buffer;
9462 key = privateKey;
9463 } else {
9464 key = new RsaPublicKey();
9465 }
9466
9467 key.modulus = asmKey[0].buffer;
9468 key.publicExponent = asmKey[1][1] === 1 ? asmKey[1].buffer.slice(1) : asmKey[1].buffer.slice(3);
9469 return key;
9470 }
9471
9472 static importAsmKey(key) {
9473 const expPadding = new Uint8Array(4 - key.publicExponent.byteLength);
9474 const asmKey = [new Uint8Array(key.modulus), concat(expPadding, new Uint8Array(key.publicExponent))];
9475
9476 if (key instanceof RsaPrivateKey) {
9477 asmKey.push(new Uint8Array(key.privateExponent));
9478 asmKey.push(new Uint8Array(key.prime1));
9479 asmKey.push(new Uint8Array(key.prime2));
9480 asmKey.push(new Uint8Array(key.exponent1));
9481 asmKey.push(new Uint8Array(key.exponent2));
9482 asmKey.push(new Uint8Array(key.coefficient));
9483 }
9484
9485 return asmKey;
9486 }
9487
9488 }
9489
9490 RsaCrypto.RsaSsa = "RSASSA-PKCS1-v1_5";
9491 RsaCrypto.RsaPss = "RSA-PSS";
9492 RsaCrypto.RsaOaep = "RSA-OAEP";
9493 RsaCrypto.privateUsages = ["sign", "decrypt", "unwrapKey"];
9494 RsaCrypto.publicUsages = ["verify", "encrypt", "wrapKey"];
9495
9496 class RsaOaepProvider$1 extends RsaOaepProvider {
9497 async onGenerateKey(algorithm, extractable, keyUsages) {
9498 return RsaCrypto.generateKey(algorithm, extractable, keyUsages);
9499 }
9500
9501 async onExportKey(format, key) {
9502 return RsaCrypto.exportKey(format, key);
9503 }
9504
9505 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9506 return RsaCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
9507 }
9508
9509 async onEncrypt(algorithm, key, data) {
9510 RsaCrypto.checkLib();
9511 return this.cipher(algorithm, key, data, true);
9512 }
9513
9514 async onDecrypt(algorithm, key, data) {
9515 RsaCrypto.checkLib();
9516 return this.cipher(algorithm, key, data, false);
9517 }
9518
9519 cipher(algorithm, key, data, encrypt) {
9520 const fn = this.getOperation(key.algorithm, encrypt);
9521 let label;
9522
9523 if (algorithm.label) {
9524 label = BufferSourceConverter.toArrayBuffer(algorithm.label);
9525 }
9526
9527 return fn(data, key.data, label).slice(0).buffer;
9528 }
9529
9530 getOperation(keyAlgorithm, encrypt) {
9531 const action = encrypt ? "encrypt" : "decrypt";
9532
9533 switch (keyAlgorithm.hash.name) {
9534 case "SHA-1":
9535 return asmCrypto.RSA_OAEP_SHA1[action];
9536
9537 case "SHA-256":
9538 return asmCrypto.RSA_OAEP_SHA256[action];
9539
9540 case "SHA-512":
9541 return asmCrypto.RSA_OAEP_SHA512[action];
9542
9543 default:
9544 throw new AlgorithmError("keyAlgorithm.hash: Is not recognized");
9545 }
9546 }
9547
9548 }
9549
9550 class RsaPssProvider$1 extends RsaPssProvider {
9551 async onGenerateKey(algorithm, extractable, keyUsages) {
9552 return RsaCrypto.generateKey(algorithm, extractable, keyUsages);
9553 }
9554
9555 async onExportKey(format, key) {
9556 return RsaCrypto.exportKey(format, key);
9557 }
9558
9559 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9560 return RsaCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
9561 }
9562
9563 async onSign(algorithm, key, data) {
9564 RsaCrypto.checkLib();
9565 const fn = this.getOperation(key.algorithm, true);
9566 return fn(data, key.data, algorithm.saltLength).buffer;
9567 }
9568
9569 async onVerify(algorithm, key, signature, data) {
9570 RsaCrypto.checkLib();
9571 const fn = this.getOperation(key.algorithm, false);
9572 return fn(signature, data, key.data, algorithm.saltLength);
9573 }
9574
9575 async checkCryptoKey(key, keyUsage) {
9576 super.checkCryptoKey(key, keyUsage);
9577 RsaCrypto.checkCryptoKey(key);
9578 }
9579
9580 getOperation(keyAlgorithm, sign) {
9581 const action = sign ? "sign" : "verify";
9582
9583 switch (keyAlgorithm.hash.name) {
9584 case "SHA-1":
9585 return asmCrypto.RSA_PSS_SHA1[action];
9586
9587 case "SHA-256":
9588 return asmCrypto.RSA_PSS_SHA256[action];
9589
9590 case "SHA-512":
9591 return asmCrypto.RSA_PSS_SHA512[action];
9592
9593 default:
9594 throw new AlgorithmError("keyAlgorithm.hash: Is not recognized");
9595 }
9596 }
9597
9598 }
9599
9600 class RsaSsaProvider$1 extends RsaSsaProvider {
9601 async onGenerateKey(algorithm, extractable, keyUsages) {
9602 return RsaCrypto.generateKey(algorithm, extractable, keyUsages);
9603 }
9604
9605 async onExportKey(format, key) {
9606 return RsaCrypto.exportKey(format, key);
9607 }
9608
9609 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9610 return RsaCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
9611 }
9612
9613 async onSign(algorithm, key, data) {
9614 RsaCrypto.checkLib();
9615 const fn = this.getOperation(key.algorithm, true);
9616 return fn(data, key.data).buffer;
9617 }
9618
9619 async onVerify(algorithm, key, signature, data) {
9620 RsaCrypto.checkLib();
9621 const fn = this.getOperation(key.algorithm, false);
9622 return fn(signature, data, key.data);
9623 }
9624
9625 async checkCryptoKey(key, keyUsage) {
9626 super.checkCryptoKey(key, keyUsage);
9627 RsaCrypto.checkCryptoKey(key);
9628 }
9629
9630 getOperation(keyAlgorithm, sign) {
9631 const action = sign ? "sign" : "verify";
9632
9633 switch (keyAlgorithm.hash.name) {
9634 case "SHA-1":
9635 return asmCrypto.RSA_PKCS1_v1_5_SHA1[action];
9636
9637 case "SHA-256":
9638 return asmCrypto.RSA_PKCS1_v1_5_SHA256[action];
9639
9640 case "SHA-512":
9641 return asmCrypto.RSA_PKCS1_v1_5_SHA512[action];
9642
9643 default:
9644 throw new AlgorithmError("keyAlgorithm.hash: Is not recognized");
9645 }
9646 }
9647
9648 }
9649
9650 const namedOIDs = {
9651 "1.2.840.10045.3.1.7": "P-256",
9652 "P-256": "1.2.840.10045.3.1.7",
9653 "1.3.132.0.34": "P-384",
9654 "P-384": "1.3.132.0.34",
9655 "1.3.132.0.35": "P-521",
9656 "P-521": "1.3.132.0.35",
9657 "1.3.132.0.10": "K-256",
9658 "K-256": "1.3.132.0.10"
9659 };
9660
9661 function getOidByNamedCurve(namedCurve) {
9662 const oid = namedOIDs[namedCurve];
9663
9664 if (!oid) {
9665 throw new OperationError(`Cannot convert WebCrypto named curve '${namedCurve}' to OID`);
9666 }
9667
9668 return oid;
9669 }
9670
9671 class EcCryptoKey extends CryptoKey$1 {
9672 constructor(algorithm, extractable, type, usages, data) {
9673 super(algorithm, extractable, type, usages);
9674 this.data = data;
9675 }
9676
9677 }
9678
9679 class EcCrypto {
9680 static checkLib() {
9681 if (typeof elliptic === "undefined") {
9682 throw new OperationError("Cannot implement DES mechanism. Add 'https://peculiarventures.github.io/pv-webcrypto-tests/src/elliptic.js' script to your project");
9683 }
9684 }
9685
9686 static async generateKey(algorithm, extractable, keyUsages) {
9687 this.checkLib();
9688 const key = this.initEcKey(algorithm.namedCurve);
9689 const ecKey = key.genKeyPair();
9690 ecKey.getPublic();
9691 const prvKey = new EcCryptoKey(_objectSpread({}, algorithm), extractable, "private", keyUsages.filter(usage => ~this.privateUsages.indexOf(usage)), ecKey);
9692 const pubKey = new EcCryptoKey(_objectSpread({}, algorithm), true, "public", keyUsages.filter(usage => ~this.publicUsages.indexOf(usage)), ecKey);
9693 return {
9694 privateKey: prvKey,
9695 publicKey: pubKey
9696 };
9697 }
9698
9699 static checkCryptoKey(key) {
9700 if (!(key instanceof EcCryptoKey)) {
9701 throw new TypeError("key: Is not EcCryptoKey");
9702 }
9703 }
9704
9705 static concat(...buf) {
9706 const res = new Uint8Array(buf.map(item => item.length).reduce((prev, cur) => prev + cur));
9707 let offset = 0;
9708 buf.forEach((item, index) => {
9709 for (let i = 0; i < item.length; i++) {
9710 res[offset + i] = item[i];
9711 }
9712
9713 offset += item.length;
9714 });
9715 return res;
9716 }
9717
9718 static async exportKey(format, key) {
9719 this.checkLib();
9720
9721 switch (format) {
9722 case "pkcs8":
9723 return this.exportPkcs8Key(key);
9724
9725 case "spki":
9726 return this.exportSpkiKey(key);
9727
9728 case "jwk":
9729 return this.exportJwkKey(key);
9730
9731 case "raw":
9732 return new Uint8Array(key.data.getPublic("der")).buffer;
9733
9734 default:
9735 throw new OperationError("format: Must be 'jwk', 'raw, 'pkcs8' or 'spki'");
9736 }
9737 }
9738
9739 static async importKey(format, keyData, algorithm, extractable, keyUsages) {
9740 this.checkLib();
9741 let ecKey;
9742
9743 switch (format) {
9744 case "pkcs8":
9745 ecKey = this.importPkcs8Key(keyData, algorithm.namedCurve);
9746 break;
9747
9748 case "spki":
9749 ecKey = this.importSpkiKey(keyData, algorithm.namedCurve);
9750 break;
9751
9752 case "raw":
9753 ecKey = this.importEcKey(new EcPublicKey(keyData), algorithm.namedCurve);
9754 break;
9755
9756 case "jwk":
9757 ecKey = this.importJwkKey(keyData);
9758 break;
9759
9760 default:
9761 throw new OperationError("format: Must be 'jwk', 'raw', 'pkcs8' or 'spki'");
9762 }
9763
9764 const key = new EcCryptoKey(_objectSpread({}, algorithm), extractable, ecKey.priv ? "private" : "public", keyUsages, ecKey);
9765 return key;
9766 }
9767
9768 static getNamedCurve(wcNamedCurve) {
9769 const crv = wcNamedCurve.toUpperCase();
9770 let res = "";
9771
9772 if (["P-256", "P-384", "P-521"].indexOf(crv) > -1) {
9773 res = crv.replace("-", "").toLowerCase();
9774 } else if (crv === "K-256") {
9775 res = "secp256k1";
9776 } else {
9777 throw new OperationError(`Unsupported named curve '${wcNamedCurve}'`);
9778 }
9779
9780 return res;
9781 }
9782
9783 static initEcKey(namedCurve) {
9784 return elliptic.ec(this.getNamedCurve(namedCurve));
9785 }
9786
9787 static exportPkcs8Key(key) {
9788 const keyInfo = new PrivateKeyInfo();
9789 keyInfo.privateKeyAlgorithm.algorithm = this.ASN_ALGORITHM;
9790 keyInfo.privateKeyAlgorithm.parameters = build_6.serialize(new ObjectIdentifier(getOidByNamedCurve(key.algorithm.namedCurve)));
9791 keyInfo.privateKey = build_6.serialize(this.exportEcKey(key));
9792 return build_6.serialize(keyInfo);
9793 }
9794
9795 static importPkcs8Key(data, namedCurve) {
9796 const keyInfo = build_5.parse(data, PrivateKeyInfo);
9797 const privateKey = build_5.parse(keyInfo.privateKey, EcPrivateKey);
9798 return this.importEcKey(privateKey, namedCurve);
9799 }
9800
9801 static importSpkiKey(data, namedCurve) {
9802 const keyInfo = build_5.parse(data, PublicKeyInfo);
9803 const publicKey = new EcPublicKey(keyInfo.publicKey);
9804 return this.importEcKey(publicKey, namedCurve);
9805 }
9806
9807 static exportSpkiKey(key) {
9808 const publicKey = new EcPublicKey(new Uint8Array(key.data.getPublic("der")).buffer);
9809 const keyInfo = new PublicKeyInfo();
9810 keyInfo.publicKeyAlgorithm.algorithm = this.ASN_ALGORITHM;
9811 keyInfo.publicKeyAlgorithm.parameters = build_6.serialize(new ObjectIdentifier(getOidByNamedCurve(key.algorithm.namedCurve)));
9812 keyInfo.publicKey = publicKey.value;
9813 return build_6.serialize(keyInfo);
9814 }
9815
9816 static importJwkKey(data) {
9817 let key;
9818
9819 if (data.d) {
9820 key = build_3$1.fromJSON(data, {
9821 targetSchema: EcPrivateKey
9822 });
9823 } else {
9824 key = build_3$1.fromJSON(data, {
9825 targetSchema: EcPublicKey
9826 });
9827 }
9828
9829 return this.importEcKey(key, data.crv);
9830 }
9831
9832 static exportJwkKey(key) {
9833 const asnKey = this.exportEcKey(key);
9834 const jwk = build_2$1.toJSON(asnKey);
9835 jwk.ext = true;
9836 jwk.key_ops = key.usages;
9837 jwk.crv = key.algorithm.namedCurve;
9838 jwk.kty = "EC";
9839 return jwk;
9840 }
9841
9842 static exportEcKey(ecKey) {
9843 if (ecKey.type === "private") {
9844 const privateKey = new EcPrivateKey();
9845 const point = new Uint8Array(ecKey.data.getPrivate("der").toArray());
9846 const pointPad = new Uint8Array(this.getPointSize(ecKey.algorithm.namedCurve) - point.length);
9847 privateKey.privateKey = concat(pointPad, point);
9848 privateKey.publicKey = new Uint8Array(ecKey.data.getPublic("der"));
9849 return privateKey;
9850 } else if (ecKey.data.pub) {
9851 return new EcPublicKey(new Uint8Array(ecKey.data.getPublic("der")).buffer);
9852 } else {
9853 throw new Error("Cannot get private or public key");
9854 }
9855 }
9856
9857 static importEcKey(key, namedCurve) {
9858 const ecKey = this.initEcKey(namedCurve);
9859
9860 if (key instanceof EcPublicKey) {
9861 return ecKey.keyFromPublic(new Uint8Array(key.value));
9862 }
9863
9864 return ecKey.keyFromPrivate(new Uint8Array(key.privateKey));
9865 }
9866
9867 static getPointSize(namedCurve) {
9868 switch (namedCurve) {
9869 case "P-256":
9870 case "K-256":
9871 return 32;
9872
9873 case "P-384":
9874 return 48;
9875
9876 case "P-521":
9877 return 66;
9878 }
9879
9880 throw new Error("namedCurve: Is not recognized");
9881 }
9882
9883 }
9884
9885 EcCrypto.privateUsages = ["sign", "deriveKey", "deriveBits"];
9886 EcCrypto.publicUsages = ["verify"];
9887 EcCrypto.ASN_ALGORITHM = "1.2.840.10045.2.1";
9888
9889 class EcdhProvider$1 extends EcdhProvider {
9890 async onGenerateKey(algorithm, extractable, keyUsages) {
9891 return EcCrypto.generateKey(algorithm, extractable, keyUsages);
9892 }
9893
9894 async onExportKey(format, key) {
9895 return EcCrypto.exportKey(format, key);
9896 }
9897
9898 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9899 return EcCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
9900 }
9901
9902 async onDeriveBits(algorithm, baseKey, length) {
9903 EcCrypto.checkLib();
9904 const shared = baseKey.data.derive(algorithm.public.data.getPublic());
9905 let array = new Uint8Array(shared.toArray());
9906 let len = array.length;
9907 len = len > 32 ? len > 48 ? 66 : 48 : 32;
9908
9909 if (array.length < len) {
9910 array = EcCrypto.concat(new Uint8Array(len - array.length), array);
9911 }
9912
9913 const buf = array.slice(0, length / 8).buffer;
9914 return buf;
9915 }
9916
9917 async checkCryptoKey(key, keyUsage) {
9918 super.checkCryptoKey(key, keyUsage);
9919 EcCrypto.checkCryptoKey(key);
9920 }
9921
9922 }
9923
9924 function b2a(buffer) {
9925 const buf = new Uint8Array(buffer);
9926 const res = [];
9927
9928 for (let i = 0; i < buf.length; i++) {
9929 res.push(buf[i]);
9930 }
9931
9932 return res;
9933 }
9934
9935 function hex2buffer(hexString, padded) {
9936 if (hexString.length % 2) {
9937 hexString = "0" + hexString;
9938 }
9939
9940 let res = new Uint8Array(hexString.length / 2);
9941
9942 for (let i = 0; i < hexString.length; i++) {
9943 const c = hexString.slice(i, ++i + 1);
9944 res[(i - 1) / 2] = parseInt(c, 16);
9945 }
9946
9947 if (padded) {
9948 let len = res.length;
9949 len = len > 32 ? len > 48 ? 66 : 48 : 32;
9950
9951 if (res.length < len) {
9952 res = EcCrypto.concat(new Uint8Array(len - res.length), res);
9953 }
9954 }
9955
9956 return res;
9957 }
9958
9959 function buffer2hex(buffer, padded) {
9960 let res = "";
9961
9962 for (let i = 0; i < buffer.length; i++) {
9963 const char = buffer[i].toString(16);
9964 res += char.length % 2 ? "0" + char : char;
9965 }
9966
9967 if (padded) {
9968 let len = buffer.length;
9969 len = len > 32 ? len > 48 ? 66 : 48 : 32;
9970
9971 if (res.length / 2 < len) {
9972 res = new Array(len * 2 - res.length + 1).join("0") + res;
9973 }
9974 }
9975
9976 return res;
9977 }
9978
9979 class EcdsaProvider$1 extends EcdsaProvider {
9980 async onGenerateKey(algorithm, extractable, keyUsages) {
9981 return EcCrypto.generateKey(algorithm, extractable, keyUsages);
9982 }
9983
9984 async onExportKey(format, key) {
9985 return EcCrypto.exportKey(format, key);
9986 }
9987
9988 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
9989 return EcCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
9990 }
9991
9992 async onSign(algorithm, key, data) {
9993 EcCrypto.checkLib();
9994 const crypto = new Crypto$1();
9995 let array;
9996 const hash = await crypto.subtle.digest(algorithm.hash, data);
9997 array = b2a(hash);
9998 const signature = await key.data.sign(array);
9999 const hexSignature = buffer2hex(signature.r.toArray(), true) + buffer2hex(signature.s.toArray(), true);
10000 return hex2buffer(hexSignature).buffer;
10001 }
10002
10003 async onVerify(algorithm, key, signature, data) {
10004 EcCrypto.checkLib();
10005 const crypto = new Crypto$1();
10006 const sig = {
10007 r: new Uint8Array(signature.slice(0, signature.byteLength / 2)),
10008 s: new Uint8Array(signature.slice(signature.byteLength / 2))
10009 };
10010 const hashedData = await crypto.subtle.digest(algorithm.hash, data);
10011 const array = b2a(hashedData);
10012 return key.data.verify(array, sig);
10013 }
10014
10015 async checkCryptoKey(key, keyUsage) {
10016 super.checkCryptoKey(key, keyUsage);
10017 EcCrypto.checkCryptoKey(key);
10018 }
10019
10020 }
10021
10022 class ShaCrypto {
10023 static checkLib() {
10024 if (typeof asmCrypto === "undefined") {
10025 throw new OperationError("Cannot implement DES mechanism. Add 'https://peculiarventures.github.io/pv-webcrypto-tests/src/asmcrypto.js' script to your project");
10026 }
10027 }
10028
10029 static async digest(algorithm, data) {
10030 this.checkLib();
10031 const mech = asmCrypto[algorithm.name.replace("-", "")];
10032 return mech.bytes(data).buffer;
10033 }
10034
10035 }
10036
10037 class Sha1Provider extends ProviderCrypto {
10038 constructor() {
10039 super(...arguments);
10040 this.name = "SHA-1";
10041 this.usages = [];
10042 }
10043
10044 async onDigest(algorithm, data) {
10045 return ShaCrypto.digest(algorithm, data);
10046 }
10047
10048 }
10049
10050 class Sha256Provider extends Sha1Provider {
10051 constructor() {
10052 super(...arguments);
10053 this.name = "SHA-256";
10054 }
10055
10056 }
10057
10058 class Sha512Provider extends Sha1Provider {
10059 constructor() {
10060 super(...arguments);
10061 this.name = "SHA-512";
10062 }
10063
10064 }
10065
10066 class PbkdfCryptoKey extends CryptoKey$1 {
10067 constructor(algorithm, extractable, usages, raw) {
10068 super(algorithm, extractable, "secret", usages);
10069 this.raw = raw;
10070 }
10071
10072 }
10073
10074 class Pbkdf2Provider$1 extends Pbkdf2Provider {
10075 checkLib() {
10076 if (typeof asmCrypto === "undefined") {
10077 throw new OperationError("Cannot implement DES mechanism. Add 'https://peculiarventures.github.io/pv-webcrypto-tests/src/asmcrypto.js' script to your project");
10078 }
10079 }
10080
10081 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
10082 this.checkLib();
10083 return new PbkdfCryptoKey(algorithm, extractable, keyUsages, BufferSourceConverter.toUint8Array(keyData));
10084 }
10085
10086 async onDeriveBits(algorithm, baseKey, length) {
10087 this.checkLib();
10088 let result;
10089 const salt = BufferSourceConverter.toUint8Array(algorithm.salt);
10090 const password = baseKey.raw;
10091
10092 switch (algorithm.hash.name.toUpperCase()) {
10093 case "SHA-1":
10094 result = asmCrypto.PBKDF2_HMAC_SHA1.bytes(password, salt, algorithm.iterations, length >> 3);
10095 break;
10096
10097 case "SHA-256":
10098 result = asmCrypto.PBKDF2_HMAC_SHA256.bytes(password, salt, algorithm.iterations, length >> 3);
10099 break;
10100
10101 default:
10102 throw new OperationError(`algorithm.hash: '${algorithm.hash.name}' hash algorithm is not supported`);
10103 }
10104
10105 return result.buffer;
10106 }
10107
10108 }
10109
10110 class DesCryptoKey extends CryptoKey$1 {
10111 constructor(algorithm, extractable, usages, raw) {
10112 super(algorithm, extractable, "secret", usages);
10113 this.raw = raw;
10114 }
10115
10116 toJSON() {
10117 const jwk = {
10118 kty: "oct",
10119 alg: this.getJwkAlgorithm(),
10120 k: Convert.ToBase64Url(this.raw),
10121 ext: this.extractable,
10122 key_ops: this.usages
10123 };
10124 return jwk;
10125 }
10126
10127 getJwkAlgorithm() {
10128 switch (this.algorithm.name.toUpperCase()) {
10129 case "DES-CBC":
10130 return `DES-CBC`;
10131
10132 case "DES-EDE3-CBC":
10133 return `3DES-CBC`;
10134
10135 default:
10136 throw new AlgorithmError("Unsupported algorithm name");
10137 }
10138 }
10139
10140 }
10141
10142 class DesCrypto {
10143 static checkLib() {
10144 if (typeof des === "undefined") {
10145 throw new OperationError("Cannot implement DES mechanism. Add 'https://peculiarventures.github.io/pv-webcrypto-tests/src/des.js' script to your project");
10146 }
10147 }
10148
10149 static async generateKey(algorithm, extractable, keyUsages) {
10150 this.checkLib();
10151 const raw = nativeCrypto.getRandomValues(new Uint8Array(algorithm.length / 8));
10152 return new DesCryptoKey(algorithm, extractable, keyUsages, raw);
10153 }
10154
10155 static async exportKey(format, key) {
10156 this.checkLib();
10157
10158 switch (format) {
10159 case "jwk":
10160 return key.toJSON();
10161
10162 case "raw":
10163 return key.raw.buffer;
10164
10165 default:
10166 throw new OperationError("format: Must be 'jwk' or 'raw'");
10167 }
10168 }
10169
10170 static async importKey(format, keyData, algorithm, extractable, keyUsages) {
10171 this.checkLib();
10172 let raw;
10173
10174 if (isJWK(keyData)) {
10175 raw = Convert.FromBase64Url(keyData.k);
10176 } else {
10177 raw = BufferSourceConverter.toArrayBuffer(keyData);
10178 }
10179
10180 if (algorithm.name === "DES-CBC" && raw.byteLength !== 8 || algorithm.name === "DES-EDE3-CBC" && raw.byteLength !== 24) {
10181 throw new OperationError("keyData: Is wrong key length");
10182 }
10183
10184 const key = new DesCryptoKey({
10185 name: algorithm.name,
10186 length: raw.byteLength << 3
10187 }, extractable, keyUsages, new Uint8Array(raw));
10188 return key;
10189 }
10190
10191 static async encrypt(algorithm, key, data) {
10192 return this.cipher(algorithm, key, data, true);
10193 }
10194
10195 static async decrypt(algorithm, key, data) {
10196 return this.cipher(algorithm, key, data, false);
10197 }
10198
10199 static async cipher(algorithm, key, data, encrypt) {
10200 this.checkLib();
10201 const type = encrypt ? "encrypt" : "decrypt";
10202 let DesCipher;
10203 const iv = BufferSourceConverter.toUint8Array(algorithm.iv);
10204
10205 switch (algorithm.name.toUpperCase()) {
10206 case "DES-CBC":
10207 DesCipher = des.CBC.instantiate(des.DES).create({
10208 key: key.raw,
10209 type,
10210 iv
10211 });
10212 break;
10213
10214 case "DES-EDE3-CBC":
10215 DesCipher = des.CBC.instantiate(des.EDE).create({
10216 key: key.raw,
10217 type,
10218 iv
10219 });
10220 break;
10221
10222 default:
10223 throw new OperationError("algorithm: Is not recognized");
10224 }
10225
10226 const enc = DesCipher.update(new Uint8Array(data)).concat(DesCipher.final());
10227 return new Uint8Array(enc).buffer;
10228 }
10229
10230 }
10231
10232 class DesCbcProvider extends DesProvider {
10233 constructor() {
10234 super(...arguments);
10235 this.keySizeBits = 64;
10236 this.ivSize = 8;
10237 this.name = "DES-CBC";
10238 }
10239
10240 async onGenerateKey(algorithm, extractable, keyUsages) {
10241 return DesCrypto.generateKey(algorithm, extractable, keyUsages);
10242 }
10243
10244 async onExportKey(format, key) {
10245 return DesCrypto.exportKey(format, key);
10246 }
10247
10248 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
10249 return DesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
10250 }
10251
10252 async onEncrypt(algorithm, key, data) {
10253 return DesCrypto.encrypt(algorithm, key, data);
10254 }
10255
10256 async onDecrypt(algorithm, key, data) {
10257 return DesCrypto.decrypt(algorithm, key, data);
10258 }
10259
10260 }
10261
10262 class DesEde3CbcProvider extends DesProvider {
10263 constructor() {
10264 super(...arguments);
10265 this.keySizeBits = 192;
10266 this.ivSize = 8;
10267 this.name = "DES-EDE3-CBC";
10268 }
10269
10270 async onGenerateKey(algorithm, extractable, keyUsages) {
10271 return DesCrypto.generateKey(algorithm, extractable, keyUsages);
10272 }
10273
10274 async onExportKey(format, key) {
10275 return DesCrypto.exportKey(format, key);
10276 }
10277
10278 async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
10279 return DesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
10280 }
10281
10282 async onEncrypt(algorithm, key, data) {
10283 return DesCrypto.encrypt(algorithm, key, data);
10284 }
10285
10286 async onDecrypt(algorithm, key, data) {
10287 return DesCrypto.decrypt(algorithm, key, data);
10288 }
10289
10290 }
10291
10292 class SubtleCrypto$1 extends SubtleCrypto {
10293 constructor() {
10294 super();
10295 this.browserInfo = BrowserInfo();
10296 this.providers.set(new AesCbcProvider$1());
10297 this.providers.set(new AesCtrProvider$1());
10298 this.providers.set(new AesEcbProvider$1());
10299 this.providers.set(new AesGcmProvider$1());
10300 this.providers.set(new AesKwProvider$1());
10301 this.providers.set(new DesCbcProvider());
10302 this.providers.set(new DesEde3CbcProvider());
10303 this.providers.set(new RsaSsaProvider$1());
10304 this.providers.set(new RsaPssProvider$1());
10305 this.providers.set(new RsaOaepProvider$1());
10306 this.providers.set(new EcdsaProvider$1());
10307 this.providers.set(new EcdhProvider$1());
10308 this.providers.set(new Sha1Provider());
10309 this.providers.set(new Sha256Provider());
10310 this.providers.set(new Sha512Provider());
10311 this.providers.set(new Pbkdf2Provider$1());
10312 }
10313
10314 static isAnotherKey(key) {
10315 if (typeof key === "object" && typeof key.type === "string" && typeof key.extractable === "boolean" && typeof key.algorithm === "object") {
10316 return !(key instanceof CryptoKey$1);
10317 }
10318
10319 return false;
10320 }
10321
10322 async digest(...args) {
10323 return this.wrapNative("digest", ...args);
10324 }
10325
10326 async importKey(...args) {
10327 this.fixFirefoxEcImportPkcs8(args);
10328 return this.wrapNative("importKey", ...args);
10329 }
10330
10331 async exportKey(...args) {
10332 return (await this.fixFirefoxEcExportPkcs8(args)) || (await this.wrapNative("exportKey", ...args));
10333 }
10334
10335 async generateKey(...args) {
10336 return this.wrapNative("generateKey", ...args);
10337 }
10338
10339 async sign(...args) {
10340 return this.wrapNative("sign", ...args);
10341 }
10342
10343 async verify(...args) {
10344 return this.wrapNative("verify", ...args);
10345 }
10346
10347 async encrypt(...args) {
10348 return this.wrapNative("encrypt", ...args);
10349 }
10350
10351 async decrypt(...args) {
10352 return this.wrapNative("decrypt", ...args);
10353 }
10354
10355 async wrapKey(...args) {
10356 return this.wrapNative("wrapKey", ...args);
10357 }
10358
10359 async unwrapKey(...args) {
10360 return this.wrapNative("unwrapKey", ...args);
10361 }
10362
10363 async deriveBits(...args) {
10364 return this.wrapNative("deriveBits", ...args);
10365 }
10366
10367 async deriveKey(...args) {
10368 return this.wrapNative("deriveKey", ...args);
10369 }
10370
10371 async wrapNative(method, ...args) {
10372 if (~["generateKey", "unwrapKey", "deriveKey", "importKey"].indexOf(method)) {
10373 this.fixAlgorithmName(args);
10374 }
10375
10376 try {
10377 if (method !== "digest" || !args.some(a => a instanceof CryptoKey$1)) {
10378 Debug.info(`Call native '${method}' method`, args);
10379 const res = await nativeSubtle[method].apply(nativeSubtle, args);
10380 return res;
10381 }
10382 } catch (e) {
10383 Debug.warn(`Error on native '${method}' calling. ${e.message}`, e);
10384 }
10385
10386 if (method === "wrapKey") {
10387 try {
10388 Debug.info(`Trying to wrap key by using native functions`, args);
10389 const data = await this.exportKey(args[0], args[1]);
10390 const keyData = args[0] === "jwk" ? Convert.FromUtf8String(JSON.stringify(data)) : data;
10391 const res = await this.encrypt(args[3], args[2], keyData);
10392 return res;
10393 } catch (e) {
10394 Debug.warn(`Cannot wrap key by native functions. ${e.message}`, e);
10395 }
10396 }
10397
10398 if (method === "unwrapKey") {
10399 try {
10400 Debug.info(`Trying to unwrap key by using native functions`, args);
10401 const data = await this.decrypt(args[3], args[2], args[1]);
10402 const keyData = args[0] === "jwk" ? JSON.parse(Convert.ToUtf8String(data)) : data;
10403 const res = await this.importKey(args[0], keyData, args[4], args[5], args[6]);
10404 return res;
10405 } catch (e) {
10406 Debug.warn(`Cannot unwrap key by native functions. ${e.message}`, e);
10407 }
10408 }
10409
10410 if (method === "deriveKey") {
10411 try {
10412 Debug.info(`Trying to derive key by using native functions`, args);
10413 const data = await this.deriveBits(args[0], args[1], args[2].length);
10414 const res = await this.importKey("raw", data, args[2], args[3], args[4]);
10415 return res;
10416 } catch (e) {
10417 Debug.warn(`Cannot derive key by native functions. ${e.message}`, e);
10418 }
10419 }
10420
10421 if (method === "deriveBits" || method === "deriveKey") {
10422 for (const arg of args) {
10423 if (typeof arg === "object" && arg.public && SubtleCrypto$1.isAnotherKey(arg.public)) {
10424 arg.public = await this.castKey(arg.public);
10425 }
10426 }
10427 }
10428
10429 for (let i = 0; i < args.length; i++) {
10430 const arg = args[i];
10431
10432 if (SubtleCrypto$1.isAnotherKey(arg)) {
10433 args[i] = await this.castKey(arg);
10434 }
10435 }
10436
10437 return super[method].apply(this, args);
10438 }
10439
10440 async castKey(key) {
10441 Debug.info("Cast native CryptoKey to linter key.", key);
10442
10443 if (!key.extractable) {
10444 throw new Error("Cannot cast unextractable crypto key");
10445 }
10446
10447 const provider = this.getProvider(key.algorithm.name);
10448 const jwk = await this.exportKey("jwk", key);
10449 return provider.importKey("jwk", jwk, key.algorithm, true, key.usages);
10450 }
10451
10452 fixAlgorithmName(args) {
10453 if (this.browserInfo.name === Browser.Edge) {
10454 for (let i = 0; i < args.length; i++) {
10455 const arg = args[0];
10456
10457 if (typeof arg === "string") {
10458 for (const algorithm of this.providers.algorithms) {
10459 if (algorithm.toLowerCase() === arg.toLowerCase()) {
10460 args[i] = algorithm;
10461 break;
10462 }
10463 }
10464 } else if (typeof arg === "object" && typeof arg.name === "string") {
10465 for (const algorithm of this.providers.algorithms) {
10466 if (algorithm.toLowerCase() === arg.name.toLowerCase()) {
10467 arg.name = algorithm;
10468 }
10469
10470 if (typeof arg.hash === "string" && algorithm.toLowerCase() === arg.hash.toLowerCase() || typeof arg.hash === "object" && typeof arg.hash.name === "string" && algorithm.toLowerCase() === arg.hash.name.toLowerCase()) {
10471 arg.hash = {
10472 name: algorithm
10473 };
10474 }
10475 }
10476 }
10477 }
10478 }
10479 }
10480
10481 fixFirefoxEcImportPkcs8(args) {
10482 const preparedAlgorithm = this.prepareAlgorithm(args[2]);
10483 const algName = preparedAlgorithm.name.toUpperCase();
10484
10485 if (this.browserInfo.name === Browser.Firefox && args[0] === "pkcs8" && ~["ECDSA", "ECDH"].indexOf(algName) && ~["P-256", "P-384", "P-521"].indexOf(preparedAlgorithm.namedCurve)) {
10486 if (!BufferSourceConverter.isBufferSource(args[1])) {
10487 throw new TypeError("data: Is not ArrayBuffer or ArrayBufferView");
10488 }
10489
10490 const preparedData = BufferSourceConverter.toArrayBuffer(args[1]);
10491 const keyInfo = build_5.parse(preparedData, PrivateKeyInfo);
10492 const privateKey = build_5.parse(keyInfo.privateKey, EcPrivateKey);
10493 const jwk = build_2$1.toJSON(privateKey);
10494 jwk.ext = true;
10495 jwk.key_ops = args[4];
10496 jwk.crv = preparedAlgorithm.namedCurve;
10497 jwk.kty = "EC";
10498 args[0] = "jwk";
10499 args[1] = jwk;
10500 }
10501 }
10502
10503 async fixFirefoxEcExportPkcs8(args) {
10504 try {
10505 if (this.browserInfo.name === Browser.Firefox && args[0] === "pkcs8" && ~["ECDSA", "ECDH"].indexOf(args[1].algorithm.name) && ~["P-256", "P-384", "P-521"].indexOf(args[1].algorithm.namedCurve)) {
10506 const jwk = await this.exportKey("jwk", args[1]);
10507 const ecKey = build_3$1.fromJSON(jwk, {
10508 targetSchema: EcPrivateKey
10509 });
10510 const keyInfo = new PrivateKeyInfo();
10511 keyInfo.privateKeyAlgorithm.algorithm = EcCrypto.ASN_ALGORITHM;
10512 keyInfo.privateKeyAlgorithm.parameters = build_6.serialize(new ObjectIdentifier(getOidByNamedCurve(args[1].algorithm.namedCurve)));
10513 keyInfo.privateKey = build_6.serialize(ecKey);
10514 return build_6.serialize(keyInfo);
10515 }
10516 } catch (err) {
10517 Debug.error(err);
10518 return null;
10519 }
10520 }
10521
10522 }
10523
10524 SubtleCrypto$1.methods = ["digest", "importKey", "exportKey", "sign", "verify", "generateKey", "encrypt", "decrypt", "deriveBits", "deriveKey", "wrapKey", "unwrapKey"];
10525
10526 class Crypto$1 extends Crypto {
10527 constructor() {
10528 super(...arguments);
10529 this.subtle = new SubtleCrypto$1();
10530 }
10531
10532 getRandomValues(array) {
10533 return nativeCrypto.getRandomValues(array);
10534 }
10535
10536 }
10537
10538 if (!Math.imul) {
10539 Math.imul = function imul(a, b) {
10540 const ah = a >>> 16 & 0xffff;
10541 const al = a & 0xffff;
10542 const bh = b >>> 16 & 0xffff;
10543 const bl = b & 0xffff;
10544 return al * bl + (ah * bl + al * bh << 16 >>> 0) | 0;
10545 };
10546 }
10547exports.crypto = new Crypto$1(); // section modified by isomorphic-webcrypto build
10548 return exports;
10549
10550}({}));
10551
10552 module.exports = liner; // section modified by isomorphic-webcrypto build