mirror of
				https://github.com/crypto-pro-web/crypto-pro-js.git
				synced 2025-10-31 06:13:22 +03:00 
			
		
		
		
	Добавил метод вычисления хэша, обновил пример с тэгом script
This commit is contained in:
		
							parent
							
								
									1f452c4ca0
								
							
						
					
					
						commit
						e456be7eda
					
				| @ -4,21 +4,28 @@ | ||||
| ;(function () { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   var $certs = document.getElementById('certList'), | ||||
|     $errorMsg = document.getElementById('errorMessage'); | ||||
|   var $certificate = document.getElementById('certificate'), | ||||
|     $createSignature = document.getElementById('createSignature'), | ||||
|     $certificateDetails = document.getElementById('certificateDetails'), | ||||
|     $certificateError = document.getElementById('certificateError'); | ||||
| 
 | ||||
|   window.cryptoPro.getUserCertificates() | ||||
|     .then(function (certificateList) { | ||||
|       certificateList.forEach(function (certificate) { | ||||
|         var $certOption = document.createElement('option'); | ||||
|   $certificate.addEventListener('change', function handleCertSelection() { | ||||
|     var thumbprint = $certificate.value; | ||||
| 
 | ||||
|         $certOption.textContent = certificate.name + ' (действителен до: ' + certificate.validTo + ')'; | ||||
|     $createSignature.disabled = !thumbprint; | ||||
|     $certificateDetails.style.display = thumbprint ? 'block' : 'none'; | ||||
|   }); | ||||
| 
 | ||||
|         $certOption.value = certificate.thumbprint; | ||||
|   window.cryptoPro.getUserCertificates().then(function (certificateList) { | ||||
|     certificateList.forEach(function (certificate) { | ||||
|       var $certOption = document.createElement('option'); | ||||
| 
 | ||||
|         $certs.appendChild($certOption); | ||||
|       }); | ||||
|     }, function (error) { | ||||
|       $errorMsg.textContent = '\n' + error.message; | ||||
|       $certOption.textContent = certificate.name + ' (действителен до: ' + certificate.validTo + ')'; | ||||
|       $certOption.value = certificate.thumbprint; | ||||
| 
 | ||||
|       $certificate.appendChild($certOption); | ||||
|     }); | ||||
|   }, function (error) { | ||||
|     $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 () { | ||||
|   '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 | ||||
|     .getElementById('createSign') | ||||
|     .addEventListener('click', function () { | ||||
|       // Вычислинный hash по ГОСТ Р 34.11-94 для строки: "abc"
 | ||||
|       var hash = 'b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c', | ||||
|         hashBase64 = window.btoa(hash), | ||||
|         thumbprint = document.getElementById('certList').value; | ||||
|   $createSignature.addEventListener('reset', function () { | ||||
|     window.location.reload(); | ||||
|   }); | ||||
| 
 | ||||
|       window.cryptoPro.createSignature(thumbprint, hashBase64).then(function (signature) { | ||||
|         document.getElementById('createdSign').value = signature; | ||||
|   $createSignature.addEventListener('submit', function (event) { | ||||
|     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) { | ||||
|         $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 () { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   var $errorMsg = document.getElementById('errorMessage'); | ||||
|   var $systemInfo = document.getElementById('systemInfo'), | ||||
|     $systemInfoError = document.getElementById('systemInfoError'); | ||||
| 
 | ||||
|   window.cryptoPro.getSystemInfo().then(function (systemInfo) { | ||||
|     window.cryptoPro.isValidSystemSetup().then(function (isValidSystemSetup) { | ||||
|       systemInfo.isValidSystemSetup = isValidSystemSetup; | ||||
| 
 | ||||
|       document.getElementById('systemInfo').textContent = JSON.stringify(systemInfo, null, '  '); | ||||
|     }, function (error) { | ||||
|       $errorMsg.textContent = '\n' + error.message; | ||||
|     }); | ||||
|   }, function (error) { | ||||
|     $errorMsg.textContent = '\n' + error.message; | ||||
|   }); | ||||
|       $systemInfo.textContent = JSON.stringify(systemInfo, null, '  '); | ||||
|     }, handleError); | ||||
|   }, handleError); | ||||
| 
 | ||||
|   function handleError(error) { | ||||
|     $systemInfoError.textContent = '\n' + error.message; | ||||
|   } | ||||
| })(); | ||||
|  | ||||
| @ -5,14 +5,76 @@ | ||||
|     <title>Пример использования cryptoPro</title> | ||||
| </head> | ||||
| <body> | ||||
|     <select id="certList"></select> | ||||
|     <button id="createSign" type="button">Создать подпись</button> | ||||
|     <button id="showCertificate" type="button">Информация о сертификате</button> | ||||
|     <br> | ||||
|     <pre id="certificateInfo"></pre> | ||||
|     <textarea id="createdSign" cols="100" rows="30"></textarea> | ||||
|     <pre id="errorMessage"></pre> | ||||
|     <pre id="systemInfo"></pre> | ||||
|     <form name="createSignature" novalidate> | ||||
|         <fieldset> | ||||
|             <legend>Создание подписи</legend> | ||||
|             <label for="message">Данные для подиси: *</label> | ||||
|             <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> | ||||
|             </details> | ||||
|             <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="systemInfoError"></pre> | ||||
|         </fieldset> | ||||
|     </form> | ||||
| 
 | ||||
|     <!-- Полифиллы для работы библиотеки --> | ||||
|     <script src="polyfills/promise.js"></script> | ||||
| @ -23,6 +85,7 @@ | ||||
| 
 | ||||
|     <!-- Полифиллы для работы демо скриптов --> | ||||
|     <script src="polyfills/atob-btoa.js"></script> | ||||
|     <script src="polyfills/details-element-polyfill.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 () { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   document | ||||
|     .getElementById('showCertificate') | ||||
|     .addEventListener('click', function () { | ||||
|       var thumbprint = document.getElementById('certList').value; | ||||
|   var $certificate = document.getElementById('certificate'), | ||||
|     $certificateDetails = document.getElementById('certificateDetails'), | ||||
|     $certificateInfo = document.getElementById('certificateInfo'), | ||||
|     $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) { | ||||
|         Promise.all([ | ||||
| @ -24,7 +32,7 @@ | ||||
|           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']), | ||||
|         ]).then(function (results) { | ||||
|           document.getElementById('certificateInfo').textContent = JSON.stringify({ | ||||
|           $certificateInfo.textContent = JSON.stringify({ | ||||
|             name: certificate.name, | ||||
|             issuerName: certificate.issuerName, | ||||
|             subjectName: certificate.subjectName, | ||||
| @ -44,7 +52,16 @@ | ||||
|             '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], | ||||
|           }, 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 строки по отпечатку сертификата | ||||
|  * | ||||
|  * @param thumbprint - отпечаток сертификата | ||||
|  * @param dataBase64 - строковые данные в формате base64 | ||||
|  * @param messageHash - хэш подписываемого сообщения, сгенерированный по ГОСТ Р 34.11 | ||||
|  * @param detachedSignature = true - тип подписи открепленная (true) / присоединенная (false) | ||||
|  * @returns подпись | ||||
|  */ | ||||
| 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 cadesCertificate = await _getCadesCert(thumbprint); | ||||
| 
 | ||||
| @ -52,7 +52,7 @@ export const createSignature = _afterPluginsLoaded( | ||||
|           cadesAuthAttrs = __cadesAsyncToken__ + cadesSigner.AuthenticatedAttributes2; | ||||
|           void (__cadesAsyncToken__ + cadesAuthAttrs.Add(cadesAttrs)); | ||||
|           void (__cadesAsyncToken__ + cadesSignedData.propset_ContentEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY)); | ||||
|           void (__cadesAsyncToken__ + cadesSignedData.propset_Content(dataBase64)); | ||||
|           void (__cadesAsyncToken__ + cadesSignedData.propset_Content(messageHash)); | ||||
|           void ( | ||||
|             __cadesAsyncToken__ + cadesSigner.propset_Options(cadesplugin.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY) | ||||
|           ); | ||||
|  | ||||
| @ -3,4 +3,5 @@ export * from './getUserCertificates'; | ||||
| export * from './getSystemInfo'; | ||||
| export * from './isValidSystemSetup'; | ||||
| export * from './createSignature'; | ||||
| export * from './createHash'; | ||||
| export * from './certificate'; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 vgoma
						vgoma