@it-enterprise/digital-signature
v1.3.3
Published
digital signature
Downloads
279
Keywords
Readme
Настройка веб-сервера
Для работы пакет требует наличие специального api на веб-сервере.
Для добавления этого api необходимо установить nuget пакет ItEnterprise.DigitalSignature.Web
Install-Package ItEnterprise.DigitalSignature.Web
Подключение
using ItEnterprise.DigitalSignature.Web;
using ItEnterprise.DigitalSignature.Models;
namespace TestApp.Web.NetCore
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDigitalSignature(builder => builder
.AddCertiticateUpdatesService(
// Ссылка на веб-сервисы. Необходимо для обновления коревых сертификатов и списка ЦСК
"https://m.it.ua/ws",
// Получать значение параметра GlSign через веб-расчёт
false
).SetConfig(new DigitalSignatureConfiguration
{
// Использовать нативные библиотеки. true, если будет использоваться C# API ЕЦП. Нативные библиотеки необходимо устанавливать отдельными nuget пакетами
UseNativeLibraries = false,
GlSign = new GlSignInfo {
// Разрешать использовать тестовые ключи
AllowTestKeys = true
}
}));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Путь, по которому будет доступно API ЕЦП
app.UseDigitalSignature("/api/ds");
}
}
}
Установка
@it-enterprise/digital-signature
npm install @it-enterprise/digital-signature
Важно! Пакет содержит web worker. Для работы пакета необходимо настроить копирование файла с web worker из пакета в папку со скриптами приложения при сборке. Пример настройки через webpack:
const CopyPlugin = require("copy-webpack-plugin");
configureWebpack: {
plugins: [
new CopyPlugin([{
// Путь к файлу в пакете
from: "node_modules/@it-enterprise/digital-signature/src/euscp.worker.js",
// Путь к файлу в public приложения
to: "js/euscp.worker.js"
}])
]
}
Импорт
import {
DigitalSignature,
GlSign,
Models,
Utils,
EUSignCP
} from "@it-enterprise/digital-signature";
Инициализация
Инициализация библиотеки
import {
DigitalSignature,
Models
} from "@it-enterprise/digital-signature";
const ds = new DigitalSignature(
new Models.DefaultSettingProvider(
// Язык ошибок (строка, или функция, возвращающая строку)
"uk",
// id пользователя (для сохранения ключей и предпочитаемого типа ключа) (строка, или функция, возвращающая строку)
userId,
// Путь к API ЕЦП
location.pathname + "api/ds/",
// Путь к web worker
"js/euscp.worker.js")
);
// Возвращает текущий тип ключа (файловый, аппаратный, облачный)
const currentKeyType = await ds.initialise();
Сменить тип библиотеки
/** Подпись файловыми ключами, через облачные сервисы */
const DigitalSignatureLibraryTypeJS = 0;
/** Подпись аппартными ключами */
const DigitalSignatureLibraryTypeSW = 1;
/**
* Типы библиотеки
*/
enum DigitalSignatureLibraryType = {
/** Подпись файловыми ключами и через облачные сервисы */
JS: DigitalSignatureLibraryTypeJS,
/** Подпись аппартными ключами */
SW: DigitalSignatureLibraryTypeSW
};
import { Models } from "@it-enterprise/digital-signature";
await ds.setLibraryType(Models.DigitalSignatureLibraryType.JS);
Центры сертификации ключей
Получение списка сертификации ключей
const cas = await ds.getCAs();
Установить центр сертификации ключей
// Предоставить возможность пользователю выбирать ЦСК. Для автоматического определения ЦСК установить значение null
const ca = cas[0];
await ds.setCA(ca);
Проверить, поддерживает ли ЦСК автоматическую загрузку сертификатов
Если ЦСК не поддерживает автоматическую загрузку сертификатов, нужно предоставить возможность пользователю вручную указать сертификаты
const needCerts = ds.needPrivateKeyCertificates();
Структура объекта CASettings
import { EUSignCP.CASettings } from "@it-enterprise/digital-signature";
class CASettings {
// Названия ЦСК (обычно используется первое из списка)
issuerCNs: Array<string>;
address: string;
ocspAccessPointAddress: string;
ocspAccessPointPort: string;
cmpAddress: string;
tspAddress: string;
tspAddressPort: string;
directAccess: boolean;
certsInKey: boolean;
cmpCompatibility: number;
qscdSNInCert: boolean;
}
Файловые ключи
Обычные файловые ключи
Считывание
const ownerInfo = await ds.readFileKey(
// Файл с ключом
privateKey,
// Пароль
password,
// Сертификаты ключа (необязательно)
privateKeyCertificates
);
JKS-контейнеры
Проверка, является ли файл JKS-контейнером
const isJKSContainer = ds.isJKSContainer(/* Файл с ключом */ fileKey);
Получение списка ключей из JKS-контейнера
const JKSPrivateKeys = await ds.getJKSPrivateKeys(/* Файл с ключом */ fileKey);
Считывание одного из ключей
// Предоставить пользователю возможность выбрать ключ из списка, полученного из метода getJKSPrivateKeys
const JKSPrivateKey = JKSPrivateKeys[0];
const keyInfo = await ds.readFileKey(
JKSPrivateKey.privateKey,
password,
JKSPrivateKey.certificates.select(cert => cert.data)
);
Аппаратные ключи
Получение списка ключей
const keyMedias = await ds.getKeyMedias();
Считывание ключа
// Предоставить пользователю возможность выбрать ключ из списка, полученного из метода getKeyMedias
const hardwareKey = keyMedias[0];
hardwareKey.password = password;
const keyInfo = await ds.readHardwareKey(
// Информация о ключе
hardwareKey,
// Сертификаты ключа (необязательно)
privateKeyCertificates
);
Облачные ключи
Провайдеры облачныч ключей есть 4х видов:
- работающие через QR код (Дія.Підпис, SmartID, CloudKey, ПУМБ)
- работающие через ID пользователя (DepositSign, ESign, Вчасно, ДПС)
- Гряда + сервис подписи
- vToken (Укргазбанк, Банк Альянс)
Получение списока провайдеров облачных ключей
const ksps = ds.KSPs;
Содержимое обьекта KSP
import { EUSignCP.KSPSettings } from "@it-enterprise/digital-signature";
// Провайдер облачных ключей
class KSPSettings {
// Идентификатор
id: string;
// Название провайдера
name: string;
// Провайдер работает через QR код или через ID пользователя
needQRCode: boolean;
// Тип ID пользователя (имя пользователя/телефон/email)
clientIdType?: EndUserKSPClientIdType;
// Тип провайдера
ksp: EndUserKSP;
address?: string;
port?: string;
directAccess?: boolean;
clientIdPrefix?: string;
confirmationURL?: string;
mobileAppName?: string;
pollingInterval?: number;
systemId?: string;
}
import { Models.EndUserKSP } from "@it-enterprise/digital-signature";
// Тип провайдера облачных ключей
enum EndUserKSP = {
// API ИИТ. Провайдеры с этим API поддерживают подписание только 1 файла за раз, сейчас все провайдеры перешли на API PB
IIT,
// API ИИТ, поддерживает подписание нескольких файлов за раз
PB,
// Дія.Підпис
DIIA,
// Подписание ключами с Гряды через сервис подписи
GRYADA,
// API vToken. Используется в Укргазбанк, Банк Альянс
VTOKEN
}
import { Models.EndUserKSPClientIdType } from "@it-enterprise/digital-signature";
// Тип ID пользователя
enum EndUserKSPClientIdType = {
// По умолчанию
Default,
// Имя пользователя
Name,
// Номер телефона
Phone,
// Email
Email,
// Имя пользователя и пароль (2 поля)
NamePassword
}
Провайдеры с API ИИТ
Провайдеры с API ИИТ имеют тип IIT или PB
Провайдеры с типом IIT могут создавать только 1 подпись за раз, провайдеры с типом PB - несколько
Оба требуют подтверждение операций создания подписей через соответствующие приложения
Подтвердение выполнения операции осуществляется либо через сканирование QR кода, либо через PUSH уведомления
Провайдеров, использующих QR код, можно определить по полю needQRCode
Для провайдеров, работающих через QR код, после инициализации библиотеки нужно подписаться на событие подтверждения операции
В это событие будут приходить данные для отображения QR кода
ds.addConfirmKSPOperationEventListener(eventArgs => { ... });
Событие будет вызываться при:
- Считывании ключа с getCerts = true
- Подписании данных
Важно! При необходимости подписать несколько файлов, нужно передавать их в функцию подписания все за раз в массиве. Иначе пользователю придётся подтверждать подписание каждого файла отдельно
Структура объекта, приходящего в коллбек события
import { EUSignCP.EndUserEvents.EndUserConfirmKSPOperationEvent } from "@it-enterprise/digital-signature";
// Аргументы события
class EndUserConfirmKSPOperationEvent {
// Ссылка на подтверждение операции
url: string;
// QR код в формате data:image/bmp для подстановки в <img scr='...' />
qrCode: string;
// Название мобильного приложения, в котором нужно подтвердить выполнение операции
mobileAppName: string;
// Время, до которого действует ссылка
expireDate: Date;
}
QR код нужно отобразить пользователю, что бы он мог отсканировать его в приложении и подтвердить подписание
Для отображения QR кода можно использовать содержимое поля qrCode, либо сгенерировать его на основе ссылки из поля url
Для мобильных устройств должна быть возможность переходя по ссылке из поля url, для возможности сразу запустить соответствующее приложение
Для провайдеров, не использующих QR код, необходимо предоставлять пользователю поле ввода идентификатора
Идентификатор пользователя необходимо передавать в функцию считывания ключа
При выполнении операции подписания или считывании ключа с getCerts = true, пользователю в приложение придёт PUSH уведомление и он должен будет подтвердить операцию
Считывание ключа
// Предоставить пользователю возможность выбрать провайдера ключей
const ksp = ds.KSPs[0];
const keyInfo = await ds.readPrivateKeyKSP(
// Объект KSP из списка ds.KSPs
ksp
// Идентификатор пользователя - для провайдеров ключей, работающих через ID пользователя
// Для провайдеров ключей, работающих через QR код - null
userID,
// Получать информацию о сертификатах пользователя
// true - поля ownerInfo и certificates в keyInfo будут заполены, но пользователю нужно будет подтвердить дополнительную операцию подписания
// false - поля ownerInfo и certificates в keyInfo будут пустыми, но пользователь не получит дополнительный запрос на подписание
getCerts = false,
// Пароль пользователя, если clientIdType == NamePassword
keyID = null);
Для создания подписей используются те же фунции, что и для обычных ключей
Promise, возвращаемый функцией создания подписи, будет висеть в ожидании пока пользователь не подтвердит операцию подписания, или не выйдет таймаут операции
Дія.Підпис
Для Дія.Підпис использование библиотеки аналогично провайдеру с API ИИТ с QR кодом
Провайдеры с API vToken
Для провайдеров с API vToken сначала нужно авторизироваться и получить список ключей, доступных пользователю:
import { Models } from "@it-enterprise/digital-signature";
// Объект KSP из списка ds.KSPs
const ksp = ds.KSPs[0];
// Логин и пароль
const userAuthData = new Models.KSPUserAuthData(
login,
password
);
const keyMediasResponse = await this.ds.getKeyMediasKSP(ksp, userAuthData);
Структура объекта keyMediasResponse:
import { Models.KSPKeyMediasResponse } from "@it-enterprise/digital-signature";
/**
* Ответ на запрос получения списка ключей пользователя в облачного провайдера
*/
class KSPKeyMediasResponse {
// Токен авторизации
token: string;
// Включён ли у пользователя второй фактор авторизации
isTwoFactor: boolean;
// Спикок ключей, доступных пользователю
keys: Array<KSPKeyMedia>;
}
/**
* Информация про ключ пользователя облачного провайдера
*/
export class KSPKeyMedia {
// Идентификатор ключа
keyId: string;
// Отображаемое имя ключа
visibleName: string;
// Владелец ключа
subject: string;
// ЦСК, который выдал ключ
issuer: string;
// Является ли ключ цифровой печатью
isStamp: boolean;
}
Считать выбранный ключ:
import { Models } from "@it-enterprise/digital-signature";
// Предоставить пользователю возможность выбрать ключ
const key = keyMedias.keys[0];
const keyAuthData = new Models.KSPPrivateKeyAuthData(
// Пароль от выбранного ключа, предоставить ввести пользователю
keyPassword,
// Токен авторизации
keyMediasResponse.token,
// Код двухфакторной авторизации (Google Authenticator), если она включена на аккаунте
twofaCode);
const keyInfo = await ds.readPrivateKeyKSP(
// Объект KSP из списка ds.KSPs
ksp,
null,
// Получать информацию о сертификатах пользователя
// true - поля ownerInfo и certificates в keyInfo будут заполены, но пользователю нужно будет подтвердить дополнительную операцию подписания
// false - поля ownerInfo и certificates в keyInfo будут пустыми, но пользователь не получит дополнительный запрос на подписание
getCerts = false,
// Идентификатор ключа
key.keyId,
// Данные авторизации
keyAuthData);
Важно! Если на аккаунте пользователя включена двухфакторная авторизация, перед каждой операцией подписания нужно передавать код двухфакторной авторизации. Для этого нужно вызывать функцию setTwoFactorCodeKSP, в которую передавать код, который укажет пользователь.
Если подписание выполняется сразу после считывания ключа, можно использовать тот же код.
if (keyMediasResponse.isTwoFactor) {
await this.ds.setTwoFactorCodeKSP(this.twofaCode);
}
const signResult = await this.ds.signData(...);
Сохранение ключей
Сохранить ключ
await ds.storePrivateKeyInfo(
// Информация о ключе
privateKeyInfo,
// Будет ли ключ сохранён после закрытия вкладки
toLocalStorage,
Считать сохранённые ключи
const keyInfo = await ds.getStoredPrivateKeyInfo(
// Тип ключа (необязательно)
keyType
Удалить сохранённые ключи
await ds.removeStoredPrivateKeyInfo(
// Идентификатор ключа (необязательно)
keyId
Создание подписей
Формат подписи
Функции создания подписей поддерживают возможность выбирать формат контейнера подписи
Формат подписи указывается в опциональном параметре signFormat
По умолчанию используется формат подписи CAdES-X-Long Detached
Структура объекта, описывающего формат подписи
class EndUserSignContainerInfo {
// Тип контейнера подписи
type: EndUserSignContainerType;
// Уточняющий тип подписи
subType: EndUserCAdESType | EndUserXAdESType | EndUserASiCType;
// Тип подписи в ASiC контейнере (только для ASiC контейнеров)
asicSignType: EndUserASiCSignType;
// Уровень подписи
signLevel: EndUserSignType | EndUserXAdESSignLevel | EndUserPAdESSignLevel;
}
import { EUSignCP.EndUserSignContainerInfo } from "@it-enterprise/digital-signature";
Типы контейнеров подписи
const EU_SIGN_CONTAINER_TYPE_CADES = 1;
const EU_SIGN_CONTAINER_TYPE_XADES = 2;
const EU_SIGN_CONTAINER_TYPE_PADES = 3;
const EU_SIGN_CONTAINER_TYPE_ASIC = 4;
enum EndUserSignContainerType {
// CMS подпись в двоичном формате. Используется по умолчанию
CAdES,
// Подпись в формате XML. Может содержать одновременно несколько наборов данных
XAdES,
// Подпись в PDF документе (Работает только с PDF файлами)
PAdES,
// Контейнер для подписей в виде ZIP-архива
ASiC
}
import { EUSignCP.EndUserConstants.EndUserSignContainerType } from "@it-enterprise/digital-signature";
Типы подписей CAdES
const EU_CADES_TYPE_DETACHED = 1;
const EU_CADES_TYPE_ENVELOPED = 3;
enum EndUserCAdESType {
// Подпись отдельно от данных (внешняя подпись). Используется по умолчанию
Detached,
// Подпись в одном контейнере с данными (внутренняя подпись)
Enveloped
}
import { EUSignCP.EndUserConstants.EndUserCAdESType } from "@it-enterprise/digital-signature";
Уровни подписей CAdES
export declare const EU_SIGN_TYPE_CADES_BES = 1;
export declare const EU_SIGN_TYPE_CADES_T = 4;
export declare const EU_SIGN_TYPE_CADES_X_LONG = 16;
export declare enum EndUserSignType {
// Базовая подпись
CAdES_BES,
// Подпись с меткой времени
CAdES_T,
// Подпись для длительного хранения с полными данными для проверки
CAdES_X_Long
}
import { EUSignCP.EndUserConstants.EndUserSignType } from "@it-enterprise/digital-signature";
Типы подписей XAdES
const EU_XADES_TYPE_DETACHED = 1;
const EU_XADES_TYPE_ENVELOPED = 3;
enum EndUserXAdESType {
// Подпись отдельно от данных (внешняя подпись)
Detached,
// Подпись в одном контейнере с данными (внутренняя подпись) !! Данные могут быть только в формате XML !!
Enveloped
}
import { EUSignCP.EndUserConstants.EndUserXAdESType } from "@it-enterprise/digital-signature";
Уровни подписей XAdES
export declare const EU_XADES_SIGN_LEVEL_B_B = 1;
export declare const EU_XADES_SIGN_LEVEL_B_T = 4;
export declare const EU_XADES_SIGN_LEVEL_B_LT = 16;
export declare enum EndUserXAdESSignLevel {
// Базовая подпись
B_B,
// Подпись с меткой времени
B_T,
// Подпись для длительного хранения с полными данными для проверки
B_LT
}
import { EUSignCP.EndUserConstants.EndUserXAdESSignLevel } from "@it-enterprise/digital-signature";
Уровни подписей PAdES
export declare const EU_PADES_SIGN_LEVEL_B_B = 1;
export declare const EU_PADES_SIGN_LEVEL_B_T = 4;
export declare enum EndUserPAdESSignLevel {
// Базовая подпись
B_B,
// Подпись с меткой времени
B_T
}
import { EUSignCP.EndUserConstants.EndUserPAdESSignLevel } from "@it-enterprise/digital-signature";
Типы контейнеров ASiC
const EU_ASIC_TYPE_S = 1;
const EU_ASIC_TYPE_E = 2;
enum EndUserASiCType {
// Простой контейнер, содержащий 1 файл с данными и 1 подпись
S,
// Расширенный контейнер, может содержать несколько файлов с данными и несколько подписей
E
}
import { EUSignCP.EndUserConstants.EndUserASiCType } from "@it-enterprise/digital-signature";
Типы подписей, которые могут содержаться в ASiC контейнере
const EU_ASIC_SIGN_TYPE_CADES = 1;
const EU_ASIC_SIGN_TYPE_XADES = 2;
enum EndUserASiCSignType {
CAdES,
XAdES
}
import { EUSignCP.EndUserConstants.EndUserASiCSignType } from "@it-enterprise/digital-signature";
Пример использования формата подписи:
const file = {
name: "file.pdf",
val: "ссылка на загрузку файла"
};
// Формат ASiC-S с подписью XAdES
const asicsformat = {
type: EndUserSignContainerType.ASiC,
subType: EndUserASiCType.S,
asicSignType: EndUserASiCSignType.XAdES,
signLevel: EndUserXAdESSignLevel.B_LT
};
// Формат PAdES
const padesformat = {
type: EndUserSignContainerType.PAdES,
signLevel: EndUserPAdESSignLevel.B_T
};
// Внутренняя CAdES подпись
const cadesformat {
type: EndUserSignContainerType.CAdES,
subType: EndUserCAdESType.Enveloped,
signLevel: EndUserSignType.CAdES_X_Long
};
const asics = await ds.signFile(file, asicsformat);
const pades = await ds.signFile(file, padesformat);
const cades = await ds.signFile(file, cadesformat);
const signatures = await ds.signFile(files);
Формат передачи данных
Все функции создания подписей поддерживают следующие форматы передачи данных:
- Одиночный набор данных (в зависимости от функции - ссылка на загрузку файла, данные в base64 или Uint8Array и т.д.)
- Данные в массиве (данные как в п.1, только в массиве). Подписи так же будут возвращены в массиве
- Именованные данные (данные в объекте NamedData, содержащем имя набора данных и сами данные). Подпись так же будет возвращена в объекте NamedData
- Именованные данные в массиве (данные как в п.3, только в массиве). Результатом выполения функций будет являться массив обьектов NamedData с подписями
Для лучшей поддержки всех форматов подписей и типов ключей, рекомендуется использовать формат из п.4
Структура объекта NamedData
declare type NamedData = {
// Имя набора данных
name: string;
// В качестве параметра при создании подписи: в зависимости от функции - ссылка на загрузку файла, данные в base64 или Uint8Array и т.д.
// В качестве возвращаемого результата: контейнер с подписью
val: string | Uint8Array;
};
import { EUSignCP.NamedData } from "@it-enterprise/digital-signature";
Пример использования формата именованных данных
const files = [{
name: "file1.docx",
val: "ссылка на загрузку первого файла"
}, {
name: "file2.pdf",
val: "ссылка на загрузку второго файла"
}];
const signatures = await ds.signFile(files);
console.log(signatures);
// Результат
[{
name: "file1.docx",
val: "подпись первого файла"
}, {
name: "file2.pdf",
val: "подпись второго файла"
}]
Функции для создания подписей
Подписание данных
const sign = await ds.signData(
// Данные в виде Uint8Array или строки base64
data,
// Формат подписи
signFormat,
// true - вернуть результат в виде массива байт,false - в виде строки base64. по умолчанию false
false);
Подписание файла
const sign = await ds.signFile(
// Ссылка на загрузку файла (например, с веб-сервисов)
data,
// Формат подписи. [Формат подписи]
signFormat,
// true - вернуть результат в виде массива байт,false - в виде строки base64. по умолчанию false
false);
Подписание хеша в формате CAdES Detached
const sign = await ds.signHash(
// Хеш в виде Uint8Array или строки base64
hash,
// true - вернуть результат в виде массива байт,false - в виде строки base64. по умолчанию false
false);
Подписание хеша из файла в формате CAdES Detached
const sign = await ds.signFileHash(
// Ссылка на загрузку файла с хешем
data,
// true - вернуть результат в виде массива байт,false - в виде строки base64. по умолчанию false
false);
Подписание данных с получением информации о подписи
const sign = await ds.signDataEx(
// Данные в виде Uint8Array или строки base64
data,
// Формат подписи
signFormat);
Подписание файла с получением информации о подписи
const sign = await ds.signFileEx(
// Ссылка на загрузку файла (например, с веб-сервисов)
data,
// Формат подписи
signFormat);
Подписание хеша в формате CAdES Detached с получением информации о подписи
const sign = await ds.signHashEx(
// Хеш в виде Uint8Array или строки base64
data);