Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

3 Страницы123>
Опции
К последнему сообщению К первому непрочитанному
Offline srubtsov59  
#1 Оставлено : 27 мая 2013 г. 13:00:34(UTC)
srubtsov59

Статус: Новичок

Группы: Участники
Зарегистрирован: 24.05.2013(UTC)
Сообщений: 6
Российская Федерация
Откуда: Москва

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 1 раз в 1 постах
Коллеги! Неприятность следующая...

Мне дан внешний веб-сервис заказчика для проверки подписи xmldsig.
Подпись созданная на С# известными средствами CryptoPro.Sharpei и System.Security.Cryptography.Xml.signedXml замечательно и без проблем проходит проверку на этом сервисе.
Я попробовал проделать то же ..., но с Browser plug-in и методом CAdESCOM.RawSignature.SignHash для вычисления тега <ds:SignatureValue> по значению тега <ds:SignedInfo>.
Значение тега <ds:DigestValue> получалось то же, что и в C#, подтверждает правильность пользования мною методом oHashedData.Hash...

К сожалению, все попытки проверить xmldsig потерпели неудачу...
Есть ощущение, что неправильно обрабатываю выход oRawSignature.SignHash...
Делаю простую вещь:

var s = oRawSignature.SignHash(oHashedData, oCertificate);
s = hex2bin(s);
s = Base64.encode(s);
return s;

Очень смущает информация о том, что oRawSignature.SignHash для ключей ГОСТ Р 34.10-2001 возвращается как описано в разделе 2.2.2 RFC 4491 (http://tools.ietf.org/html/rfc4491#section-2.2.2), но в обратном порядке байт...

Короче говоря, буду признателен, если кто-нибудь поможет сократить мой долгий путь к истине...
С ув.РСВ
Offline Новожилова Елена  
#2 Оставлено : 28 мая 2013 г. 12:59:12(UTC)
Новожилова Елена

Статус: Сотрудник

Группы: Администраторы, Участники
Зарегистрирован: 10.12.2008(UTC)
Сообщений: 924
Женщина
Откуда: Крипто-Про

Поблагодарили: 99 раз в 95 постах
http://tools.ietf.org/ht...cpxmldsig-07#section-6.3

GOST R 34.10-2001 signature is a 64-octet value as described in section 2.2.2 of CPPK ( = RFC4491 ).
The content of the dsig:SignatureValue element shall be the base64 encoding of this value.

Перед тем, как кодировать подпись в BASE64, вам ее нужно перевернуть.
thanks 1 пользователь поблагодарил Новожилова Елена за этот пост.
srubtsov59 оставлено 28.05.2013(UTC)
Offline srubtsov59  
#3 Оставлено : 28 мая 2013 г. 16:51:33(UTC)
srubtsov59

Статус: Новичок

Группы: Участники
Зарегистрирован: 24.05.2013(UTC)
Сообщений: 6
Российская Федерация
Откуда: Москва

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 1 раз в 1 постах
Спасибо за рекомендацию.
Я пробовал несколько вариантов "переворачивания" подписи, начиная от самого простого:

oHashedData.DataEncoding = CADESCOM_BASE64_TO_BINARY;
oHashedData.Hash(Base64.encode(dataToSign));
//
var s = oRawSignature.SignHash(oHashedData, oCertificate);
//
s = reverseStr(s);
s = hex2bin(s);
s = Base64.encode(s, true);
//s = "7Y00w/Dg0G6RThvuips/GgW8J0rXpYFLlxk17hzMiuyzSAZSqWCKZ1uGGENIWr5PTL28pX4FkpeNMe6FXlS+5A=="; //правильная подпись из C#

где

function reverseStr(str) {
var newStr = '', i;
for (i = str.length - 1; i >= 0; i--) {
newStr += str.charAt(i);
}
return newStr;
}

function hex2bin(hex)
{
var bytes = [], str;
for(var i=0; i< hex.length-1; i+=2)
bytes.push(parseInt(hex.substr(i, 2), 16));
return String.fromCharCode.apply(String, bytes);
}

Не проходит подпись. Подставляю вместо нее подпись, получаемую в С#, все проходит на ура...

К сожалению, метод oRawSignature.SignHash не байты или биты возвращает, а строку шестнадцатеричных цифр, группами по две цифры на байт...
Если же обратиться к источнику http://tools.ietf.org/html/rfc4491#section-2.2.2, то можно прочитать, что "переворачиваться" должна не подпись, не байты, а биты в пределах бинарной строки... И, так тоже пробовал. Не помогает.

Отредактировано пользователем 29 мая 2013 г. 14:42:36(UTC)  | Причина: Не указана

С ув.РСВ
Offline srubtsov59  
#4 Оставлено : 29 мая 2013 г. 17:26:44(UTC)
srubtsov59

Статус: Новичок

Группы: Участники
Зарегистрирован: 24.05.2013(UTC)
Сообщений: 6
Российская Федерация
Откуда: Москва

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 1 раз в 1 постах
Все ... вопрос снимается.
Проблема была в голове, а именно - в неправильной каноникализации подписываемого сообщения
С ув.РСВ
Offline allmic  
#5 Оставлено : 25 июня 2013 г. 14:23:29(UTC)
allmic

Статус: Новичок

Группы: Участники
Зарегистрирован: 25.06.2013(UTC)
Сообщений: 2

Сказал(а) «Спасибо»: 1 раз
Добрый день, у меня видимо аналогичная проблема.
Формирование подписи сообщение на сервере силами C# проходит успешно.
Но мне необходимо организовать подпись сообщения на клиенте.
Привожу сообщение к каноничному виду и расчитываю digestValue на клиенте от body сообщение - хэш совпадает с аналогичным расчитанным с помощью c#, т.е. проблем с хэш обектом нету.
Далее с помощью RawSignature пытаюсь сформировать подпись хэша от элемента SignedInfo.
Полученное значение подписи перевожу в бинарный вид, переворачиваю и кодирую в base64. Но подпись не проходит проверку.
Соответствеено если взять аналогичную подпись сформированную на сервере с помощью c#, то сообщение проходит проверку.
Подскажите пожалуйста какие именно преобразования нужно произветсти с результатом RawSignature.SignHash?
Offline srubtsov59  
#6 Оставлено : 26 июня 2013 г. 8:00:57(UTC)
srubtsov59

Статус: Новичок

Группы: Участники
Зарегистрирован: 24.05.2013(UTC)
Сообщений: 6
Российская Федерация
Откуда: Москва

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 1 раз в 1 постах
function GetSignatureValue(dataToSign) {
if (oRawSignature) {
try {
dataToSign = Base64._utf8_encode(dataToSign);
oHashedData.Hash(Base64.encode(dataToSign, false));
var hex = oRawSignature.SignHash(oHashedData, oCertificate); //возвращает подпись в виде строки шестнадцатеричных цифр группами по две цифры на байт, разделённых пробелами
var bin = hex2bin(hex);
bin = reverseStr(bin);
s = Base64.encode(bin, false);
return s;
} catch (err) {
alert('Не удалось создать подпись!: ' + GetErrorMessage(err));
return "";
}
} else {
alert("Объект RawSignature не определен!");
return "";
}
}

Если проверка не проходит, то причина в коникализации (служебные символы и т.п. и т.д.)
С ув.РСВ
thanks 1 пользователь поблагодарил srubtsov59 за этот пост.
allmic оставлено 27.06.2013(UTC)
Offline allmic  
#7 Оставлено : 27 июня 2013 г. 13:42:03(UTC)
allmic

Статус: Новичок

Группы: Участники
Зарегистрирован: 25.06.2013(UTC)
Сообщений: 2

Сказал(а) «Спасибо»: 1 раз
srubtsov59 спасибо за ответ.
Упоминание _utf8_encode натолкнуло меня на решение проблемы с хэшом.( у меня была ещё проблема в том что от одинаковых данных хэш c помощью плагина и на сервере с помощью c# получался разным. Но если перед вычислением хэша на клиенте закодировать данные в utf8 то проблем нет. Но мне непонятно зачем все таки это нужно т.к. сама страница в кодировке utf8. Причем если данные корректно отображаются при дебаге, то после применения _utf8_encode отображается нечитаемая таробарщина вместо русских символов но хэш от этих данных считается правильный.
С подписью в итоге все таки была проблема с некорректной канонизацией. В итоге получилось сформировать корректную подпись. Спасибо.
Offline dmishin  
#8 Оставлено : 5 июля 2013 г. 8:00:54(UTC)
dmishin

Статус: Активный участник

Группы: Участники
Зарегистрирован: 07.08.2012(UTC)
Сообщений: 123

Сказал(а) «Спасибо»: 4 раз
Поблагодарили: 6 раз в 6 постах
Добрый день,

Самостоятельные попытки привести подпись XML к валидному виду не увенчались успехом.
Не подскажите корректен ли алгоритм:

Беру шаблон подписи:
Цитата:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
<DigestValue/>
</Reference>
</SignedInfo>
<SignatureValue/>
<KeyInfo>
<X509Data/>
</KeyInfo>
</Signature>



Функции для конвертации в javascript:

Цитата:

reverse: function(str) {
var newStr = '', i;
for (i = str.length - 1; i >= 0; i--) {
newStr += str.charAt(i);
}
return newStr;


},

hex : {
d2h : function(d) {
res = d.toString(16).toUpperCase();

if (res.length == 1) {
res = '0' + res;
}

return res;
},

h2d : function (h) {
return parseInt(h, 16);
},

stringToHex : function (string) {
var hex = '';

for (var i = 0; i < string.length; i++) {
hex += this.d2h(string.charCodeAt(i));
}

return hex;
},

hexToString : function (hex) {
string = '';

for (var b = 0; b < hex.length; b += 2) {
string += String.fromCharCode(parseInt(hex.substr(b, 2), 16));
}

return string;
}
},

base64 : {
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;

do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);

enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;

if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}

output = output +
this._keyStr.charAt(enc1) +
this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) +
this._keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);

return output;
},

// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;

var base64test = /[^A-Za-z0-9\+\/\=]/g;
if (base64test.exec(input)) {
return null;
}

do {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));

chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;

output = output + String.fromCharCode(chr1);

if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}

chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";

} while (i < input.length);

return output;
}
}

1. Беру хэш канонизированной XML. Вставляю его в шаблон в качестве DigestValue.
Например: e5bsMmsv+qWG1oY3mW9vbeBp1sbAH+Z9KtRKnm10ZzI=
2. Использую полученный хеш для создания подписи (замечу что преобразований к UTF8 нигде не производится):

Цитата:

hashObject.SetHashValue(hex.stringToHex(base64.decode(base64Hash));
var hex = rawSignature.SignHash(hashObject, certificate);


Результат: A5BDC9CD1A50DD982725E36A8D62237712A8AECBEEF0AD0BE34BB04C50EEE0707D2EA984695FA3B45264A2BA04F2CA59501BBC23164BF4A2E2B91562A79FA589

3. Переворачиваю строку
Цитата:
reverse(hex.hexToString(hex))


Результат в хексе:
89A59FA76215B9E2A2F44B1623BC1B5059CAF204BAA26452B4A35F6984A92E7D70E0EE504CB04BE30BADF0EECBAEA8127723628D6AE3252798DD501ACDC9BDA5

4. Беру base64 от перевернутой строки и подставляю в SignatureValue.
Base64: iaWfp2IVueKi9EsWI7wbUFnK8gS6omRStKNfaYSpLn1w4O5QTLBL4wut8O7LrqgSdyNijWrjJSeY3VAazcm9pQ==

5. Добавляю в X509Data блок <X509Certificate> с сертификатом, который использовался для подписи.

6. Проверяю полученную XML утилитой xmlsec1.

В результате ошибка при проверке: EVP_VerifyFinal:error=18:data do not match:signature do not match

Отредактировано пользователем 5 июля 2013 г. 9:43:07(UTC)  | Причина: Не указана

Offline srubtsov59  
#9 Оставлено : 5 июля 2013 г. 8:20:39(UTC)
srubtsov59

Статус: Новичок

Группы: Участники
Зарегистрирован: 24.05.2013(UTC)
Сообщений: 6
Российская Федерация
Откуда: Москва

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 1 раз в 1 постах
Добрый день!
Во всем написанном я не разбирался, но п. 3 сразу "глаз колет". Нужно "втупую по символам" инвертировать строку, а не по байтам...

Отредактировано пользователем 5 июля 2013 г. 8:21:33(UTC)  | Причина: Не указана

С ув.РСВ
Offline dmishin  
#10 Оставлено : 5 июля 2013 г. 8:43:35(UTC)
dmishin

Статус: Активный участник

Группы: Участники
Зарегистрирован: 07.08.2012(UTC)
Сообщений: 123

Сказал(а) «Спасибо»: 4 раз
Поблагодарили: 6 раз в 6 постах
Да, поправился - переворачиваю строку. И Base64 беру от перевернутой строки
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
3 Страницы123>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.