@it-enterprise/digital-signature 1.1.7 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,12 @@
1
- import { EndUser, EndUserConstants, EndUserProxySettings, EndUserError, KSPSettings, EndUserCertificate, EndUserKeyMedia } from "../euscp/euscp";
2
- import { DigitalSignatureKeyType, PrivateKeyInfo, FilePrivateKeyInfo, HardwarePrivateKeyInfo, KspPrivateKeyInfo } from "./Models";
3
- import { downloadData, readFile } from "./Utils";
1
+ import { EndUser, EndUserConstants, EndUserProxySettings, EndUserError, KSPSettings, EndUserCertificate, EndUserKeyMedia, EndUserSignContainerInfo } from "../euscp/euscp";
2
+ import { DigitalSignatureKeyType, PrivateKeyInfo, FilePrivateKeyInfo, HardwarePrivateKeyInfo, KspPrivateKeyInfo, SignFormat, DigitalSignatureFormat } from "./Models";
3
+ import { downloadAndSignFiles, downloadData, format, readFile, signAlgoToHashAlgo } from "./Utils";
4
4
  import Resourses from "./Resourses.json";
5
5
  import GlSign from "./GlSign";
6
6
 
7
+ const PRIVATE_KEY_TYPE = "PKType";
8
+ const PRIVATE_KEY_INFO = "PKInfo";
9
+
7
10
  export default class DigitalSignature {
8
11
  /**
9
12
  * @param {DigitalSignatureSettings} settingsProvider
@@ -33,30 +36,74 @@ export default class DigitalSignature {
33
36
  depositsign.ksp = EndUserConstants.EU_KSP_IIT;
34
37
  depositsign.address = "https://depositsign.com/api/v1/it-enterprise/sign-server";
35
38
  depositsign.directAccess = true;
39
+ depositsign.needQrcode = false;
36
40
 
37
41
  const diia = new KSPSettings();
38
- diia.name = "ДіЯ";
42
+ diia.name = "Дія.Підпис";
39
43
  diia.ksp = EndUserConstants.EU_KSP_DIIA;
40
44
  diia.directAccess = true;
41
- diia.mobileAppName = "ДіЯ";
45
+ diia.mobileAppName = "Дія";
42
46
  diia.address = "https://diia-sign.it.ua/KSPSign";
43
47
  diia.systemId = "diia-sign-it-ent";
44
-
45
- /** @type {KSPSettings} */
46
- this._KSPs = [depositsign, diia];
48
+ diia.needQrcode = true;
49
+
50
+ const smartId = new KSPSettings();
51
+ smartId.name = "Приватбанк - хмарний підпис \"SmartID\"";
52
+ smartId.ksp = EndUserConstants.EU_KSP_PB;
53
+ smartId.directAccess = true;
54
+ smartId.mobileAppName = "Приват24";
55
+ smartId.address = "https://acsk.privatbank.ua/cloud/api/back/";
56
+ smartId.clientIdPrefix = "IEIS_";
57
+ smartId.confirmationURL = "https://www.privat24.ua/rd/kep";
58
+ smartId.needQrcode = true;
59
+
60
+ const vchasno = new KSPSettings();
61
+ vchasno.name = "Вчасно - хмарний підпис";
62
+ vchasno.ksp = EndUserConstants.EU_KSP_IIT;
63
+ vchasno.address = "https://cs.vchasno.ua/ss/";
64
+ vchasno.directAccess = true;
65
+ vchasno.needQrcode = false;
66
+
67
+ const cloudKey = new KSPSettings();
68
+ cloudKey.name = "ТОВ «ЦСК «Україна» - хмарний підпис CloudKey";
69
+ cloudKey.ksp = EndUserConstants.EU_KSP_PB;
70
+ cloudKey.directAccess = true;
71
+ cloudKey.mobileAppName = "CloudKey";
72
+ cloudKey.address = "https://sid.uakey.com.ua/smartid/iit/";
73
+ cloudKey.clientIdPrefix = "DIIA_2";
74
+ cloudKey.confirmationURL = "https://sid.uakey.com.ua/kep?hash=rd/kep";
75
+ cloudKey.needQrcode = true;
76
+
77
+ const esign = new KSPSettings();
78
+ esign.name = "ESign - хмарний підпис";
79
+ esign.ksp = EndUserConstants.EU_KSP_IIT;
80
+ esign.address = "https://cabinet.e-life.com.ua/api/EDG/Sign";
81
+ esign.directAccess = true;
82
+ esign.needQrcode = false;
83
+
84
+ this._KSPs = {
85
+ depositsign,
86
+ diia,
87
+ smartId,
88
+ vchasno,
89
+ cloudKey,
90
+ esign,
91
+ asArray: function() {
92
+ return [
93
+ depositsign,
94
+ diia,
95
+ smartId,
96
+ vchasno,
97
+ cloudKey,
98
+ esign
99
+ ];
100
+ }
101
+ };
47
102
 
48
103
  /** @type {PrivateKeyInfo} */
49
104
  this._readedKey = null;
50
105
  }
51
106
 
52
- get PRIVATE_KEY_TYPE() {
53
- return "_PrivateKeyType";
54
- }
55
-
56
- get PRIVATE_KEY_INFO() {
57
- return "_PrivateKeyInfo";
58
- }
59
-
60
107
  /**
61
108
  * Считанный приватный ключ
62
109
  * @type {PrivateKeyInfo}
@@ -78,15 +125,17 @@ export default class DigitalSignature {
78
125
  * @param {number} type
79
126
  */
80
127
  async setLibraryType(type) {
81
- if (this._euSign) {
82
- await this._euSign.ResetPrivateKey();
83
- }
84
-
85
128
  switch (type) {
86
129
  case DigitalSignatureKeyType.Token:
130
+ if (this._euSign === this._euSignKeyMedia) {
131
+ return;
132
+ }
87
133
  this._euSign = this._euSignKeyMedia;
88
134
  break;
89
135
  default:
136
+ if (this._euSign === this._euSignFile) {
137
+ return;
138
+ }
90
139
  this._euSign = this._euSignFile;
91
140
  break;
92
141
  }
@@ -104,7 +153,6 @@ export default class DigitalSignature {
104
153
  * @returns {Promise<number>} Текущий тип библиотеки
105
154
  */
106
155
  async initialise() {
107
-
108
156
  if (!this._glSign) {
109
157
  this._glSign = await Promise.resolve(this._settingsProvider.getGlSign());
110
158
  }
@@ -187,7 +235,19 @@ export default class DigitalSignature {
187
235
  }
188
236
 
189
237
  if (!this._euSettings) {
190
- const certificates = await this._settings.certificatesProvider.loadCertificates();
238
+ let certificates;
239
+ try {
240
+ certificates = await this._settings.certificatesProvider.loadCertificates();
241
+ } catch (error) {
242
+ if (error && error.code === EndUserError.EU_ERROR_DOWNLOAD_FILE) {
243
+ throw {
244
+ code: EndUserError.EU_ERROR_DOWNLOAD_FILE,
245
+ message: this._resourses.DownloadingRootCertificatesError
246
+ };
247
+ } else {
248
+ throw error;
249
+ }
250
+ }
191
251
 
192
252
  this._euSettings = {
193
253
  language: this._settings.language,
@@ -196,14 +256,14 @@ export default class DigitalSignature {
196
256
  directAccess: true,
197
257
  CAs: certificates.CAs,
198
258
  CACertificates: certificates.CACertificates,
199
- mssServiceURL: this._settings.mssServiceURL,
200
- KSPs: this._KSPs,
259
+ KSPs: this.KSPs,
201
260
  allowedKeyMediaTypes: [
202
261
  "е.ключ BIFIT iToken",
203
262
  "криптомод. ІІТ Гряда-61",
204
- "криптомод. ІІТ Гряда-301",
205
263
  "е.ключ ІІТ Алмаз-1К",
264
+ "е.ключ ІІТ Алмаз-1К (Bluetooth)",
206
265
  "е.ключ ІІТ Кристал-1",
266
+ "криптомод. ІІТ Гряда-301",
207
267
  "ID-карта громадянина (БЕН)",
208
268
  "е.ключ ІІТ Алмаз-1К (PKCS#11)",
209
269
  "е.ключ ІІТ Кристал-1 (PKCS#11)",
@@ -243,6 +303,7 @@ export default class DigitalSignature {
243
303
  if (euSign === this._euSignKeyMedia && !await this._euSignFile.IsInitialized()) {
244
304
  this._euSignFile.SetRuntimeParameter(EndUserConstants.EU_SIGN_TYPE_PARAMETER, EndUserConstants.EndUserSignType.CAdES_X_Long);
245
305
  }
306
+
246
307
  return this.getLibraryType();
247
308
  }
248
309
 
@@ -256,13 +317,13 @@ export default class DigitalSignature {
256
317
 
257
318
  /**
258
319
  * Получить список подключённых устройств
259
- * @returns {Promise<Array<EndUserKeyMedia>>} Информация о владельце ключа
320
+ * @returns {Promise<Array<EndUserKeyMedia>>} Список подключённых устройств
260
321
  */
261
322
  async getKeyMedias() {
262
- if (this._euSign != this._euSignKeyMedia) {
323
+ if (!this._euSignKeyMedia) {
263
324
  await this.setLibraryType(DigitalSignatureKeyType.Token);
264
325
  }
265
- return this._euSign.GetKeyMedias();
326
+ return this._euSignKeyMedia.GetKeyMedias();
266
327
  }
267
328
 
268
329
  /**
@@ -271,20 +332,57 @@ export default class DigitalSignature {
271
332
  * @param {Array<Uint8Array>?} certs - Сертификаты ключа (при необходимости)
272
333
  */
273
334
  async readHardwareKey(keyMedia, certs) {
274
- if (this._euSign != this._euSignKeyMedia) {
275
- await this.setLibraryType(DigitalSignatureKeyType.Token);
335
+ await this.setLibraryType(DigitalSignatureKeyType.Token);
336
+
337
+ if (!keyMedia) {
338
+ throw {
339
+ code: EndUserError.EU_ERROR_BAD_PARAMETER,
340
+ message: this._resourses.BadParameter + " keyMedia"
341
+ };
276
342
  }
343
+ if (!keyMedia.password) {
344
+ throw {
345
+ code: EndUserError.EU_ERROR_BAD_PARAMETER,
346
+ message: this._resourses.PasswordNotSet
347
+ };
348
+ }
349
+
277
350
  if (Array.isArray(certs)) {
278
351
  certs = await Promise.all(certs.map(cert => cert instanceof File || cert instanceof Blob ? readFile(cert) : cert));
279
352
  }
280
- const ownerInfo = await this._euSign.ReadPrivateKey(keyMedia, certs, this._selectedIssuerCN);
281
- this._readedKey = new HardwarePrivateKeyInfo(
282
- DigitalSignatureKeyType.Token,
283
- ownerInfo,
284
- await this._euSign.GetOwnCertificates(),
285
- keyMedia
286
- );
287
- return this._readedKey;
353
+
354
+ try {
355
+ const ownerInfo = await this._euSign.ReadPrivateKey(keyMedia, certs, this._selectedIssuerCN);
356
+ this._readedKey = new HardwarePrivateKeyInfo(
357
+ DigitalSignatureKeyType.Token,
358
+ ownerInfo,
359
+ await this._euSign.GetOwnCertificates(),
360
+ keyMedia
361
+ );
362
+ return this._readedKey;
363
+ } catch (error) {
364
+ if (error && error.code === EndUserError.EU_ERROR_CERT_NOT_FOUND) {
365
+ if (!this._selectedIssuerCN) {
366
+ throw {
367
+ code: EndUserError.EU_ERROR_CERT_NOT_FOUND,
368
+ message: this._resourses.ReadPrivateKeyCAAutoDetectError
369
+ };
370
+ } else if (this._selectedIssuerCN) {
371
+ if (!this._selectedCA.cmpAddress) {
372
+ throw {
373
+ code: EndUserError.EU_ERROR_CERT_NOT_FOUND,
374
+ message: format(this._resourses.ReadPrivateKeyNeedCertificateError, this._selectedIssuerCN)
375
+ };
376
+ } else {
377
+ throw {
378
+ code: EndUserError.EU_ERROR_CERT_NOT_FOUND,
379
+ message: format(this._resourses.ReadPrivateKeyInvalidCAError, this._selectedIssuerCN)
380
+ };
381
+ }
382
+ }
383
+ }
384
+ throw error;
385
+ }
288
386
  }
289
387
 
290
388
  /**
@@ -294,26 +392,60 @@ export default class DigitalSignature {
294
392
  * @param {Array<Uint8Array|File>?} certs - Сертификаты ключа (при необходимости)
295
393
  */
296
394
  async readFileKey(privateKey, password, certs) {
297
- let keyName = "Key";
298
- if (this._euSign != this._euSignFile) {
299
- await this.setLibraryType(DigitalSignatureKeyType.File);
395
+ await this.setLibraryType(DigitalSignatureKeyType.File);
396
+
397
+ if (!privateKey) {
398
+ throw {
399
+ code: EndUserError.EU_ERROR_BAD_PARAMETER,
400
+ message: this._resourses.BadParameter + " keyMedia"
401
+ };
402
+ }
403
+ if (!password) {
404
+ throw {
405
+ code: EndUserError.EU_ERROR_BAD_PARAMETER,
406
+ message: this._resourses.PasswordNotSet
407
+ };
300
408
  }
409
+
301
410
  if (privateKey instanceof File || privateKey instanceof Blob) {
302
- keyName = privateKey.name;
303
411
  privateKey = await readFile(privateKey);
304
412
  }
305
413
  if (Array.isArray(certs)) {
306
414
  certs = await Promise.all(certs.map(cert => cert instanceof File || cert instanceof Blob ? readFile(cert) : cert));
307
415
  }
308
- const ownerInfo = await this._euSign.ReadPrivateKeyBinary(privateKey, password, certs, this._selectedIssuerCN);
309
- this._readedKey = new FilePrivateKeyInfo(
310
- DigitalSignatureKeyType.File,
311
- ownerInfo,
312
- await this._euSign.GetOwnCertificates(),
313
- privateKey,
314
- this.glSign.AllowSavePassword ? password : undefined
315
- );
316
- return this._readedKey;
416
+ try {
417
+ const ownerInfo = await this._euSign.ReadPrivateKeyBinary(privateKey, password, certs, this._selectedIssuerCN);
418
+ this._readedKey = new FilePrivateKeyInfo(
419
+ DigitalSignatureKeyType.File,
420
+ ownerInfo,
421
+ await this._euSign.GetOwnCertificates(),
422
+ privateKey,
423
+ password
424
+ );
425
+ return this._readedKey;
426
+ } catch (error) {
427
+ if (error && error.code === EndUserError.EU_ERROR_CERT_NOT_FOUND) {
428
+ if (!this._selectedIssuerCN) {
429
+ throw {
430
+ code: EndUserError.EU_ERROR_CERT_NOT_FOUND,
431
+ message: this._resourses.ReadPrivateKeyCAAutoDetectError
432
+ };
433
+ } else if (this._selectedIssuerCN) {
434
+ if (!this._selectedCA.cmpAddress) {
435
+ throw {
436
+ code: EndUserError.EU_ERROR_CERT_NOT_FOUND,
437
+ message: format(this._resourses.ReadPrivateKeyNeedCertificateError, this._selectedIssuerCN)
438
+ };
439
+ } else {
440
+ throw {
441
+ code: EndUserError.EU_ERROR_CERT_NOT_FOUND,
442
+ message: format(this._resourses.ReadPrivateKeyInvalidCAError, this._selectedIssuerCN)
443
+ };
444
+ }
445
+ }
446
+ }
447
+ throw error;
448
+ }
317
449
  }
318
450
 
319
451
  /**
@@ -322,9 +454,8 @@ export default class DigitalSignature {
322
454
  * @returns {Promise<EndUserJKSPrivateKeyInfo[]>}
323
455
  */
324
456
  async getJKSPrivateKeys(jks) {
325
- if (this._euSign != this._euSignFile) {
326
- await this.setLibraryType(DigitalSignatureKeyType.File);
327
- }
457
+ await this.setLibraryType(DigitalSignatureKeyType.File);
458
+
328
459
  if (jks instanceof File || jks instanceof Blob) {
329
460
  jks = await readFile(jks);
330
461
  }
@@ -340,56 +471,44 @@ export default class DigitalSignature {
340
471
  }
341
472
 
342
473
  /**
343
- * Считать ключ с DepositSign
344
- * @param {string} userId - Идентификатор пользователя
345
- * @param {boolean?} getCerts - Получать информацию о ключе пользователя. Это приведёт к дополнительному запросу на подписание
346
- */
474
+ * Считать ключ с DepositSign
475
+ * @param {string} userId - Идентификатор пользователя
476
+ * @param {boolean?} getCerts - Получать информацию о ключе пользователя. Это приведёт к дополнительному запросу на подписание
477
+ */
347
478
  async readPrivateKeyDepositsign(userId, getCerts = false) {
348
- return await this.readPrivateKeyKSP(userId, this.KSPs[0], getCerts);
479
+ return await this.readPrivateKeyKSP(userId, this._KSPs.depositsign, getCerts);
349
480
  }
350
481
 
351
482
  /**
352
483
  * Считать ключ с Дiя
353
484
  * @param {boolean?} getCerts - Получать информацию о ключе пользователя. Это приведёт к дополнительному запросу на подписание
354
485
  */
355
- async readPrivateKeyDiia(getCerts = false) {
356
- const diia = "DIIA";
357
- if (sessionStorage[diia] != "+") {
358
- try {
359
- sessionStorage[diia] = await downloadData(new URL(this.KSPs[1].address).origin + "/diia");
360
- } catch {
361
- throw {
362
- message: this._resourses.DiiaError + `<a target="_blank" href="${window.origin}">${window.origin}</a></li><ul>`
363
- };
364
- }
365
- }
366
-
367
- return await this.readPrivateKeyKSP(null, this.KSPs[1], getCerts);
486
+ async readPrivateKeyDiia(getCerts = false) {
487
+ return await this.readPrivateKeyKSP(null, this.KSPs.diia, getCerts);
368
488
  }
369
489
 
370
490
  /**
371
491
  * Считать ключ с облачного провайдера
372
- * @param {string} userId - Идентификатор пользователя
373
- * @param {string|KSPSettings} ksp - Идентификатор облачного провайдера
492
+ * @param {KSPSettings} ksp - Идентификатор облачного провайдера
493
+ * @param {string?} userId - Идентификатор пользователя
374
494
  * @param {boolean?} getCerts - Получать информацию о ключе пользователя. Это приведёт к дополнительному запросу на подписание
375
- * @param {number?} keyType - Тип ключа
376
495
  */
377
- async readPrivateKeyKSP(userId, ksp, getCerts = false) {
378
- if (ksp != EndUserConstants.EndUserKSP.DIIA && typeof ksp !== "string") {
379
- ksp = ksp.name;
380
- }
381
- const keyType = ksp == "DepositSign" ? DigitalSignatureKeyType.Depositsign : ksp == "diia" ? DigitalSignatureKeyType.Diia : DigitalSignatureKeyType.KSP;
382
- if (this._euSign != this._euSignFile) {
383
- await this.setLibraryType(keyType);
496
+ async readPrivateKeyKSP(ksp, userId, getCerts = false) {
497
+ await this.setLibraryType(DigitalSignatureKeyType.KSP);
498
+
499
+ if (ksp.ksp === EndUserConstants.EU_KSP_DIIA) {
500
+ await this._diiaCheckAccess();
384
501
  }
385
- const ownerInfo = await this._euSign.ReadPrivateKeyKSP(userId, ksp, getCerts);
502
+
503
+ const ownerInfo = await this._euSign.ReadPrivateKeyKSP(userId, ksp.name, getCerts);
386
504
  if (getCerts && !ownerInfo) {
387
505
  throw {
506
+ code: EndUserError.EU_ERROR_KEY_MEDIAS_READ_FAILED,
388
507
  message: this._resourses.PrivateKeyNotReaded
389
508
  };
390
509
  }
391
510
  this._readedKey = new KspPrivateKeyInfo(
392
- keyType,
511
+ DigitalSignatureKeyType.KSP,
393
512
  ownerInfo,
394
513
  getCerts ? await this._euSign.GetOwnCertificates() : [],
395
514
  userId,
@@ -419,7 +538,7 @@ export default class DigitalSignature {
419
538
  * @returns {KSPSettings[]} Список поддержирживаемых облачных провайдеров
420
539
  */
421
540
  get KSPs() {
422
- return this._KSPs;
541
+ return this._KSPs.asArray();
423
542
  }
424
543
 
425
544
  /**
@@ -427,16 +546,18 @@ export default class DigitalSignature {
427
546
  * @returns {Promise<boolean>} считан ли ключ
428
547
  */
429
548
  async isPrivateKeyReaded() {
430
- return !!this._readedKey && await this._euSign.IsPrivateKeyReaded();
549
+ try {
550
+ return !!this._readedKey && await this._euSign.IsPrivateKeyReaded();
551
+ } catch {
552
+ return false;
553
+ }
431
554
  }
432
555
 
433
556
  /**
434
557
  * Очистить считанный ключ
435
558
  */
436
559
  async resetPrivateKey() {
437
- await Promise.all([
438
- this._euSign.ResetPrivateKey()
439
- ]);
560
+ await this._euSign.ResetPrivateKey();
440
561
  this._readedKey = null;
441
562
  }
442
563
 
@@ -445,7 +566,7 @@ export default class DigitalSignature {
445
566
  * @returns {Promise<Array<CASettings>>}
446
567
  */
447
568
  async getCAs() {
448
- return await this._euSign.GetCAs();
569
+ return await this._euSignFile.GetCAs();
449
570
  }
450
571
 
451
572
  /**
@@ -469,49 +590,67 @@ export default class DigitalSignature {
469
590
 
470
591
  /**
471
592
  * Подписать данные
472
- * @param {Uint8Array | string | NamedeData | Array<Uint8Array | string | NamedeData>} data - Данные для подписи. Можно передавать данные в массиве для наложения нескольких подписей за раз
473
- * @param {boolean?} internal - Внутренняя или внешняя подпись
593
+ * @param {Uint8Array | string | NamedData | Array<Uint8Array | string | NamedData>} data - Данные для подписи. Можно передавать данные в массиве для наложения нескольких подписей за раз
594
+ * @param {EndUserSignContainerInfo?} signType - Тип подписи
474
595
  * @param {boolean?} asByteArray - Возвращать подпись в виде массива байтов. По умолчанию подпись возвращается в виде строки в base64
475
596
  */
476
- async signData(data, internal, asByteArray) {
477
- if (typeof internal !== "boolean") {
478
- internal = false;
597
+ async signData(data, signType, asByteArray) {
598
+ if (signType === true) {
599
+ // Обратная совместимость. Если передать в параметре значение true, дожна создаться подпись CAdES Enveloped (внутренняя)
600
+ signType = new EndUserSignContainerInfo();
601
+ signType.type = EndUserConstants.EndUserSignContainerType.CAdES;
602
+ signType.subType = EndUserConstants.EndUserCAdESType.Enveloped;
603
+ } else if (typeof signType != "object") {
604
+ // По умолчанию создаётся подпись CAdES Detached
605
+ signType = new EndUserSignContainerInfo();
606
+ signType.type = EndUserConstants.EndUserSignContainerType.CAdES;
607
+ signType.subType = EndUserConstants.EndUserCAdESType.Detached;
479
608
  }
480
609
  if (typeof asByteArray !== "boolean") {
481
610
  asByteArray = false;
482
611
  }
483
- return await this._euSign.SignDataEx(this._readedKey.getSignAlgo(), data, !internal, true, !asByteArray);
612
+
613
+ if (this.readedKey.keyType === DigitalSignatureKeyType.KSP && signType !== EndUserConstants.EndUserSignContainerType.CAdES) {
614
+ throw {
615
+ code: EndUserError.EU_ERROR_NOT_SUPPORTED,
616
+ message: this._resourses.KSPSignFormatError
617
+ };
618
+ }
619
+
620
+ if (signType.type === EndUserConstants.EndUserSignContainerType.ASiC) {
621
+ const signLevel = signType.asicSignType === EndUserConstants.EndUserASiCSignType.CAdES ? EndUserConstants.EndUserSignType.CAdES_X_Long : EndUserConstants.EndUserXAdESSignLevel.B_LT;
622
+ return await this._euSign.ASiCSignData(this._readedKey.getSignAlgo(), signType.subType, signType.asicSignType, signLevel, data, !asByteArray);
623
+ } else if (signType.type === EndUserConstants.EndUserSignContainerType.XAdES) {
624
+ return (await this._euSign.XAdESSignData(this._readedKey.getSignAlgo(), signType.subType, EndUserConstants.EndUserXAdESSignLevel.B_LT, data, !asByteArray));
625
+ } else if (signType.type === EndUserConstants.EndUserSignContainerType.PAdES) {
626
+ return await this._euSign.PDFSignData(this._readedKey.getSignAlgo(), data, EndUserConstants.EndUserPAdESSignLevel.B_T, !asByteArray);
627
+ } else if (signType.type === EndUserConstants.EndUserSignContainerType.CAdES) {
628
+ if (signType.subType === EndUserConstants.EndUserCAdESType.Detached) {
629
+ const hash = await this._euSign.HashData(this._readedKey.getHashAlgo(), data, !asByteArray);
630
+ return await this._euSign.SignHash(this._readedKey.getSignAlgo(), hash, true, !asByteArray);
631
+ } else {
632
+ return await this._euSign.SignDataEx(this._readedKey.getSignAlgo(), data, false, true, !asByteArray);
633
+ }
634
+ } else {
635
+ throw {
636
+ code: EndUserError.EU_ERROR_BAD_PARAMETER,
637
+ message: this._resourses.BadSignatureType
638
+ };
639
+ }
484
640
  }
485
641
 
486
642
  /**
487
643
  * Подписать файл
488
- * @param {string | NamedeData | Array<string | NamedeData>} fileUrl - Ссылка на загрузку файла. Можно передавать несколько ссылок в массиве для наложения нескольких подписей за раз
489
- * @param {boolean?} internal - Внутренняя или внешняя подпись
644
+ * @param {string | NamedData | Array<string | NamedData>} fileUrl - Ссылка на загрузку файла. Можно передавать несколько ссылок в массиве для наложения нескольких подписей за раз
645
+ * @param {EndUserSignContainerInfo?} signType - Тип подписи
490
646
  * @param {boolean?} asByteArray - Возвращать подпись в виде массива байт. По умолчанию подпись возвращается в виде строки в base64
491
647
  */
492
- async signFile(fileUrl, internal, asByteArray) {
493
- if (typeof internal !== "boolean") {
494
- internal = false;
495
- }
496
- if (typeof asByteArray !== "boolean") {
497
- asByteArray = false;
498
- }
499
- const isNamedData = Array.isArray(fileUrl) && fileUrl.every(url => typeof url === "object") || typeof fileUrl === "object";
500
- let data;
501
- if (Array.isArray(fileUrl)) {
502
- data = await Promise.all(fileUrl.map(function(url) {
503
- const downloadedData = downloadData(isNamedData ? url.val : url, "binary");
504
- return isNamedData ? {name: url.name, val: downloadedData} : downloadedData;
505
- }));
506
- } else {
507
- const downloadedData = await downloadData(isNamedData ? fileUrl.val : fileUrl, "binary");
508
- data = isNamedData ? {name: fileUrl.name, val: downloadedData} : downloadedData;
509
- }
510
- return await this.signData(data, internal, asByteArray);
648
+ async signFile(fileUrl, signType, asByteArray) {
649
+ return await downloadAndSignFiles(fileUrl, async (data) => await this.signData(data, signType, asByteArray));
511
650
  }
512
651
 
513
652
  /**
514
- * Подписать хеш
653
+ * Подписать хеш подписью CAdES Detached
515
654
  * @param {Uint8Array | string | NamedData | Array<Uint8Array | string> | NamedData} hash - Хеш файла. Можно передавать несколько хешей в массиве для наложения нескольких подписей за раз
516
655
  * @param {boolean?} asByteArray - Возвращать подпись в виде массива байт. По умолчанию подпись возвращается в виде строки в base64
517
656
  */
@@ -523,38 +662,57 @@ export default class DigitalSignature {
523
662
  }
524
663
 
525
664
  /**
526
- * Подписать хеш из файла
665
+ * Подписать хеш из файла подписью CAdES Detached
527
666
  * @param {string | NamedData | Array<string | NamedData>} hashUrl - Ссылка на скачивание хеша. Можно передавать несколько ссылок в массиве для наложения нескольких подписей за раз
528
667
  * @param {boolean?} asByteArray - Возвращать подпись в виде массива байт. По умолчанию подпись возвращается в виде строки в base64
529
668
  */
530
669
  async signFileHash(hashUrl, asByteArray) {
531
- if (typeof asByteArray !== "boolean") {
532
- asByteArray = false;
533
- }
534
- const isNamedData = Array.isArray(hashUrl) && hashUrl.every(url => typeof url === "object") || typeof hashUrl === "object";
535
- let hash;
536
- if (Array.isArray(hashUrl)) {
537
- hash = await Promise.all(hashUrl.map(function(url) {
538
- const downloadedData = downloadData(isNamedData ? url.val : url, "binary");
539
- return isNamedData ? {name: url.name, val: downloadedData} : downloadedData;
540
- }));
541
- } else {
542
- const downloadedData = await downloadData(hashUrl, "binary");
543
- hash = isNamedData ? {name: hashUrl.name, val: downloadedData} : downloadedData;
544
- }
545
- return await this.signHash(hash, asByteArray);
670
+ return await downloadAndSignFiles(hashUrl, async (hash) => await this.signHash(hash, asByteArray));
671
+ }
672
+
673
+ /**
674
+ * Получить данные о типе подписи
675
+ * @param {string | Uint8Array} sign - Подпись
676
+ */
677
+ async getSignContainerInfo(sign) {
678
+ return await this._euSign.GetSignContainerInfo(sign);
546
679
  }
547
680
 
548
681
  /**
549
- * Проверить внешнюю подпись
682
+ * Проверить подпись (Соответствие подписанных данных не проверяется)
550
683
  * @param {Uint8Array | string} data - Подписанные данные
551
684
  * @param {Uint8Array | string} sign - Подпись
552
685
  * @param {number?} signIndex - Номер подписи. -1 что бы проверить все подписи
553
686
  */
554
687
  async verifyData(data, sign, signIndex) {
555
688
  if (!Number.isInteger(signIndex)) {
556
- signIndex = 0;
689
+ signIndex = -1;
690
+ }
691
+ const signContainerInfo = await this._euSign.GetSignContainerInfo(sign.val || sign);
692
+
693
+ if (signContainerInfo.type === EndUserConstants.EndUserSignContainerType.ASiC) {
694
+ return await this._euSign.ASiCVerifyData(sign, signIndex);
695
+ } else if (signContainerInfo.type === EndUserConstants.EndUserSignContainerType.PAdES) {
696
+ return await this._euSign.PDFVerifyData(sign, signIndex);
697
+ } else if (signContainerInfo.type === EndUserConstants.EndUserSignContainerType.XAdES) {
698
+ return await this._euSign.XAdESVerifyData(data, sign, signIndex);
699
+ } else if (signContainerInfo.type === EndUserConstants.EndUserSignContainerType.CAdES) {
700
+ if (signContainerInfo.subType === EndUserConstants.EndUserCAdESType.Detached) {
701
+ if (!data) {
702
+ throw {
703
+ code: EndUserError.EU_ERROR_BAD_PARAMETER,
704
+ message: this._resourses.BadParameter + " data"
705
+ };
706
+ }
707
+ const signerInfo = await this._euSign.GetSigner(sign, signIndex, false);
708
+ const hashAlgo = signAlgoToHashAlgo((Array.isArray(signerInfo) ? signerInfo[0] : signerInfo).infoEx.publicKeyType);
709
+ const hash = await this._euSign.HashData(hashAlgo, data);
710
+ return await this._euSign.VerifyHash(hash.val || hash, sign.val || sign, signIndex);
711
+ } else {
712
+ return await this._euSign.VerifyDataInternal(sign.val || sign, signIndex);
713
+ }
557
714
  }
715
+
558
716
  return await this._euSign.VerifyData(data, sign, signIndex);
559
717
  }
560
718
 
@@ -578,10 +736,7 @@ export default class DigitalSignature {
578
736
  * @param {number?} signIndex - Номер подписи. -1 что бы проверить все подписи
579
737
  */
580
738
  async verifyDataInternal(sign, signIndex) {
581
- if (!Number.isInteger(signIndex)) {
582
- signIndex = 0;
583
- }
584
- return await this._euSign.VerifyDataInternal(sign, signIndex);
739
+ return await this.verifyData(null, sign, signIndex);
585
740
  }
586
741
 
587
742
  /**
@@ -595,7 +750,7 @@ export default class DigitalSignature {
595
750
  }
596
751
 
597
752
  /**
598
- * Проверить подпись хеша
753
+ * Проверить подпись хеша (Только CAdES Detached)
599
754
  * @param {Uint8Array | string} hash - Хеш подписанного файла
600
755
  * @param {Uint8Array | string} sign - Подпись
601
756
  * @param {number?} signIndex - Номер подписи. -1 что бы проверить все подписи
@@ -608,7 +763,7 @@ export default class DigitalSignature {
608
763
  }
609
764
 
610
765
  /**
611
- * Проверить подпись хеша из файла
766
+ * Проверить подпись хеша из файла (Только CAdES Detached)
612
767
  * @param {string} hashUrl - Ссылка на загрузку файла
613
768
  * @param {string} signUrl - Ссылка на загрузку подписи
614
769
  * @param {number?} signIndex - Номер подписи. -1 что бы проверить все подписи
@@ -623,34 +778,48 @@ export default class DigitalSignature {
623
778
 
624
779
  /**
625
780
  * Выполнить подписание данных с проверкой подписи
626
- * @param {Uint8Array | string | NamedData} data - данные для подписи
627
- * @param {boolean?} internal - Накладывать внутреннюю или внешнюю подпись. По умолчанию накладывается внешняя.
628
- */
629
- async signDataEx(data, internal) {
630
- if (typeof internal !== "boolean") {
631
- internal = false;
632
- }
633
- const isNamedData = typeof data === "object" && !(data instanceof Uint8Array);
634
- if (!internal) {
635
- const hashedData = await this._euSign.HashData(this._readedKey.getHashAlgo(), isNamedData ? data.val : data, false);
636
- if(isNamedData) {
637
- data.val = hashedData;
638
- } else {
639
- data = hashedData;
781
+ * @param {Uint8Array | string | NamedData | Array<Uint8Array | string | NamedData>} data - Данные для подписи. Можно передавать данные в массиве для наложения нескольких подписей за раз
782
+ * @param {EndUserSignContainerInfo?} signType - Тип подписи
783
+ */
784
+ async signDataEx(data, signType) {
785
+ const signs = await this.signData(data, signType);
786
+
787
+ if (Array.isArray(data)) {
788
+ const result = [];
789
+ for (let i = 0; i < signs.length; i++) {
790
+ const sign = signs[i];
791
+ let signInfo = await this.verifyData(data[i], sign);
792
+ if (Array.isArray(signInfo)) {
793
+ signInfo = signInfo[signInfo.length - 1];
794
+ }
795
+ result[i] = {
796
+ Success: true,
797
+ Sign: sign.val || sign,
798
+ SignatureInfo: {
799
+ Success: true,
800
+ DateTimeStr: signInfo.timeInfo.time,
801
+ Signer: signInfo.ownerInfo.subjCN,
802
+ OwnerInfo: signInfo.ownerInfo
803
+ }
804
+ };
640
805
  }
641
- }
642
- const signature = internal ? await this.signData(data, internal) : await this.signHash(data);
643
- const signatureInfo = internal ? await this.verifyDataInternal(isNamedData ? signature.val : signature, 0) : await this.verifyHash(isNamedData ? data.val : data, isNamedData ? signature.val : signature);
644
- return {
645
- Success: true,
646
- Sign: isNamedData ? signature.val : signature,
647
- SignatureInfo: {
648
- Success: true,
649
- DateTimeStr: signatureInfo.timeInfo.time,
650
- Signer: signatureInfo.ownerInfo.subjCN,
651
- OwnerInfo: signatureInfo.ownerInfo
806
+ return result;
807
+ } else {
808
+ let signInfo = await this.verifyData(data, signs);
809
+ if (Array.isArray(signInfo)) {
810
+ signInfo = signInfo[signInfo.length - 1];
652
811
  }
653
- };
812
+ return {
813
+ Success: true,
814
+ Sign: signs.val || signs,
815
+ SignatureInfo: {
816
+ Success: true,
817
+ DateTimeStr: signInfo.timeInfo.time,
818
+ Signer: signInfo.ownerInfo.subjCN,
819
+ OwnerInfo: signInfo.ownerInfo
820
+ }
821
+ };
822
+ }
654
823
  }
655
824
 
656
825
  /**
@@ -661,24 +830,14 @@ export default class DigitalSignature {
661
830
  async signFileEx(fileUrl, hash) {
662
831
  const isNamedData = typeof fileUrl === "object";
663
832
  let data = await downloadData(isNamedData ? fileUrl.val : fileUrl, "binary");
664
- if(!hash) {
665
- data = await this._euSign.HashData(this._readedKey.getHashAlgo(), data, false);
666
- if(isNamedData) {
667
- data = {name: fileUrl.name, val: data};
668
- }
833
+ if(isNamedData) {
834
+ data = {name: fileUrl.name, val: data};
835
+ }
836
+ if(hash) {
837
+ return await this.signHashEx(data);
838
+ } else {
839
+ return await this.signDataEx(data, false);
669
840
  }
670
- const signature = await this.signHash(data);
671
- const signatureInfo = await this.verifyHash(isNamedData ? data.val : data, isNamedData ? signature.val : signature);
672
- return {
673
- Success: true,
674
- Sign: isNamedData ? signature.val : signature,
675
- SignatureInfo: {
676
- Success: true,
677
- DateTimeStr: signatureInfo.timeInfo.time,
678
- Signer: signatureInfo.ownerInfo.subjCN,
679
- OwnerInfo: signatureInfo.ownerInfo
680
- }
681
- };
682
841
  }
683
842
 
684
843
  /**
@@ -759,7 +918,7 @@ export default class DigitalSignature {
759
918
  * @param {boolean} toLocalStorage - Будет ли ключ сохранён после закрытия вкладки
760
919
  */
761
920
  async storePrivateKeyInfo(privateKeyInfo, toLocalStorage) {
762
- if(privateKeyInfo.ksp && (privateKeyInfo.ksp == EndUserConstants.EndUserKSP.DIIA || privateKeyInfo.ksp == this.KSPs[1].name)) {
921
+ if(this._KSPs.needQrcode(privateKeyInfo.ksp)) {
763
922
  return;
764
923
  }
765
924
 
@@ -770,7 +929,7 @@ export default class DigitalSignature {
770
929
  const keys = await this.getPrivateKeyInfoFromStorage(toLocalStorage);
771
930
  keys.push(privateKeyInfo);
772
931
  const data = await this._euSignFile.ProtectDataByPassword(JSON.stringify(keys), "", true);
773
- storage[this._userId + this.PRIVATE_KEY_INFO] = data;
932
+ storage[this._userId + PRIVATE_KEY_INFO] = data;
774
933
  }
775
934
  }
776
935
 
@@ -787,7 +946,7 @@ export default class DigitalSignature {
787
946
 
788
947
  async getPrivateKeyInfoFromStorage(fromLocalStorage, keyType) {
789
948
  const storage = fromLocalStorage ? localStorage : sessionStorage;
790
- const storedKeys = storage[this._userId + this.PRIVATE_KEY_INFO];
949
+ const storedKeys = storage[this._userId + PRIVATE_KEY_INFO];
791
950
 
792
951
  let ls;
793
952
  const result = [];
@@ -834,8 +993,8 @@ export default class DigitalSignature {
834
993
  * Удалить сохранённые ключи
835
994
  * @param {string} keyId - Идентификатор ключа
836
995
  */
837
- async removeStoredPrivateKeyInfo(keyId) {
838
- if (keyId === undefined) {
996
+ async removeStoredPrivateKeyInfo(keyId) {
997
+ if (keyId === undefined) {
839
998
  localStorage.removeItem(this._userId + this.PRIVATE_KEY_INFO);
840
999
  sessionStorage.removeItem(this._userId + this.PRIVATE_KEY_INFO);
841
1000
  }
@@ -858,11 +1017,11 @@ export default class DigitalSignature {
858
1017
  * Получить предпочитаемый тип ключа
859
1018
  */
860
1019
  get _preferredKeyType () {
861
- const keyType = parseInt(localStorage[this._userId + this.PRIVATE_KEY_TYPE]);
1020
+ const keyType = parseInt(localStorage[this._userId + PRIVATE_KEY_TYPE]);
862
1021
  if (typeof keyType === "number" && keyType > -1) {
863
1022
  return keyType;
864
1023
  } else {
865
- localStorage[this._userId + this.PRIVATE_KEY_TYPE] = DigitalSignatureKeyType.File;
1024
+ localStorage[this._userId + PRIVATE_KEY_TYPE] = DigitalSignatureKeyType.File;
866
1025
  return DigitalSignatureKeyType.File;
867
1026
  }
868
1027
  }
@@ -873,7 +1032,7 @@ export default class DigitalSignature {
873
1032
  */
874
1033
  set _preferredKeyType (keyType) {
875
1034
  if (typeof keyType === "number" && keyType > -1) {
876
- localStorage[this._userId + this.PRIVATE_KEY_TYPE] = keyType;
1035
+ localStorage[this._userId + PRIVATE_KEY_TYPE] = keyType;
877
1036
  }
878
1037
  }
879
1038
 
@@ -884,4 +1043,21 @@ export default class DigitalSignature {
884
1043
  get _userId () {
885
1044
  return typeof this._settings.userId === "function" ? this._settings.userId() : this._settings.userId;
886
1045
  }
1046
+
1047
+ /**
1048
+ * Проверка доступности Дiя
1049
+ */
1050
+ async _diiaCheckAccess() {
1051
+ const diia = "DIIA";
1052
+ if (sessionStorage[diia] != "+") {
1053
+ try {
1054
+ sessionStorage[diia] = await downloadData(new URL(this._KSPs.diia.address).origin + "/diia");
1055
+ } catch {
1056
+ throw {
1057
+ code: EndUserError.EU_ERROR_TRANSMIT_REQUEST,
1058
+ message: this._resourses.DiiaError + `<a target="_blank" href="${window.origin}">${window.origin}</a></li><ul>`
1059
+ };
1060
+ }
1061
+ }
1062
+ }
887
1063
  }