441 lines
11 KiB
JavaScript
441 lines
11 KiB
JavaScript
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);
|
||
});
|
||
} |