2023-03-31 13:22:11 +03:00

441 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import moment from "moment";
export function isPluginCryptoProInstalled()
{
return new Promise(function(resolve, reject)
{
console.log("isPluginCryptoProInstalled");
console.log("window.cadesplugin", "BEFORE", window.cadesplugin);
setTimeout(() =>
{
console.log("window.cadesplugin", "AFTER", window.cadesplugin);
if(window.cadesplugin !== undefined)
{
window.cadesplugin.async_spawn(function *(args)
{
try
{
yield window.cadesplugin
}
catch (e)
{
console.error("isPluginCryptoProInstalled");
console.error(e);
reject({ message: e })
return;
}
resolve();
});
}
else
{
reject();
}
}, 500);
});
}
/**
* Получение списка сертификатов пользователя
* @returns {*}
*/
export function getCertificates()
{
return new Promise(function(resolve, reject)
{
setTimeout(() =>
{
window.cadesplugin.async_spawn(function *(args)
{
try
{
var store = yield window.cadesplugin.CreateObjectAsync("CAdESCOM.Store");
yield store.Open(
window.cadesplugin.CAPICOM_CURRENT_USER_STORE,
window.cadesplugin.CAPICOM_MY_STORE,
window.cadesplugin.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED
);
var certificates = yield store.Certificates;
var certificatesCount = yield certificates.Count
var data = [];
for (let i = 0; i < certificatesCount; i++)
{
let certificate = yield certificates.Item(i+1)
data.push({
index: i+1,
certificate: certificate,
info: {
subjectName: parseSubjectNameToObj(yield certificate.SubjectName)['name'],
subjectFields: parseSubjectNameToObj(yield certificate.SubjectName), //parseSubjectNameToArray(yield certificate.SubjectName),
issuerName: yield certificate.IssuerName,
validFromDate: yield certificate.ValidFromDate,
validToDate: yield certificate.ValidToDate
}
});
}
store.Close();
resolve(data);
}
catch (e)
{
console.error("getCertificates");
console.error(e);
reject(e);
}
});
}, 500);
});
}
/**
* Парсинг данных владельца сертификата
* @param string - Строка с информацией о владельце
* @returns {[{}]}
*
* example:
* input: 'C=RU, S="Магаданская область", L=Магадан, O="OOO ""Несуществующая компания""", OU=Подразделение, CN=Иван Иванов, E=ivan@mail.ru'
* output: [{
* fieldName: 'Имя',
* value: 'Иван Иванов'
* }, {
* fieldName: 'Электронная почта',
* value: 'ivan@mail.ru'
* }, {
* fieldName: 'Страна',
* value: 'RU'
* }, {
* fieldName: 'Область, шташ',
* value: '"Магаданская область"'
* }, {
* fieldName: 'Город',
* value: 'Магадан'
* }, {
* fieldName: 'Организация',
* value: 'OOO ""Несуществующая компания""'
* }, {
* fieldName: 'Подраздиление',
* value: 'Подразделение'
* }]
*
*/
function parseSubjectNameToArray(string)
{
console.log("parseSubjectNameToArray", "string", string);
let outputData = [];
let fieldsNames = {
'CN': 'Имя',
'E': 'Электронная почта',
'C': 'Страна',
'S': 'Область, штат',
'L': 'Город',
'O': 'Организация',
'OU': 'Подраздиление',
'SN': 'SN',
'G': 'G',
};
// 'C=RU, S="Область, штат"' -> [['C', 'RU'], ['S', '"Область, штат"']]
let reg = RegExp('[а-яА-Я\\w]*=.*?((?=, [а-яА-Я\\w]+=)|$)','g');
let fields = string.matchAll(reg);
fields = Array.from(fields, x => x[0]);
fields = fields.map(field => field.split('='));
fields.forEach(field => {
if (field[0] in fieldsNames)
{
let fieldName = fieldsNames[field[0]];
outputData.push({
fieldName: fieldName,
value: field[1]
});
}
});
return outputData;
}
/**
* Парсинг данных владельца сертификата
* @param string - Строка с информацией о владельце
* @returns {{}}
*
* example:
* input: 'C=RU, S="Магаданская область", L=Магадан, O="OOO ""Несуществующая компания""", OU=Подразделение, CN=Иван Иванов, E=ivan@mail.ru'
* output: {
* name: 'Иван Иванов',
* email: 'ivan@mail.ru',
* country: 'RU',
* state: '"Магаданская область"',
* city: 'Магадан',
* organization: '"OOO ""Несуществующая компания"""',
* subdivision: 'Подразделение'
* }
*
*/
function parseSubjectNameToObj(string)
{
let outputData = [];
let fieldsNames = {
'CN': 'name',
'E': 'email',
'C': 'country',
'S': 'state',
'L': 'city',
'O': 'organization',
'OU': 'subdivision',
'SN': 'SN',
'G': 'G',
};
// 'C=RU, S="Область, штат"' -> [['C', 'RU'], ['S', '"Область, штат"']]
let reg = RegExp('[а-яА-Я\\w]*=.*?((?=, [а-яА-Я\\w]+=)|$)','g');
let fields = string.matchAll(reg);
fields = Array.from(fields, x => x[0]);
fields = fields.map(field => field.split('='));
fields.forEach(field => {
if (field[0] in fieldsNames)
{
let fieldName = fieldsNames[field[0]];
outputData[fieldName] = field[1];
}
});
return outputData;
}
/**
* Подпись данных
* @param dataToSign {String} - Данные для подписи
* @param certificate - Сертификат подписи
*
* @param returnObj - RETURN_DATA | RETURN_SIGNATURE
* RETURN_SIGNED_DATA - Возвращает подписанный файл
* RETURN_SIGNATURE - Возвращает подпись
*
* @param signingType - SIGN_ALL_DATA | ADD_SIGNATURE_TO_DATA
* SIGN_ALL_DATA - Подписать данные целиком
* ADD_SIGNATURE_TO_DATA - Добавить подпись к уже подписанным данным
*
* @returns {*}
*/
export function signData(dataToSign, certificate, returnObj, signingType)
{
return new Promise(function(resolve, reject)
{
window.cadesplugin.async_spawn(function *(args)
{
try {
var oSigner = yield window.cadesplugin.CreateObjectAsync("CAdESCOM.CPSigner");
yield oSigner.propset_Certificate(certificate);
var oSignedData = yield window.cadesplugin.CreateObjectAsync("CAdESCOM.CadesSignedData");
var CADES_BES = 1;
yield oSignedData.propset_ContentEncoding(1); //CADESCOM_BASE64_TO_BINARY
yield oSignedData.propset_Content(dataToSign);
yield oSigner.propset_Options(window.cadesplugin.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY);
let returnObjFlags = {
'RETURN_SIGNED_DATA': false,
'RETURN_SIGNATURE': true
};
let returnObjFlag = returnObjFlags[returnObj];
if (returnObjFlag === undefined)
{
reject("Некорректное значения параметра returnObj. Данный параметр может принимать значения RETURN_SIGNED_DATA или RETURN_SIGNATURE");
return;
}
let signedData = '';
if (signingType === 'SIGN_ALL_DATA')
{
signedData = yield oSignedData.SignCades(oSigner, CADES_BES, returnObjFlag);
}
else if (signingType === 'ADD_SIGNATURE_TO_DATA')
{
yield oSignedData.VerifyCades(dataToSign, CADES_BES);
signedData = yield oSignedData.CoSignCades(oSigner, CADES_BES, returnObjFlag);
}
else
{
reject('Incorrect signature type');
}
resolve(signedData);
} catch (e)
{
console.error("window.cadesplugin.async_spawn(function *(args) CATCH");
console.error(e);
reject(e);
}
});
});
}
/**
* Проверка наличия у данных подписи
* @param data
* @returns {*} - true | false
* true - данные подписаны
* false - данные не подписаны
*/
export function hasDataSignature(data)
{
return new Promise((resolve, reject) =>
{
window.cadesplugin.async_spawn(function *(args)
{
try
{
var oSignedData = yield window.cadesplugin.CreateObjectAsync("CAdESCOM.CadesSignedData");
try
{
let CADES_BES = 1;
yield oSignedData.VerifyCades(data, CADES_BES);
resolve(true);
}
catch (e2)
{
console.error("oSignedData.VerifyCades");
console.error(e2);
resolve(false);
}
}
catch (e)
{
console.error("CAdESCOM.CadesSignedData");
console.error(e);
reject(e);
}
});
});
}
/**
* Подписание файла
* @param file - Файл для подписи
* @param certificate - Сертификат подписи
*
* @param returnObj - RETURN_DATA | RETURN_SIGNATURE
* RETURN_SIGNED_DATA - Возвращает подписанный файл
* RETURN_SIGNATURE - Возвращает подпись
*
* @returns Подписанный файл
*/
export function signing(file, certificate, returnObj)
{
return new Promise((resolve, reject) =>
{
// Подписываем файл, у которого нет подписи
let handlerWithoutSig = (file) =>
{
return new Promise((resolve, reject) =>
{
var oFReader = new FileReader();
oFReader.readAsDataURL(file);
oFReader.onload = (oFREvent) =>
{
var header = ";base64,";
var sFileData = oFREvent.target.result;
var sBase64Data = sFileData.substr(sFileData.indexOf(header) + header.length);
signData(sBase64Data, certificate, returnObj, 'SIGN_ALL_DATA').then(resolve, reject);
}
});
}
// Подписываем файл, у которого уже есть подпись
let handlerWithSig = (file) =>
{
return new Promise((resolve, reject) =>
{
file.text()
.then(text =>
{
signData(text, certificate, returnObj, 'ADD_SIGNATURE_TO_DATA').then(resolve, reject);
})
.catch(reject);
});
}
file.text()
.then(text =>
{
return hasDataSignature(text)
})
.then(result =>
{
if (result)
{
return handlerWithSig(file)
}
else
{
return handlerWithoutSig(file)
}
})
.then(resolve).catch(reject);
});
}
/**
* Подпись файла и вернуть подписанный файл
* @param file - Файл для подписи
* @param certificate - Сертификат подписи
* @returns Подписанный файл
*/
export function signFile(file, certificate)
{
return new Promise((resolve, reject) =>
{
signing(file, certificate, 'RETURN_SIGNED_DATA')
.then(signedData =>
{
let filename = file.name + '.sig';
let signedFile = new File([signedData], filename);
resolve(signedFile);
})
.catch(reject);
});
}
/**
* Подписать файл и вернуть файл с данными подписи
* @param file - Файл для подписи
* @param certificate - Сертификат подписи
* @returns Подписанный файл
*/
export function generateSignature(file, certificate)
{
return new Promise((resolve, reject) =>
{
signing(file, certificate, 'RETURN_SIGNATURE')
.then(signedData =>
{
let filename = file.name + '.sig';
let signedFile = new File([signedData], filename);
resolve(signedFile);
})
.catch(reject);
});
}