ViArt ,Шваров Евгений Использование MS CryptoAPI в Cache
1. 2. 3. 4. 5.
USER>w ##class(iscapi.Signer).ByteToHex($c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17))
- 000102030405060708090A0B0C0D0E0F1011
- USER>w ##class(%xsd.hexBinary).LogicalToXSD($c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17))
- 000102030405060708090A0B0C0D0E0F1011
- USER>w ##class(iscapi.Signer).HexToString("000102030405060708090A0B0C0D0E0F1011")=##class(%xsd.hexBinary).XSDToLogical("000102030405060708090A0B0C0D0E0F1011")
- 1
- Поэтому я бы заменил/// Преобразование бинарной строки в HEX
- /// TODO: rewrite
- ClassMethod ByteToHex(bString As %String) As %String
- {
- s str = ""
for i=1:1:$l(bString) - {
- s hex = $zhex($ascii($e(bString, i)))
- if ($l(hex) = 1) s hex = "0" _ hex
- s str = str _ hex
-
- }
- q str
- }
-
ClassMethod HexToString(value As %String) As %String
-
- {
- s str = ""
for i=1:2:$l(value) - {
s hex = $e(value, i, i + 1)-
s str = str _ $c($zhex(hex))
-
-
- }
-
- q str
}на/// Преобразование бинарной строки в HEX-
ClassMethod Bin2Hex(binary As %Binary) As %String [ CodeMode = expression ]
-
- {
##class(%xsd.hexBinary).LogicalToXSD(binary)-
- }
-
ClassMethod Hex2Bin(hexValue As %String) As %Binary [ CodeMode = expression ]
-
- {
##class(%xsd.hexBinary).XSDToLogical(hexValue)-
- }
Для большей скорости вместо $ZF(-3) лучше использовать $ZF(-4,1/2)/$ZF(-5) и методы библиотеки правильнее сделать методами экземпляра, а не класса iscapi.Signer.cls/// Функции для работы с крипто-провайдерами через MS CAPI -
Class iscapi.Signer Extends %RegisteredObject
-
- {
-
Parameter DLLInit As INTEGER [ Internal ] = 2;
-
-
Parameter DLLInitLogger As INTEGER [ Internal ] = 3;
-
-
Parameter DLLHashData As INTEGER [ Internal ] = 6;
-
-
Parameter DLLHashFile As INTEGER [ Internal ] = 7;
-
-
Parameter DLLGetHashValue As INTEGER [ Internal ] = 8;
-
-
Parameter DLLSignCurrentHash As INTEGER [ Internal ] = 9;
-
-
Parameter DLLSignNewHash As INTEGER [ Internal ] = 10;
-
-
Parameter DLLVerifyHash As INTEGER [ Internal ] = 11;
-
-
Parameter DLLVerifyHashByKey As INTEGER [ Internal ] = 12;
-
-
Parameter DLLVerifySignature As INTEGER [ Internal ] = 13;
-
-
Parameter DLLExportUserKey As INTEGER [ Internal ] = 14;
-
-
Parameter DLLPrintProviders As INTEGER [ Internal ] = 15;
-
-
Parameter DLLReleaseAll As INTEGER [ Internal ] = 16;
-
-
Property DLLHandle As %Integer [ Private, Transient ];
-
-
/// Инициализация протоколирования.
-
/// <p>
-
/// <var>logFileName</var> - имя файла протокола. Должно быть право на запись.
-
/// <br><var>logLevel</var> - уровень протоколирования
-
/// <ul>
-
/// <li>0 - ничего</li>
-
/// <li>1 - только ошибки</li>
-
/// <li>2 - все сообщения</li>
-
/// </ul>
-
/// <var>logTargets</var> - устройства, в которые нужно писать протокол
-
/// <ul>
-
/// <li>0 - не писать никуда</li>
-
/// <li>1 - писать в файл</li>
-
/// <li>2 - выводить на консоль</li>
-
/// <li>3 - файл и консоль</li></ul>
-
Method %OnNew(
-
logFileName As %String = "c:\iscapi.log",
-
logLevel As %Integer = 2,
-
logTargets As %Integer = 3) As %Status [ Private, ProcedureBlock = 1, ServerOnly = 1 ]
-
- {
s r=$$$OK-
try
- {
s ..DLLHandle=$ZF(-4,1,"ISCAPI.dll")-
d $ZF(-5,..DLLHandle,..#DLLInitLogger, logFileName, logLevel, logTargets)
-
}catch ex
- {
s r = ex.AsStatus() -
-
- }
quit r-
- }
-
/// Освобождение ресурсов и выгрузка DLL
-
Method %OnClose() As %Status [ Private, ProcedureBlock = 1, ServerOnly = 1 ]
-
- {
try{do:..DLLHandle $ZF(-5,..DLLHandle,..#DLLReleaseAll)}catch ex{- }
do:..DLLHandle $ZF(-4,2,..DLLHandle)-
Quit $$$OK
-
- }
-
/// Инициализация крипто-провайдера.
-
/// <p>
-
/// <var>provType</var> - тип провайдера
-
/// <ul>
-
/// <li>VipNet=2</li>
-
/// <li>CryptoPro=75</li>
-
/// </ul>
-
/// <var>algId</var> - используемый алгоритм
-
/// <br><var>containerName</var> - полное имя контейнера с ключами
-
/// <br><var>pin</var> - пароль к контейнеру (если не указан, CSP будет запрашивать его в интерактивном режиме, что не всегда возможно)
-
/// <br><var>providerName</var> - имя крипто-провайдера
-
Method Init(
-
provType = 75,
-
algId = 32798,
-
containerName As %String = "CacheCrypt",
-
pin As %String = "111111",
-
providerName As %String = "Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider") As %Status
-
- {
s r = $$$OK-
try
- {
d $ZF(-5,..DLLHandle,..#DLLInit, provType, algId, containerName, pin, providerName)-
-
- }
catch ex - {
s r = ex.AsStatus()-
-
- }
q r-
- }
-
/// Хеширование порции данных.
-
/// <br>Можно вызывать в цикле для хеширования потока по чанкам, каждая порция данных будет прибавляться к хешу.
-
Method HashData(dataPortion As %String) As %Status
-
- {
s r = $$$OK-
try
- {
d $ZF(-5,..DLLHandle,..#DLLHashData, dataPortion)-
-
- }
catch ex - {
s r = ex.AsStatus()-
-
- }
q r-
- }
-
/// Хеширование файла.
-
Method HashFile(fileName As %String) As %Status
-
- {
s r = $$$OK-
try
- {
d $ZF(-5,..DLLHandle,..#DLLHashFile, fileName)-
-
- }
catch ex - {
s r = ex.AsStatus()-
-
- }
q r-
- }
-
/// Возвращает значение хеша.
-
/// <br>После вызова хеш сохраняется
-
Method GetHashValue() As %String
-
- {
try - {
s r = $ZF(-5,..DLLHandle,..#DLLGetHashValue)-
-
- }
catch ex - {
d ex.DisplayString()-
s r = ""
-
-
- }
q r-
- }
-
Method ExportUserKey() As %String
-
- {
try - {
s r = $ZF(-5,..DLLHandle,..#DLLExportUserKey)-
-
- }
catch ex - {
d ex.DisplayString()-
s r = ""
-
-
- }
q r-
- }
-
/// Экспорт открытого ключа.
-
/// <br>Подпись хеша.
-
Method SignNewHash(dataPortion As %String) As %String
-
- {
try - {
s r = $ZF(-5,..DLLHandle,..#DLLSignNewHash, dataPortion)-
-
- }
catch ex - {
d ex.DisplayString()-
s r = ""
-
-
- }
q r-
- }
-
/// Подпись текущего объекта хеша.
-
Method SignCurrentHash() As %String
-
- {
try - {
s r = $ZF(-5,..DLLHandle,..#DLLSignCurrentHash)-
-
- }
catch ex - {
d ex.DisplayString()-
s r = ""
-
-
- }
q r-
- }
-
/// Проверка подписи хэша.
-
Method VerifyHash(
-
hash As %String,
-
sign As %String) As %Boolean
-
- {
try - {
s r = $ZF(-5,..DLLHandle,..#DLLVerifyHash, hash, sign)-
-
- }
catch ex - {
s r = $$$NO-
-
- }
q r-
- }
-
Method VerifyHashByKey(
-
hash As %String,
-
sign As %String,
-
pubKey As %String) As %Boolean
-
- {
try - {
s r = $ZF(-5,..DLLHandle,..#DLLVerifyHashByKey, hash, sign, pubKey)-
-
- }
catch ex - {
s r = $$$NO-
-
- }
q r-
- }
-
/// Проверка подписи хэша по открытому ключу.
-
/// <br>Проверка подписи данных
-
Method VerifySignature(
-
dataPortion As %String,
-
sign As %String) As %Boolean
-
- {
try - {
s r = $ZF(-5,..DLLHandle,..#DLLVerifySignature, dataPortion, sign)-
-
- }
catch ex - {
s r = $$$NO-
-
- }
q r-
- }
-
Method PrintProviders() As %Status
-
- {
s r = $$$OK-
try
- {
s r = $ZF(-5,..DLLHandle,..#DLLPrintProviders)-
-
- }
catch ex - {
s r = ex.AsStatus()-
-
- }
q r-
- }
-
/// Преобразование бинарной строки в HEX
-
ClassMethod Bin2Hex(binary As %Binary) As %String [ CodeMode = expression ]
-
- {
##class(%xsd.hexBinary).LogicalToXSD(binary)-
- }
-
ClassMethod Hex2Bin(hexValue As %String) As %Binary [ CodeMode = expression ]
-
- {
##class(%xsd.hexBinary).XSDToLogical(hexValue)-
- }
-
/// Тестовый прогон КриптоПро
-
ClassMethod Test()
-
- {
s data = "123!"-
-
s t=..%New("c:\ARTEM\iscapi.log", 2, 1)
-
-
d t.PrintProviders()
-
-
/*
-
Криптопровайдер: Microsoft Base Cryptographic Provider v1.0
-
Тип: 1 - RSA full provider
-
Версия: 2.0
-
Тип реализации: программный
-
Поддерживает алгоритмы:
-
RC2 длина ключа - 40 бит ID: 26114
-
RC4 длина ключа - 40 бит ID: 26625
-
SHA-1 длина ключа - 160 бит ID: 32772
-
MD2 длина ключа - 128 бит ID: 32769
-
MD4 длина ключа - 128 бит ID: 32770
-
MD5 длина ключа - 128 бит ID: 32771
-
SSL3 SHAMD5 длина ключа - 288 бит ID: 32776
-
MAC длина ключа - 64 бит ID: 32773
-
RSA_SIGN длина ключа - 512 бит ID: 9216
-
RSA_KEYX длина ключа - 512 бит ID: 41984
-
HMAC длина ключа - 0 бит ID: 32777
-
*/
-
-
d t.Init(1,32772,,"","Microsoft Base Cryptographic Provider v1.0")
-
-
; или
-
;d t.Init()
-
-
d t.HashData(data)
-
w "Hash created on: ", data, !
-
-
s hash = t.GetHashValue()
-
w "Hash received, hash length=", $l(hash), !
-
w "Hash to base64:", $system.Encryption.Base64Encode(hash), !
-
w "Hash to HEX:", ..Bin2Hex(hash), !
-
w "Hash value:", hash, !
-
-
s sign = t.SignCurrentHash()
-
w "Hash signed, sign length=", $l(sign), !
-
w "Sign to base64:", $system.Encryption.Base64Encode(sign), !
-
-
w "Sign to HEX:", ..Bin2Hex(sign), !
-
w "Verifying Hash signature result = ", t.VerifyHash(hash, sign), !
-
w "Verifying Signature by input text result = ", t.VerifySignature(data, sign), !
-
-
w "Exporting User Key...",!
-
s userKey = t.ExportUserKey()
-
w "Size: ", $l(userKey), !
-
w "UserKeyBytes: ", ..Bin2Hex(userKey), !
-
-
w "Verifying Hash signature ByKey result = ", t.VerifyHashByKey(hash, sign, userKey), !
-
- }
-
}
-
Хорошо бы иметь пример и для стандартных провайдеров (например, Microsoft Base Cryptographic Provider v1.0 ), а не только для GOST, так как не всем он нужен.
-
Чтобы пример выше заработал, пришлось предварительно создать ключи для контейнера (см. Example C Program: Creating a Key Container and Generating Keys )
-
-
-
Если в Caché-терминале выполнить d $ZF(-3,"ISCAPI.dll")
-
d $ZF(-3,"")то файл ISCAPI.dll остаётся заблокированным, пока не закрыть терминал.
-
-
Исходники (COS + C) простого (без Stdafx.cpp) рабочего (без блокирования) примера можно найти здесь: 11597799 и далее.
-
|