@it-enterprise/digital-signature 1.1.5 → 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,21 +125,24 @@ export default class DigitalSignature {
78
125
  * @param {number} type
79
126
  */
80
127
  async setLibraryType(type) {
81
-
82
- if (this._euSign) {
83
- await this._euSign.ResetPrivateKey();
84
- }
85
-
86
128
  switch (type) {
87
129
  case DigitalSignatureKeyType.Token:
130
+ if (this._euSign === this._euSignKeyMedia) {
131
+ return;
132
+ }
88
133
  this._euSign = this._euSignKeyMedia;
89
134
  break;
90
135
  default:
136
+ if (this._euSign === this._euSignFile) {
137
+ return;
138
+ }
91
139
  this._euSign = this._euSignFile;
92
140
  break;
93
141
  }
94
142
 
95
- this._preferredKeyType = type;
143
+ if (type != null && type != undefined) {
144
+ this._preferredKeyType = type;
145
+ }
96
146
 
97
147
  await this.initialise();
98
148
  this.keyType = type;
@@ -103,7 +153,6 @@ export default class DigitalSignature {
103
153
  * @returns {Promise<number>} Текущий тип библиотеки
104
154
  */
105
155
  async initialise() {
106
-
107
156
  if (!this._glSign) {
108
157
  this._glSign = await Promise.resolve(this._settingsProvider.getGlSign());
109
158
  }
@@ -185,38 +234,55 @@ export default class DigitalSignature {
185
234
  return this.getLibraryType();
186
235
  }
187
236
 
188
- const certificates = await this._settings.certificatesProvider.loadCertificates();
189
-
190
- const euSettings = {
191
- language: this._settings.language,
192
- encoding: "UTF-16LE",
193
- httpProxyServiceURL: this._settings.httpProxyServiceURL,
194
- directAccess: true,
195
- CAs: certificates.CAs,
196
- CACertificates: certificates.CACertificates,
197
- mssServiceURL: this._settings.mssServiceURL,
198
- KSPs: this._KSPs,
199
- allowedKeyMediaTypes: [
200
- "е.ключ BIFIT iToken",
201
- "криптомод. ІІТ Гряда-61",
202
- "криптомод. ІІТ Гряда-301",
203
- "е.ключ ІІТ Алмаз-1К",
204
- "е.ключ ІІТ Кристал-1",
205
- "ID-карта громадянина (БЕН)",
206
- "е.ключ ІІТ Алмаз-1К (PKCS#11)",
207
- "е.ключ ІІТ Кристал-1 (PKCS#11)",
208
- "е.ключ чи смарт-карта Avest (PKCS#11)",
209
- "е.ключ Ефіт Key (PKCS#11)",
210
- "е.ключ чи смарт-карта Автор (PKCS#11)",
211
- "е.ключ чи смарт-карта Автор 338 (PKCS#11)",
212
- "смарт-карта Техноконс. TEllipse3 (PKCS#11)",
213
- "смарт-карта Техноконс. TEllipse",
214
- "смарт-карта Техноконс. TEllipse2/3",
215
- "е.ключ SafeNet iKey (PKCS#11, RSA)"
216
- ]
217
- };
237
+ if (!this._euSettings) {
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
+ }
218
251
 
219
- await euSign.Initialize(euSettings);
252
+ this._euSettings = {
253
+ language: this._settings.language,
254
+ encoding: "UTF-16LE",
255
+ httpProxyServiceURL: this._settings.httpProxyServiceURL,
256
+ directAccess: true,
257
+ CAs: certificates.CAs,
258
+ CACertificates: certificates.CACertificates,
259
+ KSPs: this.KSPs,
260
+ allowedKeyMediaTypes: [
261
+ "е.ключ BIFIT iToken",
262
+ "криптомод. ІІТ Гряда-61",
263
+ "е.ключ ІІТ Алмаз-1К",
264
+ "е.ключ ІІТ Алмаз-1К (Bluetooth)",
265
+ "е.ключ ІІТ Кристал-1",
266
+ "криптомод. ІІТ Гряда-301",
267
+ "ID-карта громадянина (БЕН)",
268
+ "е.ключ ІІТ Алмаз-1К (PKCS#11)",
269
+ "е.ключ ІІТ Кристал-1 (PKCS#11)",
270
+ "е.ключ чи смарт-карта Avest (PKCS#11)",
271
+ "е.ключ Ефіт Key (PKCS#11)",
272
+ "е.ключ чи смарт-карта Автор (PKCS#11)",
273
+ "е.ключ чи смарт-карта Автор 338 (PKCS#11)",
274
+ "смарт-карта Техноконс. TEllipse3 (PKCS#11)",
275
+ "смарт-карта Техноконс. TEllipse",
276
+ "смарт-карта Техноконс. TEllipse2/3",
277
+ "е.ключ SafeNet iKey (PKCS#11, RSA)"
278
+ ]
279
+ };
280
+ }
281
+
282
+ await euSign.Initialize(this._euSettings);
283
+ if (euSign === this._euSignKeyMedia && !await this._euSignFile.IsInitialized()) {
284
+ this._euSignFile.Initialize(this._euSettings);
285
+ }
220
286
  if (this._glSign.ApplyProxySettings) {
221
287
  const { UseProxy, ProxyAddress, ProxyPort, ProxyUser, ProxyPassword } = this._glSign;
222
288
  const proxy = new EndUserProxySettings();
@@ -228,9 +294,15 @@ export default class DigitalSignature {
228
294
  proxy.password = ProxyPassword;
229
295
  proxy.savePassword = true;
230
296
  await euSign.SetProxySettings(proxy);
297
+ if (euSign === this._euSignKeyMedia && !await this._euSignFile.IsInitialized()) {
298
+ this._euSignFile.SetProxySettings(proxy);
299
+ }
231
300
  }
232
301
 
233
302
  await euSign.SetRuntimeParameter(EndUserConstants.EU_SIGN_TYPE_PARAMETER, EndUserConstants.EndUserSignType.CAdES_X_Long);
303
+ if (euSign === this._euSignKeyMedia && !await this._euSignFile.IsInitialized()) {
304
+ this._euSignFile.SetRuntimeParameter(EndUserConstants.EU_SIGN_TYPE_PARAMETER, EndUserConstants.EndUserSignType.CAdES_X_Long);
305
+ }
234
306
 
235
307
  return this.getLibraryType();
236
308
  }
@@ -245,13 +317,13 @@ export default class DigitalSignature {
245
317
 
246
318
  /**
247
319
  * Получить список подключённых устройств
248
- * @returns {Promise<Array<EndUserKeyMedia>>} Информация о владельце ключа
320
+ * @returns {Promise<Array<EndUserKeyMedia>>} Список подключённых устройств
249
321
  */
250
322
  async getKeyMedias() {
251
- if (this._euSign != this._euSignKeyMedia) {
323
+ if (!this._euSignKeyMedia) {
252
324
  await this.setLibraryType(DigitalSignatureKeyType.Token);
253
325
  }
254
- return this._euSign.GetKeyMedias();
326
+ return this._euSignKeyMedia.GetKeyMedias();
255
327
  }
256
328
 
257
329
  /**
@@ -260,20 +332,57 @@ export default class DigitalSignature {
260
332
  * @param {Array<Uint8Array>?} certs - Сертификаты ключа (при необходимости)
261
333
  */
262
334
  async readHardwareKey(keyMedia, certs) {
263
- if (this._euSign != this._euSignKeyMedia) {
264
- 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
+ };
265
342
  }
343
+ if (!keyMedia.password) {
344
+ throw {
345
+ code: EndUserError.EU_ERROR_BAD_PARAMETER,
346
+ message: this._resourses.PasswordNotSet
347
+ };
348
+ }
349
+
266
350
  if (Array.isArray(certs)) {
267
351
  certs = await Promise.all(certs.map(cert => cert instanceof File || cert instanceof Blob ? readFile(cert) : cert));
268
352
  }
269
- const ownerInfo = await this._euSign.ReadPrivateKey(keyMedia, certs, this._selectedIssuerCN);
270
- this._readedKey = new HardwarePrivateKeyInfo(
271
- DigitalSignatureKeyType.Token,
272
- ownerInfo,
273
- await this._euSign.GetOwnCertificates(),
274
- keyMedia
275
- );
276
- 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
+ }
277
386
  }
278
387
 
279
388
  /**
@@ -283,26 +392,60 @@ export default class DigitalSignature {
283
392
  * @param {Array<Uint8Array|File>?} certs - Сертификаты ключа (при необходимости)
284
393
  */
285
394
  async readFileKey(privateKey, password, certs) {
286
- let keyName = "Key";
287
- if (this._euSign != this._euSignFile) {
288
- 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
+ };
289
408
  }
409
+
290
410
  if (privateKey instanceof File || privateKey instanceof Blob) {
291
- keyName = privateKey.name;
292
411
  privateKey = await readFile(privateKey);
293
412
  }
294
413
  if (Array.isArray(certs)) {
295
414
  certs = await Promise.all(certs.map(cert => cert instanceof File || cert instanceof Blob ? readFile(cert) : cert));
296
415
  }
297
- const ownerInfo = await this._euSign.ReadPrivateKeyBinary(privateKey, password, certs, this._selectedIssuerCN);
298
- this._readedKey = new FilePrivateKeyInfo(
299
- DigitalSignatureKeyType.File,
300
- ownerInfo,
301
- await this._euSign.GetOwnCertificates(),
302
- privateKey,
303
- this.glSign.AllowSavePassword ? password : undefined
304
- );
305
- 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
+ }
306
449
  }
307
450
 
308
451
  /**
@@ -311,9 +454,8 @@ export default class DigitalSignature {
311
454
  * @returns {Promise<EndUserJKSPrivateKeyInfo[]>}
312
455
  */
313
456
  async getJKSPrivateKeys(jks) {
314
- if (this._euSign != this._euSignFile) {
315
- await this.setLibraryType(DigitalSignatureKeyType.File);
316
- }
457
+ await this.setLibraryType(DigitalSignatureKeyType.File);
458
+
317
459
  if (jks instanceof File || jks instanceof Blob) {
318
460
  jks = await readFile(jks);
319
461
  }
@@ -328,22 +470,40 @@ export default class DigitalSignature {
328
470
  return file.name.endsWith(".jks");
329
471
  }
330
472
 
473
+ /**
474
+ * Считать ключ с DepositSign
475
+ * @param {string} userId - Идентификатор пользователя
476
+ * @param {boolean?} getCerts - Получать информацию о ключе пользователя. Это приведёт к дополнительному запросу на подписание
477
+ */
478
+ async readPrivateKeyDepositsign(userId, getCerts = false) {
479
+ return await this.readPrivateKeyKSP(userId, this._KSPs.depositsign, getCerts);
480
+ }
481
+
482
+ /**
483
+ * Считать ключ с Дiя
484
+ * @param {boolean?} getCerts - Получать информацию о ключе пользователя. Это приведёт к дополнительному запросу на подписание
485
+ */
486
+ async readPrivateKeyDiia(getCerts = false) {
487
+ return await this.readPrivateKeyKSP(null, this.KSPs.diia, getCerts);
488
+ }
489
+
331
490
  /**
332
491
  * Считать ключ с облачного провайдера
333
- * @param {string} userId - Идентификатор пользователя
334
- * @param {string|KSPSettings} ksp - Идентификатор облачного провайдера
492
+ * @param {KSPSettings} ksp - Идентификатор облачного провайдера
493
+ * @param {string?} userId - Идентификатор пользователя
335
494
  * @param {boolean?} getCerts - Получать информацию о ключе пользователя. Это приведёт к дополнительному запросу на подписание
336
495
  */
337
- async readPrivateKeyKSP(userId, ksp, getCerts = false) {
338
- if (this._euSign != this._euSignFile) {
339
- await this.setLibraryType(DigitalSignatureKeyType.KSP);
340
- }
341
- if (ksp != EndUserConstants.EndUserKSP.DIIA && typeof ksp !== "string") {
342
- ksp = ksp.name;
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();
343
501
  }
344
- const ownerInfo = await this._euSign.ReadPrivateKeyKSP(userId, ksp, getCerts);
502
+
503
+ const ownerInfo = await this._euSign.ReadPrivateKeyKSP(userId, ksp.name, getCerts);
345
504
  if (getCerts && !ownerInfo) {
346
505
  throw {
506
+ code: EndUserError.EU_ERROR_KEY_MEDIAS_READ_FAILED,
347
507
  message: this._resourses.PrivateKeyNotReaded
348
508
  };
349
509
  }
@@ -367,11 +527,7 @@ export default class DigitalSignature {
367
527
  * @param {authenticationCallback} event - Коллбэк. Вызывается при запросе на подписание.
368
528
  */
369
529
  async addConfirmKSPOperationEventListener(event) {
370
- if (this._euSign != this._euSignFile) {
371
- await this.setLibraryType(DigitalSignatureKeyType.KSP);
372
- }
373
-
374
- await this._euSign.AddEventListener(EndUserConstants.EndUserEventType.ConfirmKSPOperation, function(data) {
530
+ await this._euSignFile.AddEventListener(EndUserConstants.EndUserEventType.ConfirmKSPOperation, function(data) {
375
531
  data.qrCode = "data:image/bmp;base64," + data.qrCode;
376
532
  event(data);
377
533
  });
@@ -382,7 +538,7 @@ export default class DigitalSignature {
382
538
  * @returns {KSPSettings[]} Список поддержирживаемых облачных провайдеров
383
539
  */
384
540
  get KSPs() {
385
- return this._KSPs;
541
+ return this._KSPs.asArray();
386
542
  }
387
543
 
388
544
  /**
@@ -390,16 +546,18 @@ export default class DigitalSignature {
390
546
  * @returns {Promise<boolean>} считан ли ключ
391
547
  */
392
548
  async isPrivateKeyReaded() {
393
- return !!this._readedKey && await this._euSign.IsPrivateKeyReaded();
549
+ try {
550
+ return !!this._readedKey && await this._euSign.IsPrivateKeyReaded();
551
+ } catch {
552
+ return false;
553
+ }
394
554
  }
395
555
 
396
556
  /**
397
557
  * Очистить считанный ключ
398
558
  */
399
559
  async resetPrivateKey() {
400
- await Promise.all([
401
- this._euSign.ResetPrivateKey()
402
- ]);
560
+ await this._euSign.ResetPrivateKey();
403
561
  this._readedKey = null;
404
562
  }
405
563
 
@@ -408,7 +566,7 @@ export default class DigitalSignature {
408
566
  * @returns {Promise<Array<CASettings>>}
409
567
  */
410
568
  async getCAs() {
411
- return await this._euSign.GetCAs();
569
+ return await this._euSignFile.GetCAs();
412
570
  }
413
571
 
414
572
  /**
@@ -432,49 +590,67 @@ export default class DigitalSignature {
432
590
 
433
591
  /**
434
592
  * Подписать данные
435
- * @param {Uint8Array | string | NamedeData | Array<Uint8Array | string | NamedeData>} data - Данные для подписи. Можно передавать данные в массиве для наложения нескольких подписей за раз
436
- * @param {boolean?} internal - Внутренняя или внешняя подпись
593
+ * @param {Uint8Array | string | NamedData | Array<Uint8Array | string | NamedData>} data - Данные для подписи. Можно передавать данные в массиве для наложения нескольких подписей за раз
594
+ * @param {EndUserSignContainerInfo?} signType - Тип подписи
437
595
  * @param {boolean?} asByteArray - Возвращать подпись в виде массива байтов. По умолчанию подпись возвращается в виде строки в base64
438
596
  */
439
- async signData(data, internal, asByteArray) {
440
- if (typeof internal !== "boolean") {
441
- 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;
442
608
  }
443
609
  if (typeof asByteArray !== "boolean") {
444
610
  asByteArray = false;
445
611
  }
446
- 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
+ }
447
640
  }
448
641
 
449
642
  /**
450
643
  * Подписать файл
451
- * @param {string | NamedeData | Array<string | NamedeData>} fileUrl - Ссылка на загрузку файла. Можно передавать несколько ссылок в массиве для наложения нескольких подписей за раз
452
- * @param {boolean?} internal - Внутренняя или внешняя подпись
644
+ * @param {string | NamedData | Array<string | NamedData>} fileUrl - Ссылка на загрузку файла. Можно передавать несколько ссылок в массиве для наложения нескольких подписей за раз
645
+ * @param {EndUserSignContainerInfo?} signType - Тип подписи
453
646
  * @param {boolean?} asByteArray - Возвращать подпись в виде массива байт. По умолчанию подпись возвращается в виде строки в base64
454
647
  */
455
- async signFile(fileUrl, internal, asByteArray) {
456
- if (typeof internal !== "boolean") {
457
- internal = false;
458
- }
459
- if (typeof asByteArray !== "boolean") {
460
- asByteArray = false;
461
- }
462
- const isNamedData = Array.isArray(fileUrl) && fileUrl.every(url => typeof url === "object") || typeof fileUrl === "object";
463
- let data;
464
- if (Array.isArray(fileUrl)) {
465
- data = await Promise.all(fileUrl.map(function(url) {
466
- const downloadedData = downloadData(isNamedData ? url.val : url, "binary");
467
- return isNamedData ? {name: url.name, val: downloadedData} : downloadedData;
468
- }));
469
- } else {
470
- const downloadedData = await downloadData(isNamedData ? fileUrl.val : fileUrl, "binary");
471
- data = isNamedData ? {name: fileUrl.name, val: downloadedData} : downloadedData;
472
- }
473
- 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));
474
650
  }
475
651
 
476
652
  /**
477
- * Подписать хеш
653
+ * Подписать хеш подписью CAdES Detached
478
654
  * @param {Uint8Array | string | NamedData | Array<Uint8Array | string> | NamedData} hash - Хеш файла. Можно передавать несколько хешей в массиве для наложения нескольких подписей за раз
479
655
  * @param {boolean?} asByteArray - Возвращать подпись в виде массива байт. По умолчанию подпись возвращается в виде строки в base64
480
656
  */
@@ -486,38 +662,57 @@ export default class DigitalSignature {
486
662
  }
487
663
 
488
664
  /**
489
- * Подписать хеш из файла
665
+ * Подписать хеш из файла подписью CAdES Detached
490
666
  * @param {string | NamedData | Array<string | NamedData>} hashUrl - Ссылка на скачивание хеша. Можно передавать несколько ссылок в массиве для наложения нескольких подписей за раз
491
667
  * @param {boolean?} asByteArray - Возвращать подпись в виде массива байт. По умолчанию подпись возвращается в виде строки в base64
492
668
  */
493
669
  async signFileHash(hashUrl, asByteArray) {
494
- if (typeof asByteArray !== "boolean") {
495
- asByteArray = false;
496
- }
497
- const isNamedData = Array.isArray(hashUrl) && hashUrl.every(url => typeof url === "object") || typeof hashUrl === "object";
498
- let hash;
499
- if (Array.isArray(hashUrl)) {
500
- hash = await Promise.all(hashUrl.map(function(url) {
501
- const downloadedData = downloadData(isNamedData ? url.val : url, "binary");
502
- return isNamedData ? {name: url.name, val: downloadedData} : downloadedData;
503
- }));
504
- } else {
505
- const downloadedData = await downloadData(hashUrl, "binary");
506
- hash = isNamedData ? {name: hashUrl.name, val: downloadedData} : downloadedData;
507
- }
508
- 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);
509
679
  }
510
680
 
511
681
  /**
512
- * Проверить внешнюю подпись
682
+ * Проверить подпись (Соответствие подписанных данных не проверяется)
513
683
  * @param {Uint8Array | string} data - Подписанные данные
514
684
  * @param {Uint8Array | string} sign - Подпись
515
685
  * @param {number?} signIndex - Номер подписи. -1 что бы проверить все подписи
516
686
  */
517
687
  async verifyData(data, sign, signIndex) {
518
688
  if (!Number.isInteger(signIndex)) {
519
- 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
+ }
520
714
  }
715
+
521
716
  return await this._euSign.VerifyData(data, sign, signIndex);
522
717
  }
523
718
 
@@ -541,10 +736,7 @@ export default class DigitalSignature {
541
736
  * @param {number?} signIndex - Номер подписи. -1 что бы проверить все подписи
542
737
  */
543
738
  async verifyDataInternal(sign, signIndex) {
544
- if (!Number.isInteger(signIndex)) {
545
- signIndex = 0;
546
- }
547
- return await this._euSign.VerifyDataInternal(sign, signIndex);
739
+ return await this.verifyData(null, sign, signIndex);
548
740
  }
549
741
 
550
742
  /**
@@ -558,7 +750,7 @@ export default class DigitalSignature {
558
750
  }
559
751
 
560
752
  /**
561
- * Проверить подпись хеша
753
+ * Проверить подпись хеша (Только CAdES Detached)
562
754
  * @param {Uint8Array | string} hash - Хеш подписанного файла
563
755
  * @param {Uint8Array | string} sign - Подпись
564
756
  * @param {number?} signIndex - Номер подписи. -1 что бы проверить все подписи
@@ -571,7 +763,7 @@ export default class DigitalSignature {
571
763
  }
572
764
 
573
765
  /**
574
- * Проверить подпись хеша из файла
766
+ * Проверить подпись хеша из файла (Только CAdES Detached)
575
767
  * @param {string} hashUrl - Ссылка на загрузку файла
576
768
  * @param {string} signUrl - Ссылка на загрузку подписи
577
769
  * @param {number?} signIndex - Номер подписи. -1 что бы проверить все подписи
@@ -586,34 +778,48 @@ export default class DigitalSignature {
586
778
 
587
779
  /**
588
780
  * Выполнить подписание данных с проверкой подписи
589
- * @param {Uint8Array | string | NamedData} data - данные для подписи
590
- * @param {boolean?} internal - Накладывать внутреннюю или внешнюю подпись. По умолчанию накладывается внешняя.
591
- */
592
- async signDataEx(data, internal) {
593
- if (typeof internal !== "boolean") {
594
- internal = false;
595
- }
596
- const isNamedData = typeof data === "object" && !(data instanceof Uint8Array);
597
- if (!internal) {
598
- const hashedData = await this._euSign.HashData(this._readedKey.getHashAlgo(), isNamedData ? data.val : data, false);
599
- if(isNamedData) {
600
- data.val = hashedData;
601
- } else {
602
- 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
+ };
603
805
  }
604
- }
605
- const signature = internal ? await this.signData(data, internal) : await this.signHash(data);
606
- const signatureInfo = internal ? await this.verifyDataInternal(isNamedData ? signature.val : signature, 0) : await this.verifyHash(isNamedData ? data.val : data, isNamedData ? signature.val : signature);
607
- return {
608
- Success: true,
609
- Sign: isNamedData ? signature.val : signature,
610
- SignatureInfo: {
611
- Success: true,
612
- DateTimeStr: signatureInfo.timeInfo.time,
613
- Signer: signatureInfo.ownerInfo.subjCN,
614
- 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];
615
811
  }
616
- };
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
+ }
617
823
  }
618
824
 
619
825
  /**
@@ -624,24 +830,14 @@ export default class DigitalSignature {
624
830
  async signFileEx(fileUrl, hash) {
625
831
  const isNamedData = typeof fileUrl === "object";
626
832
  let data = await downloadData(isNamedData ? fileUrl.val : fileUrl, "binary");
627
- if(!hash) {
628
- data = await this._euSign.HashData(this._readedKey.getHashAlgo(), data, false);
629
- if(isNamedData) {
630
- data = {name: fileUrl.name, val: data};
631
- }
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);
632
840
  }
633
- const signature = await this.signHash(data);
634
- const signatureInfo = await this.verifyHash(isNamedData ? data.val : data, isNamedData ? signature.val : signature);
635
- return {
636
- Success: true,
637
- Sign: isNamedData ? signature.val : signature,
638
- SignatureInfo: {
639
- Success: true,
640
- DateTimeStr: signatureInfo.timeInfo.time,
641
- Signer: signatureInfo.ownerInfo.subjCN,
642
- OwnerInfo: signatureInfo.ownerInfo
643
- }
644
- };
645
841
  }
646
842
 
647
843
  /**
@@ -722,7 +918,7 @@ export default class DigitalSignature {
722
918
  * @param {boolean} toLocalStorage - Будет ли ключ сохранён после закрытия вкладки
723
919
  */
724
920
  async storePrivateKeyInfo(privateKeyInfo, toLocalStorage) {
725
- if(privateKeyInfo.ksp && privateKeyInfo.ksp == EndUserConstants.EndUserKSP.DIIA) {
921
+ if(this._KSPs.needQrcode(privateKeyInfo.ksp)) {
726
922
  return;
727
923
  }
728
924
 
@@ -733,7 +929,7 @@ export default class DigitalSignature {
733
929
  const keys = await this.getPrivateKeyInfoFromStorage(toLocalStorage);
734
930
  keys.push(privateKeyInfo);
735
931
  const data = await this._euSignFile.ProtectDataByPassword(JSON.stringify(keys), "", true);
736
- storage[this._userId + this.PRIVATE_KEY_INFO] = data;
932
+ storage[this._userId + PRIVATE_KEY_INFO] = data;
737
933
  }
738
934
  }
739
935
 
@@ -750,7 +946,7 @@ export default class DigitalSignature {
750
946
 
751
947
  async getPrivateKeyInfoFromStorage(fromLocalStorage, keyType) {
752
948
  const storage = fromLocalStorage ? localStorage : sessionStorage;
753
- const storedKeys = storage[this._userId + this.PRIVATE_KEY_INFO];
949
+ const storedKeys = storage[this._userId + PRIVATE_KEY_INFO];
754
950
 
755
951
  let ls;
756
952
  const result = [];
@@ -797,8 +993,8 @@ export default class DigitalSignature {
797
993
  * Удалить сохранённые ключи
798
994
  * @param {string} keyId - Идентификатор ключа
799
995
  */
800
- async removeStoredPrivateKeyInfo(keyId) {
801
- if (keyId === undefined) {
996
+ async removeStoredPrivateKeyInfo(keyId) {
997
+ if (keyId === undefined) {
802
998
  localStorage.removeItem(this._userId + this.PRIVATE_KEY_INFO);
803
999
  sessionStorage.removeItem(this._userId + this.PRIVATE_KEY_INFO);
804
1000
  }
@@ -821,11 +1017,11 @@ export default class DigitalSignature {
821
1017
  * Получить предпочитаемый тип ключа
822
1018
  */
823
1019
  get _preferredKeyType () {
824
- const keyType = parseInt(localStorage[this._userId + this.PRIVATE_KEY_TYPE]);
1020
+ const keyType = parseInt(localStorage[this._userId + PRIVATE_KEY_TYPE]);
825
1021
  if (typeof keyType === "number" && keyType > -1) {
826
1022
  return keyType;
827
1023
  } else {
828
- localStorage[this._userId + this.PRIVATE_KEY_TYPE] = DigitalSignatureKeyType.File;
1024
+ localStorage[this._userId + PRIVATE_KEY_TYPE] = DigitalSignatureKeyType.File;
829
1025
  return DigitalSignatureKeyType.File;
830
1026
  }
831
1027
  }
@@ -836,7 +1032,7 @@ export default class DigitalSignature {
836
1032
  */
837
1033
  set _preferredKeyType (keyType) {
838
1034
  if (typeof keyType === "number" && keyType > -1) {
839
- localStorage[this._userId + this.PRIVATE_KEY_TYPE] = keyType;
1035
+ localStorage[this._userId + PRIVATE_KEY_TYPE] = keyType;
840
1036
  }
841
1037
  }
842
1038
 
@@ -847,4 +1043,21 @@ export default class DigitalSignature {
847
1043
  get _userId () {
848
1044
  return typeof this._settings.userId === "function" ? this._settings.userId() : this._settings.userId;
849
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
+ }
850
1063
  }