В системе реализовано взаимодействие с криптопровайдерами, выполняющими функции подписания
пользовательских данных: КриптоПро,
НУЦ и другими.
Кроме того, пользовательские скрипты позволяют выполнять подписание данных с помощью других
облачных криптопровайдеров. Для работы с
данным функционалом необходимо настроить электронную подпись.
Для получения данных и контроля изменений в системе можно получить внутреннюю подпись данных. Данная
подпись не является юридически значимой. Ее предназначение — контроль изменений в приложении и фиксация
версии данных элемента приложения. С подписью предоставляются также и данные, вычисленные по настройкам подписи
приложения. В системе предусмотрено получение внутренней подписи для атрибутов элемента любого приложения и
для файла в приложении типа Документ. Для получения внутренней подписи необходимо
хранить приложение в контексте или найти его с помощью объектов Global или Namespace:
asyncfunctionworkWithDataSigns(): Promise<void> {
// Получение приложения из контекста// document — приложение типа Документconst app = Context.data.document!;
// Получение данных приложенияconst appData = await app.fetch();
// Получение подписейconst innerSigns = await appData.getDataSigns();
// Найдём внутреннюю подпись атрибутов, чтобы подписать данные с помощью криптопровайдераconst attributesInnerSign = innerSigns.find(innerSign => innerSign.type === SignType.Attributes);
if (!attributesInnerSign) {
thrownewError('Внутренняя подпись не найдена');
}
}
В предыдущем примере была получена внутренняя подпись для атрибутов приложения. Каждая внутренняя
подпись содержит хеш (отпечаток данных) и данные, которые были подписаны. В дальнейшем
такие данные возможно использовать для отправки провайдеру, подписывающему их:
asyncfunctionsaveSign(): Promise<void> {
// SignProvider — пример криптопровайдера// Включает в себя один метод вычисления подписи из данныхconst signProvider = new SignProvider();
// Получение подписи для атрибутовconst signData = signProvider.sign(attributesInnerSign.body);
const newSign: NewSign = {
// Подпись в формате base64sign: signData;
// Тип подписи в зависимости от того, что необходимо подписать — attributes или file
signType: attributesInnerSign.type;
// Код провайдера
codeProvider: 'signProvider';
// ID файла в формате base64
body: attributesInnerSign.body,
// Хеш подписанных данных (необходим для идентификации версии подписываемых данных)hash: attributesInnerSign.hash,
}
await appData.uploadSign(newSign);
}
Для получения содержимого подписанных атрибутов и самой подписи используются методы
createAttributesFile и EntitySign.createSignFile. Для того чтобы получить EntitySign, необходимо
получить историю подписей элемента приложения. Для нахождения необходимой версии подписи в истории можно воспользоваться
внутренней подписью приложения:
asyncfunctiongetSignsFiles(): Promise<void> {
// Получение приложения типа Документ из контекста пользовательского скриптаconst app = Context.data.document!;
// Получение данных приложенияconst appData = await app.fetch();
// Получение истории подписей элемента приложенияconst signsHistory = await appData.getSignHistory();
// Получение внутренних подписейconst innerSigns = await appData.getDataSigns();
// Найдём внутреннюю подпись атрибутов, чтобы подписать данные с помощью криптопровайдераconst attributesInnerSign = innerSigns.find(innerSign => innerSign.type === SignType.Attributes);
if (!attributesInnerSign) {
thrownewError('Внутренняя подпись не найдена');
}
// Найдём в архиве подпиcей подписи последней версии элемента приложенияconst signs = signsHistory.find(signs => signs.hash === attributesInnerSigns.hash);
if (!signs) {
thrownewError('Данная версия не подписана');
}
const dataSign = signs.signs[0];
const attributesFile = await dataSign.createAttributesFile();
const signFile = await dataSign.createSignFile();
}
В системе можно получить детальные данные о подписи, включающие в себя:
информацию о самой подписи;
содержимое подписи;
информацию о публичном ключе, с помощью которого выполнено подписание данных;
подписанные данные.
Для получения данных необходимо вызвать метод EntitySign.getDetails. Данный метод позволяет получить
детальные данные о подписи. Рассмотрим ситуацию, когда в пользовательском скрипте необходимо определить,
юридическим или физическим лицом выполнена подпись. Для этого необходимо получить подпись из истории и вызвать
метод EntitySign.getDetails. После получения данных необходимо проанализировать содержимое сертификата:
asyncfunctionwhoMadeSign(): Promise<void> {
// Получение приложения типа Документ из контекста пользовательского скриптаconst app = Context.data.document!;
// Получение данных приложенияconst appData = await app.fetch();
// Получение истории подписей приложенияconst signsHistory = await appData.getSignHistory();
// Получение последней подписиconst sign = signsHistory[0].signs[0];
// Получение информации о подписиconst signDetails = await sign.getDetails();
// Если заполнено одно из этих полей, то подпись выполнена юридическим лицом// Также для таких проверок можно использовать и другие поля сертификата, в зависимости// от провайдера, выдавшего цифровую подписьconst orgField = signDetails.subject['O'] || signDetails.subject['OU'];
if (orgField !== '') {
// Подпись для юридического лица
} else {
// Подпись для физического лица
}
}
Также вы можете получить информацию о сертификатах подписей, включающие в себя: данные об УЦ, кому выдан сертификат и время его действия.
Пример скрипта для получения информации о сертификатах подписей, истекающих в течение месяца:
asyncfunctionsignWithSoonExpiredCerts (): Promise<void> {
// Получение текущего пользователяconst user = await System.users.getCurrentUser();
// Дата, не позднее которой истекает действие сертификата подписи const expiredDate = new Datetime().addDate(0, 1, 0);
// Получение подписей пользователяconst digitalSigns = await System.signs.digitalSigns.search().where(sign => sign.__createdBy.eq(user)).all();
// Получение подписей, сертификаты которых истекают в течение следующего месяца const expiredSigns = digitalSigns.filter(sign => sign.data.validUntilAt?.beforeOrEqual(expiredDate));
// Запись в переменную контекста информации о подписях с истекающими сертификатами
Context.data.expiredcerts = 'Сертификаты, истекающие в течении месяца: ';
for (let sign of expiredSigns) {
const subjectName = sign.data.subject ? sign.data.subject['CN'] ?? 'имя неизвестно' : 'подписант неизвестен';
Context.data.expiredcerts += `${sign.id} : ${subjectName},`;
}
return;
}
Начало работы с подписями
В системе реализовано взаимодействие с криптопровайдерами, выполняющими функции подписания пользовательских данных: КриптоПро, НУЦ и другими. Кроме того, пользовательские скрипты позволяют выполнять подписание данных с помощью других облачных криптопровайдеров. Для работы с данным функционалом необходимо настроить электронную подпись.
Внутренняя подпись
Для получения данных и контроля изменений в системе можно получить внутреннюю подпись данных. Данная подпись не является юридически значимой. Ее предназначение — контроль изменений в приложении и фиксация версии данных элемента приложения. С подписью предоставляются также и данные, вычисленные по настройкам подписи приложения. В системе предусмотрено получение внутренней подписи для атрибутов элемента любого приложения и для файла в приложении типа Документ. Для получения внутренней подписи необходимо хранить приложение в контексте или найти его с помощью объектов Global или Namespace:
async function workWithDataSigns(): Promise<void> { // Получение приложения из контекста // document — приложение типа Документ const app = Context.data.document!; // Получение данных приложения const appData = await app.fetch(); // Получение подписей const innerSigns = await appData.getDataSigns(); // Найдём внутреннюю подпись атрибутов, чтобы подписать данные с помощью криптопровайдера const attributesInnerSign = innerSigns.find(innerSign => innerSign.type === SignType.Attributes); if (!attributesInnerSign) { throw new Error('Внутренняя подпись не найдена'); } }
Загрузка полученной подписи в систему
В предыдущем примере была получена внутренняя подпись для атрибутов приложения. Каждая внутренняя подпись содержит хеш (отпечаток данных) и данные, которые были подписаны. В дальнейшем такие данные возможно использовать для отправки провайдеру, подписывающему их:
async function saveSign(): Promise<void> { // SignProvider — пример криптопровайдера // Включает в себя один метод вычисления подписи из данных const signProvider = new SignProvider(); // Получение подписи для атрибутов const signData = signProvider.sign(attributesInnerSign.body); const newSign: NewSign = { // Подпись в формате base64 sign: signData; // Тип подписи в зависимости от того, что необходимо подписать — attributes или file signType: attributesInnerSign.type; // Код провайдера codeProvider: 'signProvider'; // ID файла в формате base64 body: attributesInnerSign.body, // Хеш подписанных данных (необходим для идентификации версии подписываемых данных) hash: attributesInnerSign.hash, } await appData.uploadSign(newSign); }
Получение файла подписанных атрибутов и файла подписи
Для получения содержимого подписанных атрибутов и самой подписи используются методы createAttributesFile и EntitySign.createSignFile. Для того чтобы получить EntitySign, необходимо получить историю подписей элемента приложения. Для нахождения необходимой версии подписи в истории можно воспользоваться внутренней подписью приложения:
async function getSignsFiles(): Promise<void> { // Получение приложения типа Документ из контекста пользовательского скрипта const app = Context.data.document!; // Получение данных приложения const appData = await app.fetch(); // Получение истории подписей элемента приложения const signsHistory = await appData.getSignHistory(); // Получение внутренних подписей const innerSigns = await appData.getDataSigns(); // Найдём внутреннюю подпись атрибутов, чтобы подписать данные с помощью криптопровайдера const attributesInnerSign = innerSigns.find(innerSign => innerSign.type === SignType.Attributes); if (!attributesInnerSign) { throw new Error('Внутренняя подпись не найдена'); } // Найдём в архиве подпиcей подписи последней версии элемента приложения const signs = signsHistory.find(signs => signs.hash === attributesInnerSigns.hash); if (!signs) { throw new Error('Данная версия не подписана'); } const dataSign = signs.signs[0]; const attributesFile = await dataSign.createAttributesFile(); const signFile = await dataSign.createSignFile(); }
Получение детальной информации о подписи
В системе можно получить детальные данные о подписи, включающие в себя:
Для получения данных необходимо вызвать метод EntitySign.getDetails. Данный метод позволяет получить детальные данные о подписи. Рассмотрим ситуацию, когда в пользовательском скрипте необходимо определить, юридическим или физическим лицом выполнена подпись. Для этого необходимо получить подпись из истории и вызвать метод EntitySign.getDetails. После получения данных необходимо проанализировать содержимое сертификата:
async function whoMadeSign(): Promise<void> { // Получение приложения типа Документ из контекста пользовательского скрипта const app = Context.data.document!; // Получение данных приложения const appData = await app.fetch(); // Получение истории подписей приложения const signsHistory = await appData.getSignHistory(); // Получение последней подписи const sign = signsHistory[0].signs[0]; // Получение информации о подписи const signDetails = await sign.getDetails(); // Если заполнено одно из этих полей, то подпись выполнена юридическим лицом // Также для таких проверок можно использовать и другие поля сертификата, в зависимости // от провайдера, выдавшего цифровую подпись const orgField = signDetails.subject['O'] || signDetails.subject['OU']; if (orgField !== '') { // Подпись для юридического лица } else { // Подпись для физического лица } }
Также вы можете получить информацию о сертификатах подписей, включающие в себя: данные об УЦ, кому выдан сертификат и время его действия.
Пример скрипта для получения информации о сертификатах подписей, истекающих в течение месяца:
async function signWithSoonExpiredCerts (): Promise<void> { // Получение текущего пользователя const user = await System.users.getCurrentUser(); // Дата, не позднее которой истекает действие сертификата подписи const expiredDate = new Datetime().addDate(0, 1, 0); // Получение подписей пользователя const digitalSigns = await System.signs.digitalSigns.search().where(sign => sign.__createdBy.eq(user)).all(); // Получение подписей, сертификаты которых истекают в течение следующего месяца const expiredSigns = digitalSigns.filter(sign => sign.data.validUntilAt?.beforeOrEqual(expiredDate)); // Запись в переменную контекста информации о подписях с истекающими сертификатами Context.data.expiredcerts = 'Сертификаты, истекающие в течении месяца: '; for (let sign of expiredSigns) { const subjectName = sign.data.subject ? sign.data.subject['CN'] ?? 'имя неизвестно' : 'подписант неизвестен'; Context.data.expiredcerts += `${sign.id} : ${subjectName},`; } return; }