# Настройка веб-сервера

Для работы пакет требует наличие специального api на веб-сервере.  
Для добавления этого api необходимо установить nuget пакет [ItEnterprise.DigitalSignature.Web](https://www.nuget.org/packages/ItEnterprise.DigitalSignature.Web/)

```
Install-Package ItEnterprise.DigitalSignature.Web
```

Подключение

```c#
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](https://www.npmjs.com/package/@it-enterprise/digital-signature)

```
npm install @it-enterprise/digital-signature
```

**Важно!** Пакет содержит web worker. Для работы пакета необходимо настроить копирование файла с web worker из пакета в папку со скриптами приложения при сборке.
Пример настройки через webpack:

```javascript
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"
    }])
  ]
}
```

# Импорт

```javascript
import {
  DigitalSignature,
  GlSign,
  Models,
  Utils,
  EUSignCP
} from "@it-enterprise/digital-signature";
```

# Инициализация

Инициализация библиотеки
```javascript
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();
```
Сменить тип библиотеки
```javascript
/** Подпись файловыми ключами, через облачные сервисы  */
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);
```

# Центры сертификации ключей

Получение списка сертификации ключей
```javascript
const cas = await ds.getCAs();
```
Установить центр сертификации ключей
```javascript
// Предоставить возможность пользователю выбирать ЦСК. Для автоматического определения ЦСК установить значение null
const ca = cas[0];
await ds.setCA(ca);

```
Проверить, поддерживает ли ЦСК автоматическую загрузку сертификатов  
Если ЦСК не поддерживает автоматическую загрузку сертификатов, нужно предоставить возможность пользователю вручную указать сертификаты  
```javascript
const needCerts = ds.needPrivateKeyCertificates();
```  
Структура объекта CASettings
```javascript
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;
}
```  

# Файловые ключи

## Обычные файловые ключи

Считывание

```javascript
const ownerInfo = await ds.readFileKey(
  // Файл с ключом
  privateKey,
  // Пароль
  password,
  // Сертификаты ключа (необязательно)
  privateKeyCertificates
);
```
## JKS-контейнеры

Проверка, является ли файл JKS-контейнером

```javascript
const isJKSContainer = ds.isJKSContainer(/* Файл с ключом */ fileKey);
```

Получение списка ключей из JKS-контейнера

```javascript
const JKSPrivateKeys = await ds.getJKSPrivateKeys(/* Файл с ключом */ fileKey);
```

Считывание одного из ключей

```javascript
// Предоставить пользователю возможность выбрать ключ из списка, полученного из метода getJKSPrivateKeys
const JKSPrivateKey = JKSPrivateKeys[0];

const keyInfo = await ds.readFileKey(
  JKSPrivateKey.privateKey,
  password,
  JKSPrivateKey.certificates.select(cert => cert.data)
);
```

# Аппаратные ключи

Получение списка ключей

```javascript
const keyMedias = await ds.getKeyMedias();
```

Считывание ключа

```javascript
// Предоставить пользователю возможность выбрать ключ из списка, полученного из метода getKeyMedias
const hardwareKey = keyMedias[0];

hardwareKey.password = password;

const keyInfo = await ds.readHardwareKey(
  // Информация о ключе
  hardwareKey,
  // Сертификаты ключа (необязательно)
  privateKeyCertificates
);
```

# Облачные ключи

Провайдеры облачныч ключей есть 4х видов: 
* работающие через QR код (Дія.Підпис, SmartID, CloudKey, ПУМБ)
* работающие через ID пользователя (DepositSign, ESign, Вчасно, ДПС)
* Гряда + сервис подписи
* vToken (Укргазбанк, Банк Альянс)

Получение списока провайдеров облачных ключей

```javascript
const ksps = ds.KSPs;
```

Содержимое обьекта KSP

```javascript
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 кода

```javascript
ds.addConfirmKSPOperationEventListener(eventArgs => { ... });
```

Событие будет вызываться при:  
1. Считывании ключа с getCerts = true  
2. Подписании данных  

**Важно!** При необходимости подписать несколько файлов, нужно передавать их в функцию подписания все за раз в массиве. Иначе пользователю придётся подтверждать подписание каждого файла отдельно  

Структура объекта, приходящего в коллбек события  
```javascript
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 уведомление  и он должен будет подтвердить операцию  

Считывание ключа

```javascript
// Предоставить пользователю возможность выбрать провайдера ключей
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 сначала нужно авторизироваться и получить список ключей, доступных пользователю:

```javascript
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:

```javascript
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;
}

```

Считать выбранный ключ:

```javascript
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, в которую передавать код, который укажет пользователь.  
Если подписание выполняется сразу после считывания ключа, можно использовать тот же код.  

```javascript

if (keyMediasResponse.isTwoFactor) {
  await this.ds.setTwoFactorCodeKSP(this.twofaCode);
}

const signResult = await this.ds.signData(...);

```

# Сохранение ключей

Сохранить ключ

```javascript
await ds.storePrivateKeyInfo(
  // Информация о ключе
  privateKeyInfo,
  // Будет ли ключ сохранён после закрытия вкладки
  toLocalStorage,
```

Считать сохранённые ключи

```javascript
const keyInfo = await ds.getStoredPrivateKeyInfo(
  // Тип ключа (необязательно) 
  keyType
```

Удалить сохранённые ключи

```javascript
await ds.removeStoredPrivateKeyInfo(
  // Идентификатор ключа (необязательно)
  keyId
```

# Создание подписей

## Формат подписи

Функции создания подписей поддерживают возможность выбирать формат контейнера подписи  
Формат подписи указывается в опциональном параметре signFormat  
По умолчанию используется формат подписи CAdES-X-Long Detached  

Структура объекта, описывающего формат подписи  

```javascript
class EndUserSignContainerInfo {
  // Тип контейнера подписи
  type: EndUserSignContainerType;
  // Уточняющий тип подписи
  subType: EndUserCAdESType | EndUserXAdESType | EndUserASiCType;
  // Тип подписи в ASiC контейнере (только для ASiC контейнеров)
  asicSignType: EndUserASiCSignType;
  // Уровень подписи
  signLevel: EndUserSignType | EndUserXAdESSignLevel | EndUserPAdESSignLevel;
}
import { EUSignCP.EndUserSignContainerInfo } from "@it-enterprise/digital-signature";
```
Типы контейнеров подписи
```javascript
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
```javascript
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
```javascript
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
```javascript
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
```javascript
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
```javascript
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
```javascript
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 контейнере
```javascript
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";
```

Пример использования формата подписи:
```javascript
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);

## Формат передачи данных

Все функции создания подписей поддерживают следующие форматы передачи данных:  
1. Одиночный набор данных (в зависимости от функции - ссылка на загрузку файла, данные в base64 или Uint8Array и т.д.)
2. Данные в массиве (данные как в п.1, только в массиве). Подписи так же будут возвращены в массиве
3. Именованные данные (данные в объекте NamedData, содержащем имя набора данных и сами данные). Подпись так же будет возвращена в объекте NamedData
4. Именованные данные в массиве (данные как в п.3, только в массиве). Результатом выполения функций будет являться массив обьектов NamedData с подписями  
**Для лучшей поддержки всех форматов подписей и типов ключей, рекомендуется использовать формат из п.4**

Структура объекта NamedData
```javascript
declare type NamedData = {
    // Имя набора данных
    name: string;
    // В качестве параметра при создании подписи: в зависимости от функции - ссылка на загрузку файла, данные в base64 или Uint8Array и т.д.
    // В качестве возвращаемого результата: контейнер с подписью
    val: string | Uint8Array;
};
import { EUSignCP.NamedData } from "@it-enterprise/digital-signature";
```
Пример использования формата именованных данных
```javascript
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: "подпись второго файла"
}]
```

## Функции для создания подписей

Подписание данных

```javascript
const sign = await ds.signData(
  // Данные в виде Uint8Array или строки base64
  data,
  // Формат подписи
  signFormat,
  // true - вернуть результат в виде массива байт,false - в виде строки base64. по умолчанию false
  false);
```

Подписание файла

```javascript
const sign = await ds.signFile(
  // Ссылка на загрузку файла (например, с веб-сервисов)
  data,
  // Формат подписи. [Формат подписи]
  signFormat,
  // true - вернуть результат в виде массива байт,false - в виде строки base64. по умолчанию false
  false);
```

Подписание хеша в формате CAdES Detached

```javascript
const sign = await ds.signHash(
  // Хеш в виде Uint8Array или строки base64
  hash,
  // true - вернуть результат в виде массива байт,false - в виде строки base64. по умолчанию false
  false);
```

Подписание хеша из файла в формате CAdES Detached

```javascript
const sign = await ds.signFileHash(
  // Ссылка на загрузку файла с хешем
  data,
  // true - вернуть результат в виде массива байт,false - в виде строки base64. по умолчанию false
  false);
```

Подписание данных с получением информации о подписи

```javascript
const sign = await ds.signDataEx(
  // Данные в виде Uint8Array или строки base64
  data,
  // Формат подписи
  signFormat);
```

Подписание файла с получением информации о подписи

```javascript
const sign = await ds.signFileEx(
  // Ссылка на загрузку файла (например, с веб-сервисов)
  data,
  // Формат подписи
  signFormat);
```

Подписание хеша в формате CAdES Detached с получением информации о подписи

```javascript
const sign = await ds.signHashEx(
  // Хеш в виде Uint8Array или строки base64
  data);
```

# Шифровання податкових звітів

Для шифрування податкових звітів, спочатку потрібно зчитати ключ з використанням окремих функцій **cxtReadFileKey** та **ctxReadHardwareKey**

```javascript
const keyInfo = await ds.cxtReadFileKey(
  // Файл с ключем
  privateKey,
  // Пароль
  password,
  // Сертифікати ключа (необов'язково)
  privateKeyCertificates
);
```

```javascript
const keyInfo = await ds.ctxReadHardwareKey(
  // Інформація про ключ
  hardwareKey,
  // Сертифікати ключа (необов'язково)
  privateKeyCertificates
);
```

Для виконання шифрування, потрібно викликати функцію **protectTaxReports**

```javascript
const protectedReports = await ds.protectTaxReports({
  // Зчитаний ключ
  directorPrivateKeyContext: keyInfo,
  // Email відправника
  senderEMail,
  // Сертифікат отримувача (податкової) в форматі Uint8Array
  recipientCertificate,
  reports: [
    {
      // Назва звіту
      name,
      // Вміст звіту в форматі Uint8Array
      data
    }
  ]
});
```

Після виконання шифрування, ключ необхідно очистити, викликавши функцію **ctxFreePrivateKey**

```javascript
await ds.ctxReadHardwareKey(
  // Зчитаний ключ
  keyInfo,
);
