mirror of
https://github.com/crypto-pro-web/crypto-pro-js.git
synced 2024-11-24 00:55:00 +03:00
Добавил метод вычисления хэша, обновил пример с тэгом script
This commit is contained in:
parent
1f452c4ca0
commit
e456be7eda
@ -4,21 +4,28 @@
|
|||||||
;(function () {
|
;(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var $certs = document.getElementById('certList'),
|
var $certificate = document.getElementById('certificate'),
|
||||||
$errorMsg = document.getElementById('errorMessage');
|
$createSignature = document.getElementById('createSignature'),
|
||||||
|
$certificateDetails = document.getElementById('certificateDetails'),
|
||||||
|
$certificateError = document.getElementById('certificateError');
|
||||||
|
|
||||||
window.cryptoPro.getUserCertificates()
|
$certificate.addEventListener('change', function handleCertSelection() {
|
||||||
.then(function (certificateList) {
|
var thumbprint = $certificate.value;
|
||||||
|
|
||||||
|
$createSignature.disabled = !thumbprint;
|
||||||
|
$certificateDetails.style.display = thumbprint ? 'block' : 'none';
|
||||||
|
});
|
||||||
|
|
||||||
|
window.cryptoPro.getUserCertificates().then(function (certificateList) {
|
||||||
certificateList.forEach(function (certificate) {
|
certificateList.forEach(function (certificate) {
|
||||||
var $certOption = document.createElement('option');
|
var $certOption = document.createElement('option');
|
||||||
|
|
||||||
$certOption.textContent = certificate.name + ' (действителен до: ' + certificate.validTo + ')';
|
$certOption.textContent = certificate.name + ' (действителен до: ' + certificate.validTo + ')';
|
||||||
|
|
||||||
$certOption.value = certificate.thumbprint;
|
$certOption.value = certificate.thumbprint;
|
||||||
|
|
||||||
$certs.appendChild($certOption);
|
$certificate.appendChild($certOption);
|
||||||
});
|
});
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
$errorMsg.textContent = '\n' + error.message;
|
$certificateError.textContent = '\n' + error.message;
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@ -1,24 +1,52 @@
|
|||||||
/**
|
/**
|
||||||
* Пример создания подписи данных, сгенерированных по ГОСТ Р 34.11-94
|
* Пример создания подписи данных
|
||||||
* https://ru.wikipedia.org/wiki/%D0%93%D0%9E%D0%A1%D0%A2_%D0%A0_34.11-94
|
|
||||||
* */
|
* */
|
||||||
;(function () {
|
;(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var $errorMsg = document.getElementById('errorMessage');
|
var $createSignature = document.forms.createSignature,
|
||||||
|
$certificate = document.getElementById('certificate'),
|
||||||
|
$message = document.getElementById('message'),
|
||||||
|
$hash = document.getElementById('hash'),
|
||||||
|
$hashError = document.getElementById('hashError'),
|
||||||
|
$signature = document.getElementById('signature'),
|
||||||
|
$signatureError = document.getElementById('signatureError');
|
||||||
|
|
||||||
document
|
$createSignature.addEventListener('reset', function () {
|
||||||
.getElementById('createSign')
|
window.location.reload();
|
||||||
.addEventListener('click', function () {
|
});
|
||||||
// Вычислинный hash по ГОСТ Р 34.11-94 для строки: "abc"
|
|
||||||
var hash = 'b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c',
|
|
||||||
hashBase64 = window.btoa(hash),
|
|
||||||
thumbprint = document.getElementById('certList').value;
|
|
||||||
|
|
||||||
window.cryptoPro.createSignature(thumbprint, hashBase64).then(function (signature) {
|
$createSignature.addEventListener('submit', function (event) {
|
||||||
document.getElementById('createdSign').value = signature;
|
var thumbprint = $certificate.value,
|
||||||
|
message = $message.value,
|
||||||
|
hashingAlgorithm = document.querySelector('input[name="hashingAlgorithm"]:checked').value;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
$hash.placeholder = 'Вычисляется...';
|
||||||
|
$hash.value = '';
|
||||||
|
|
||||||
|
window.cryptoPro.createHash(message, hashingAlgorithm).then(function (hash) {
|
||||||
|
var detachedSignature = document.querySelector('input[name="signatureType"]:checked').value;
|
||||||
|
|
||||||
|
detachedSignature = Boolean(Number(detachedSignature));
|
||||||
|
|
||||||
|
$hash.value = hash;
|
||||||
|
|
||||||
|
$signature.placeholder = 'Создается...';
|
||||||
|
$signature.value = '';
|
||||||
|
|
||||||
|
window.cryptoPro.createSignature(thumbprint, hash, detachedSignature).then(function (signature) {
|
||||||
|
$signature.value = signature;
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
$errorMsg.textContent = '\n' + error.message;
|
$signature.placeholder = 'Не создана';
|
||||||
|
|
||||||
|
$signatureError.textContent = '\n' + error.message;
|
||||||
|
});
|
||||||
|
}, function (error) {
|
||||||
|
$hash.placeholder = 'Не вычислен';
|
||||||
|
|
||||||
|
$hashError.textContent = '\n' + error.message;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@ -4,17 +4,18 @@
|
|||||||
;(function () {
|
;(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var $errorMsg = document.getElementById('errorMessage');
|
var $systemInfo = document.getElementById('systemInfo'),
|
||||||
|
$systemInfoError = document.getElementById('systemInfoError');
|
||||||
|
|
||||||
window.cryptoPro.getSystemInfo().then(function (systemInfo) {
|
window.cryptoPro.getSystemInfo().then(function (systemInfo) {
|
||||||
window.cryptoPro.isValidSystemSetup().then(function (isValidSystemSetup) {
|
window.cryptoPro.isValidSystemSetup().then(function (isValidSystemSetup) {
|
||||||
systemInfo.isValidSystemSetup = isValidSystemSetup;
|
systemInfo.isValidSystemSetup = isValidSystemSetup;
|
||||||
|
|
||||||
document.getElementById('systemInfo').textContent = JSON.stringify(systemInfo, null, ' ');
|
$systemInfo.textContent = JSON.stringify(systemInfo, null, ' ');
|
||||||
}, function (error) {
|
}, handleError);
|
||||||
$errorMsg.textContent = '\n' + error.message;
|
}, handleError);
|
||||||
});
|
|
||||||
}, function (error) {
|
function handleError(error) {
|
||||||
$errorMsg.textContent = '\n' + error.message;
|
$systemInfoError.textContent = '\n' + error.message;
|
||||||
});
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -5,14 +5,76 @@
|
|||||||
<title>Пример использования cryptoPro</title>
|
<title>Пример использования cryptoPro</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<select id="certList"></select>
|
<form name="createSignature" novalidate>
|
||||||
<button id="createSign" type="button">Создать подпись</button>
|
<fieldset>
|
||||||
<button id="showCertificate" type="button">Информация о сертификате</button>
|
<legend>Создание подписи</legend>
|
||||||
|
<label for="message">Данные для подиси: *</label>
|
||||||
<br>
|
<br>
|
||||||
|
<textarea id="message" cols="130" rows="5" placeholder="Введите сообщение" autofocus required>abc</textarea>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label for="certificate">Сертификат: *</label>
|
||||||
|
<br>
|
||||||
|
<select id="certificate" tabindex="-1" required>
|
||||||
|
<option disabled selected>Не выбран</option>
|
||||||
|
</select>
|
||||||
|
<details id="certificateDetails">
|
||||||
|
<summary>Информация о сертификате</summary>
|
||||||
<pre id="certificateInfo"></pre>
|
<pre id="certificateInfo"></pre>
|
||||||
<textarea id="createdSign" cols="100" rows="30"></textarea>
|
</details>
|
||||||
<pre id="errorMessage"></pre>
|
<pre id="certificateError"></pre>
|
||||||
|
|
||||||
|
<label>Тип подписи: *</label>
|
||||||
|
<br>
|
||||||
|
<label><input type="radio" name="signatureType" value="0" checked>Совмещенная</label>
|
||||||
|
<br>
|
||||||
|
<label><input type="radio" name="signatureType" value="1">Отделенная</label>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label>Алгоритм хэширования: *</label>
|
||||||
|
<br>
|
||||||
|
<label><input type="radio" name="hashingAlgorithm" value="GOST_3411">ГОСТ Р 34.11-94</label><br>
|
||||||
|
<label><input type="radio" name="hashingAlgorithm" value="GOST_3411_2012_256">ГОСТ Р 34.11-2012 (256)</label><br>
|
||||||
|
<label><input type="radio" name="hashingAlgorithm" value="GOST_3411_2012_512" checked>ГОСТ Р 34.11-2012 (512)</label><br>
|
||||||
|
<label><input type="radio" name="hashingAlgorithm" value="GOST_3411_HMAC">ГОСТ Р 34.11-94 (HMAC)</label><br>
|
||||||
|
<label><input type="radio" name="hashingAlgorithm" value="GOST_3411_2012_256_HMAC">ГОСТ Р 34.11-2012 (HMAC 256)</label><br>
|
||||||
|
<label><input type="radio" name="hashingAlgorithm" value="GOST_3411_2012_512_HMAC">ГОСТ Р 34.11-2012 (HMAC 512)</label>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<button id="createSignature" type="submit" disabled>Создать подпись</button>
|
||||||
|
<button type="reset">Сбросить</button>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Результат</legend>
|
||||||
|
<label for="hash">Хэш:</label><br>
|
||||||
|
<textarea id="hash" cols="130" rows="5" placeholder="Не вычислен"></textarea>
|
||||||
|
<br>
|
||||||
|
<pre id="hashError"></pre>
|
||||||
|
|
||||||
|
<label for="signature">Подпись:</label><br>
|
||||||
|
<textarea id="signature" cols="130" rows="30" placeholder="Не создана"></textarea>
|
||||||
|
<p>
|
||||||
|
Для проверки нужно создать файл со сгенерированной подписью в кодировке UTF-8 с расширением *.sig
|
||||||
|
<br>
|
||||||
|
для совмещенной подписи (или *.sgn для отделенной).
|
||||||
|
</p>
|
||||||
|
<a href="https://www.gosuslugi.ru/pgu/eds/"
|
||||||
|
target="_blank"
|
||||||
|
rel="nofollow noopener noreferrer"
|
||||||
|
title="Перейти к проверке подписи">
|
||||||
|
Проверить подпись
|
||||||
|
</a>
|
||||||
|
<pre id="signatureError"></pre>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Информация о системе</legend>
|
||||||
<pre id="systemInfo"></pre>
|
<pre id="systemInfo"></pre>
|
||||||
|
<pre id="systemInfoError"></pre>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
|
||||||
<!-- Полифиллы для работы библиотеки -->
|
<!-- Полифиллы для работы библиотеки -->
|
||||||
<script src="polyfills/promise.js"></script>
|
<script src="polyfills/promise.js"></script>
|
||||||
@ -23,6 +85,7 @@
|
|||||||
|
|
||||||
<!-- Полифиллы для работы демо скриптов -->
|
<!-- Полифиллы для работы демо скриптов -->
|
||||||
<script src="polyfills/atob-btoa.js"></script>
|
<script src="polyfills/atob-btoa.js"></script>
|
||||||
|
<script src="polyfills/details-element-polyfill.js"></script>
|
||||||
|
|
||||||
<!-- Демо скрипты -->
|
<!-- Демо скрипты -->
|
||||||
<script src="cert-list.js"></script>
|
<script src="cert-list.js"></script>
|
||||||
|
194
examples/script-tag/public/polyfills/details-element-polyfill.js
Normal file
194
examples/script-tag/public/polyfills/details-element-polyfill.js
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
Details Element Polyfill 2.4.0
|
||||||
|
Copyright © 2019 Javan Makhmali
|
||||||
|
*/
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
var element = document.createElement("details");
|
||||||
|
var elementIsNative = typeof HTMLDetailsElement != "undefined" && element instanceof HTMLDetailsElement;
|
||||||
|
var support = {
|
||||||
|
open: "open" in element || elementIsNative,
|
||||||
|
toggle: "ontoggle" in element
|
||||||
|
};
|
||||||
|
var styles = '\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\nsummary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\n[open] > summary::before {\n content: "▼";\n}\n';
|
||||||
|
var _ref = [], forEach = _ref.forEach, slice = _ref.slice;
|
||||||
|
if (!support.open) {
|
||||||
|
polyfillStyles();
|
||||||
|
polyfillProperties();
|
||||||
|
polyfillToggle();
|
||||||
|
polyfillAccessibility();
|
||||||
|
}
|
||||||
|
if (support.open && !support.toggle) {
|
||||||
|
polyfillToggleEvent();
|
||||||
|
}
|
||||||
|
function polyfillStyles() {
|
||||||
|
document.head.insertAdjacentHTML("afterbegin", "<style>" + styles + "</style>");
|
||||||
|
}
|
||||||
|
function polyfillProperties() {
|
||||||
|
var prototype = document.createElement("details").constructor.prototype;
|
||||||
|
var setAttribute = prototype.setAttribute, removeAttribute = prototype.removeAttribute;
|
||||||
|
var open = Object.getOwnPropertyDescriptor(prototype, "open");
|
||||||
|
Object.defineProperties(prototype, {
|
||||||
|
open: {
|
||||||
|
get: function get() {
|
||||||
|
if (this.tagName == "DETAILS") {
|
||||||
|
return this.hasAttribute("open");
|
||||||
|
} else {
|
||||||
|
if (open && open.get) {
|
||||||
|
return open.get.call(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set: function set(value) {
|
||||||
|
if (this.tagName == "DETAILS") {
|
||||||
|
return value ? this.setAttribute("open", "") : this.removeAttribute("open");
|
||||||
|
} else {
|
||||||
|
if (open && open.set) {
|
||||||
|
return open.set.call(this, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setAttribute: {
|
||||||
|
value: function value(name, _value) {
|
||||||
|
var _this = this;
|
||||||
|
var call = function call() {
|
||||||
|
return setAttribute.call(_this, name, _value);
|
||||||
|
};
|
||||||
|
if (name == "open" && this.tagName == "DETAILS") {
|
||||||
|
var wasOpen = this.hasAttribute("open");
|
||||||
|
var result = call();
|
||||||
|
if (!wasOpen) {
|
||||||
|
var summary = this.querySelector("summary");
|
||||||
|
if (summary) summary.setAttribute("aria-expanded", true);
|
||||||
|
triggerToggle(this);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return call();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeAttribute: {
|
||||||
|
value: function value(name) {
|
||||||
|
var _this2 = this;
|
||||||
|
var call = function call() {
|
||||||
|
return removeAttribute.call(_this2, name);
|
||||||
|
};
|
||||||
|
if (name == "open" && this.tagName == "DETAILS") {
|
||||||
|
var wasOpen = this.hasAttribute("open");
|
||||||
|
var result = call();
|
||||||
|
if (wasOpen) {
|
||||||
|
var summary = this.querySelector("summary");
|
||||||
|
if (summary) summary.setAttribute("aria-expanded", false);
|
||||||
|
triggerToggle(this);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return call();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function polyfillToggle() {
|
||||||
|
onTogglingTrigger(function(element) {
|
||||||
|
element.hasAttribute("open") ? element.removeAttribute("open") : element.setAttribute("open", "");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function polyfillToggleEvent() {
|
||||||
|
if (window.MutationObserver) {
|
||||||
|
new MutationObserver(function(mutations) {
|
||||||
|
forEach.call(mutations, function(mutation) {
|
||||||
|
var target = mutation.target, attributeName = mutation.attributeName;
|
||||||
|
if (target.tagName == "DETAILS" && attributeName == "open") {
|
||||||
|
triggerToggle(target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).observe(document.documentElement, {
|
||||||
|
attributes: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
onTogglingTrigger(function(element) {
|
||||||
|
var wasOpen = element.getAttribute("open");
|
||||||
|
setTimeout(function() {
|
||||||
|
var isOpen = element.getAttribute("open");
|
||||||
|
if (wasOpen != isOpen) {
|
||||||
|
triggerToggle(element);
|
||||||
|
}
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function polyfillAccessibility() {
|
||||||
|
setAccessibilityAttributes(document);
|
||||||
|
if (window.MutationObserver) {
|
||||||
|
new MutationObserver(function(mutations) {
|
||||||
|
forEach.call(mutations, function(mutation) {
|
||||||
|
forEach.call(mutation.addedNodes, setAccessibilityAttributes);
|
||||||
|
});
|
||||||
|
}).observe(document.documentElement, {
|
||||||
|
subtree: true,
|
||||||
|
childList: true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMNodeInserted", function(event) {
|
||||||
|
setAccessibilityAttributes(event.target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setAccessibilityAttributes(root) {
|
||||||
|
findElementsWithTagName(root, "SUMMARY").forEach(function(summary) {
|
||||||
|
var details = findClosestElementWithTagName(summary, "DETAILS");
|
||||||
|
summary.setAttribute("aria-expanded", details.hasAttribute("open"));
|
||||||
|
if (!summary.hasAttribute("tabindex")) summary.setAttribute("tabindex", "0");
|
||||||
|
if (!summary.hasAttribute("role")) summary.setAttribute("role", "button");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function eventIsSignificant(event) {
|
||||||
|
return !(event.defaultPrevented || event.ctrlKey || event.metaKey || event.shiftKey || event.target.isContentEditable);
|
||||||
|
}
|
||||||
|
function onTogglingTrigger(callback) {
|
||||||
|
addEventListener("click", function(event) {
|
||||||
|
if (eventIsSignificant(event)) {
|
||||||
|
if (event.which <= 1) {
|
||||||
|
var element = findClosestElementWithTagName(event.target, "SUMMARY");
|
||||||
|
if (element && element.parentNode && element.parentNode.tagName == "DETAILS") {
|
||||||
|
callback(element.parentNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
addEventListener("keydown", function(event) {
|
||||||
|
if (eventIsSignificant(event)) {
|
||||||
|
if (event.keyCode == 13 || event.keyCode == 32) {
|
||||||
|
var element = findClosestElementWithTagName(event.target, "SUMMARY");
|
||||||
|
if (element && element.parentNode && element.parentNode.tagName == "DETAILS") {
|
||||||
|
callback(element.parentNode);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
function triggerToggle(element) {
|
||||||
|
var event = document.createEvent("Event");
|
||||||
|
event.initEvent("toggle", false, false);
|
||||||
|
element.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
function findElementsWithTagName(root, tagName) {
|
||||||
|
return (root.tagName == tagName ? [ root ] : []).concat(typeof root.getElementsByTagName == "function" ? slice.call(root.getElementsByTagName(tagName)) : []);
|
||||||
|
}
|
||||||
|
function findClosestElementWithTagName(element, tagName) {
|
||||||
|
if (typeof element.closest == "function") {
|
||||||
|
return element.closest(tagName);
|
||||||
|
} else {
|
||||||
|
while (element) {
|
||||||
|
if (element.tagName == tagName) {
|
||||||
|
return element;
|
||||||
|
} else {
|
||||||
|
element = element.parentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
@ -4,10 +4,18 @@
|
|||||||
;(function () {
|
;(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
document
|
var $certificate = document.getElementById('certificate'),
|
||||||
.getElementById('showCertificate')
|
$certificateDetails = document.getElementById('certificateDetails'),
|
||||||
.addEventListener('click', function () {
|
$certificateInfo = document.getElementById('certificateInfo'),
|
||||||
var thumbprint = document.getElementById('certList').value;
|
$certificatesError = document.getElementById('certificatesError');
|
||||||
|
|
||||||
|
$certificateDetails.style.display = 'none';
|
||||||
|
|
||||||
|
$certificateDetails.addEventListener('toggle', function () {
|
||||||
|
if ($certificateDetails.open) {
|
||||||
|
var thumbprint = $certificate.value;
|
||||||
|
|
||||||
|
$certificateInfo.textContent = 'Запрашивается...';
|
||||||
|
|
||||||
window.cryptoPro.getCertificate(thumbprint).then(function (certificate) {
|
window.cryptoPro.getCertificate(thumbprint).then(function (certificate) {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
@ -24,7 +32,7 @@
|
|||||||
certificate.hasExtendedKeyUsage('1.3.6.1.4.1.311.80.2'),
|
certificate.hasExtendedKeyUsage('1.3.6.1.4.1.311.80.2'),
|
||||||
certificate.hasExtendedKeyUsage(['1.3.6.1.5.5.7.3.3', '1.3.6.1.4.1.311.10.3.12']),
|
certificate.hasExtendedKeyUsage(['1.3.6.1.5.5.7.3.3', '1.3.6.1.4.1.311.10.3.12']),
|
||||||
]).then(function (results) {
|
]).then(function (results) {
|
||||||
document.getElementById('certificateInfo').textContent = JSON.stringify({
|
$certificateInfo.textContent = JSON.stringify({
|
||||||
name: certificate.name,
|
name: certificate.name,
|
||||||
issuerName: certificate.issuerName,
|
issuerName: certificate.issuerName,
|
||||||
subjectName: certificate.subjectName,
|
subjectName: certificate.subjectName,
|
||||||
@ -44,7 +52,16 @@
|
|||||||
'1.3.6.1.4.1.311.80.2': results[10],
|
'1.3.6.1.4.1.311.80.2': results[10],
|
||||||
"'1.3.6.1.5.5.7.3.3', '1.3.6.1.4.1.311.10.3.12'": results[11],
|
"'1.3.6.1.5.5.7.3.3', '1.3.6.1.4.1.311.10.3.12'": results[11],
|
||||||
}, null, ' ');
|
}, null, ' ');
|
||||||
|
}, handleError);
|
||||||
|
}, handleError);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$certificateInfo.textContent = '';
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
function handleError(error) {
|
||||||
|
$certificatesError.textContent = '\n' + error.message;
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
71
src/api/createHash.ts
Normal file
71
src/api/createHash.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { _afterPluginsLoaded } from '../helpers/_afterPluginsLoaded';
|
||||||
|
import { _extractMeaningfulErrorMessage } from '../helpers/_extractMeaningfulErrorMessage';
|
||||||
|
import { __cadesAsyncToken__, __createCadesPluginObject__, _generateCadesFn } from '../helpers/_generateCadesFn';
|
||||||
|
|
||||||
|
type Algorithm =
|
||||||
|
| 'GOST_3411'
|
||||||
|
| 'GOST_3411_2012_256'
|
||||||
|
| 'GOST_3411_2012_512'
|
||||||
|
| 'GOST_3411_HMAC'
|
||||||
|
| 'GOST_3411_2012_256_HMAC'
|
||||||
|
| 'GOST_3411_2012_512_HMAC';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Создает хэш сообщения по ГОСТ Р 34.11
|
||||||
|
* https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B8%D0%B1%D0%BE%D0%B3_(%D1%85%D0%B5%D1%88-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F)
|
||||||
|
*
|
||||||
|
* @param unencryptedMessage - сообщение для хеширования
|
||||||
|
* @param algorithm - один из алгоритмов хеширования:
|
||||||
|
* GOST_3411
|
||||||
|
* GOST_3411_2012_256
|
||||||
|
* GOST_3411_2012_512 - по умолчанию
|
||||||
|
* GOST_3411_HMAC
|
||||||
|
* GOST_3411_2012_256_HMAC
|
||||||
|
* GOST_3411_2012_512_HMAC
|
||||||
|
*
|
||||||
|
* @returns хэш
|
||||||
|
*/
|
||||||
|
export const createHash = _afterPluginsLoaded(
|
||||||
|
async (unencryptedMessage: string | ArrayBuffer, algorithm: Algorithm = 'GOST_3411_2012_512'): Promise<string> => {
|
||||||
|
const { cadesplugin } = window;
|
||||||
|
|
||||||
|
return eval(
|
||||||
|
_generateCadesFn(function createHash(): string {
|
||||||
|
const cadesHashedData = __cadesAsyncToken__ + __createCadesPluginObject__('CAdESCOM.HashedData');
|
||||||
|
let messageBase64;
|
||||||
|
let hash;
|
||||||
|
|
||||||
|
try {
|
||||||
|
messageBase64 = Buffer.from(unencryptedMessage).toString('base64');
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
throw new Error('Ошибка при преобразовании сообщения в Base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
void (
|
||||||
|
__cadesAsyncToken__ +
|
||||||
|
cadesHashedData.propset_Algorithm(cadesplugin['CADESCOM_HASH_ALGORITHM_CP_' + algorithm])
|
||||||
|
);
|
||||||
|
void (__cadesAsyncToken__ + cadesHashedData.propset_DataEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY));
|
||||||
|
void (__cadesAsyncToken__ + cadesHashedData.Hash(messageBase64));
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
throw new Error(_extractMeaningfulErrorMessage(error) || 'Ошибка при инициализации хэширования');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
hash = __cadesAsyncToken__ + cadesHashedData.Value;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
throw new Error(_extractMeaningfulErrorMessage(error) || 'Ошибка при создании хэша');
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
@ -9,12 +9,12 @@ import { _getDateObj } from '../helpers/_getDateObj';
|
|||||||
* Создает подпись base64 строки по отпечатку сертификата
|
* Создает подпись base64 строки по отпечатку сертификата
|
||||||
*
|
*
|
||||||
* @param thumbprint - отпечаток сертификата
|
* @param thumbprint - отпечаток сертификата
|
||||||
* @param dataBase64 - строковые данные в формате base64
|
* @param messageHash - хэш подписываемого сообщения, сгенерированный по ГОСТ Р 34.11
|
||||||
* @param detachedSignature = true - тип подписи открепленная (true) / присоединенная (false)
|
* @param detachedSignature = true - тип подписи открепленная (true) / присоединенная (false)
|
||||||
* @returns подпись
|
* @returns подпись
|
||||||
*/
|
*/
|
||||||
export const createSignature = _afterPluginsLoaded(
|
export const createSignature = _afterPluginsLoaded(
|
||||||
async (thumbprint: string, dataBase64: string, detachedSignature: boolean = true): Promise<string> => {
|
async (thumbprint: string, messageHash: string, detachedSignature: boolean = true): Promise<string> => {
|
||||||
const { cadesplugin } = window;
|
const { cadesplugin } = window;
|
||||||
const cadesCertificate = await _getCadesCert(thumbprint);
|
const cadesCertificate = await _getCadesCert(thumbprint);
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ export const createSignature = _afterPluginsLoaded(
|
|||||||
cadesAuthAttrs = __cadesAsyncToken__ + cadesSigner.AuthenticatedAttributes2;
|
cadesAuthAttrs = __cadesAsyncToken__ + cadesSigner.AuthenticatedAttributes2;
|
||||||
void (__cadesAsyncToken__ + cadesAuthAttrs.Add(cadesAttrs));
|
void (__cadesAsyncToken__ + cadesAuthAttrs.Add(cadesAttrs));
|
||||||
void (__cadesAsyncToken__ + cadesSignedData.propset_ContentEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY));
|
void (__cadesAsyncToken__ + cadesSignedData.propset_ContentEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY));
|
||||||
void (__cadesAsyncToken__ + cadesSignedData.propset_Content(dataBase64));
|
void (__cadesAsyncToken__ + cadesSignedData.propset_Content(messageHash));
|
||||||
void (
|
void (
|
||||||
__cadesAsyncToken__ + cadesSigner.propset_Options(cadesplugin.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY)
|
__cadesAsyncToken__ + cadesSigner.propset_Options(cadesplugin.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY)
|
||||||
);
|
);
|
||||||
|
@ -3,4 +3,5 @@ export * from './getUserCertificates';
|
|||||||
export * from './getSystemInfo';
|
export * from './getSystemInfo';
|
||||||
export * from './isValidSystemSetup';
|
export * from './isValidSystemSetup';
|
||||||
export * from './createSignature';
|
export * from './createSignature';
|
||||||
|
export * from './createHash';
|
||||||
export * from './certificate';
|
export * from './certificate';
|
||||||
|
Loading…
Reference in New Issue
Block a user