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

Уведомление

Icon
Error

3 Страницы<123>
Опции
К последнему сообщению К первому непрочитанному
Offline Новожилова Елена  
#11 Оставлено : 8 апреля 2013 г. 13:59:32(UTC)
Новожилова Елена

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

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

Поблагодарили: 99 раз в 95 постах
Вот здесь подробно все описано:

http://www.w3.org/TR/2001/REC-xml-c14n-20010315

даже test case есть
thanks 1 пользователь поблагодарил Новожилова Елена за этот пост.
GostyCtypto оставлено 08.04.2013(UTC)
Offline khomenko  
#12 Оставлено : 8 апреля 2013 г. 14:07:52(UTC)
Михаил Хоменко

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

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

Поблагодарили: 15 раз в 14 постах
А если посмотреть как C# канонизирует ?
см. c14n
thanks 1 пользователь поблагодарил Михаил Хоменко за этот пост.
GostyCtypto оставлено 08.04.2013(UTC)
Offline GostyCtypto  
#13 Оставлено : 8 апреля 2013 г. 15:32:51(UTC)
GostyCtypto

Статус: Участник

Группы: Участники
Зарегистрирован: 01.04.2013(UTC)
Сообщений: 17
Мужчина
Российская Федерация
Откуда: ООО &quot;ЦентрПрограммСистем&quot;

Сказал «Спасибо»: 8 раз
Автор: Новожилова Елена Перейти к цитате
Вот здесь подробно все описано:

http://www.w3.org/TR/2001/REC-xml-c14n-20010315

даже test case есть

Спасибо за ссылку, я это читал, но опять таки, не особо понял, что должно получиться в итого в моем случае, ведь, согласно рекомендациям, мне нужно применять канонизация к фрагментам XML...
Или я что-то не так понял и достаточно просто применить канонизация ко всем XML, а потом просто работать с ней?
Кстати, что Вы имеете введу под прецедентом (test case)?



Автор: khomenko Перейти к цитате
А если посмотреть как C# канонизирует ?
см. c14n

Первый раз с канонизацией XML я столкнулся только недавно поэтому про инструментарий позволяющий сделать это в том или ином языке практически ничего не знаю...

В C# я пока нашел только вариант с криптографией:

Я имею введу что и канонизация, и вся остальная механика скрыта в класса SignedXml и посотреть канонизированный XML я просто не знаю как...

На ХэшКод-е ответили (Каноникализация (канонизация) XML), что можно получить канонизированную XML используя код:
Цитата:
#!/usr/bin/perl

use strict;
use XML::LibXML;

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file('1.xml');
print $doc->toStringC14N();


Но я не уверен что это то что нужно, потому что в результате XML меняется совсем немного:
Цитата:
<soapenv:Envelope xmlns:inc="http://www.w3.org/2004/08/xop/include" xmlns:rev="http://smev.gosuslugi.ru/rev120315" xmlns:rq1="http://ws.unisoft/CPSSubsidPercent/Rq1" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.unisoft/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header>
<wsse:Security soapenv:actor="http://smev.gosuslugi.ru/actors/smev">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference URI="#SenderCertificate"></wsse:Reference>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="SenderCertificate"></wsse:BinarySecurityToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body wsu:Id="body">
<ws:async_getId_SendRequest_Tyrim_Pyrim>
<rev:Message>
<rev:Sender>
<rev:Code>CODE63544</rev:Code>
<rev:Name>ТутИмя</rev:Name>
</rev:Sender>
<rev:Recipient>
<rev:Code>CODE2</rev:Code>
<rev:Name>Тест</rev:Name>
</rev:Recipient>
<rev:Originator>
<rev:Code>CODE3</rev:Code>
<rev:Name>Тест</rev:Name>
</rev:Originator>
<rev:ServiceName>ТестВебСервис</rev:ServiceName>
<rev:TypeCode>GSRV</rev:TypeCode>
<rev:Status>REQUEST</rev:Status>
<rev:Date>2012-03-13T12:12:12Z</rev:Date>
<rev:ExchangeType>1</rev:ExchangeType>
<rev:RequestIdRef></rev:RequestIdRef>
<rev:OriginRequestIdRef></rev:OriginRequestIdRef>
<rev:ServiceCode></rev:ServiceCode>
<rev:CaseNumber></rev:CaseNumber>
<rev:TestMsg></rev:TestMsg>
</rev:Message>
<rev:MessageData>
<rev:AppData>
<rq1:Документ UIDЗапроса="4832bdef-bef7-459a-8397-dc28793f59d4" ВерсияФормата="1.0">
<РегНомер>1</РегНомер>
</rq1:Документ>
</rev:AppData>
<rev:AppDocument>
<rev:RequestCode>req_4832bdef-bef7-459a-8397-dc28793f59d4</rev:RequestCode>
<rev:BinaryData>UEsDBBQAAAAIABm=</rev:BinaryData>
</rev:AppDocument>
</rev:MessageData>
</ws:async_getId_SendRequest_Tyrim_Pyrim>
</soapenv:Body>
</soapenv:Envelope>


Этого и в правду достаточно ? d'oh!
Ведь здесь всего лишь сделаны пары для непарных тэгов и упорядочены атрибуты тэгов, где их больше одного...
Вроде бы говорилось что нужно ещё что-то с пространством имен сделать...
Или этого и вправду достаточно ?

PS Пробовал и так
Цитата:
#!/usr/bin/perl

use strict;
use XML::LibXML;

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file('1.xml');
print $doc->toStringEC14N();

Код:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:actor="http://smev.gosuslugi.ru/actors/smev">
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:KeyInfo>
          <wsse:SecurityTokenReference>
            <wsse:Reference URI="#SenderCertificate"></wsse:Reference>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
      <wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="SenderCertificate"></wsse:BinarySecurityToken>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="body">
    <ws:async_getId_SendRequest_Tyrim_Pyrim xmlns:ws="http://ws.unisoft/">
      <rev:Message xmlns:rev="http://smev.gosuslugi.ru/rev120315">
        <rev:Sender>
          <rev:Code>CODE63544</rev:Code>
          <rev:Name>ТутИмя</rev:Name>
        </rev:Sender>
        <rev:Recipient>
          <rev:Code>CODE2</rev:Code>
          <rev:Name>Тест</rev:Name>
        </rev:Recipient>
        <rev:Originator>
          <rev:Code>CODE3</rev:Code>
          <rev:Name>Тест</rev:Name>
        </rev:Originator>
        <rev:ServiceName>ТестВебСервис</rev:ServiceName>
        <rev:TypeCode>GSRV</rev:TypeCode>
        <rev:Status>REQUEST</rev:Status>
        <rev:Date>2012-03-13T12:12:12Z</rev:Date>
        <rev:ExchangeType>1</rev:ExchangeType>
        <rev:RequestIdRef></rev:RequestIdRef>
        <rev:OriginRequestIdRef></rev:OriginRequestIdRef>
        <rev:ServiceCode></rev:ServiceCode>
        <rev:CaseNumber></rev:CaseNumber>
        <rev:TestMsg></rev:TestMsg>
      </rev:Message>
      <rev:MessageData xmlns:rev="http://smev.gosuslugi.ru/rev120315">
        <rev:AppData>
          <rq1:Документ xmlns:rq1="http://ws.unisoft/CPSSubsidPercent/Rq1" UIDЗапроса="4832bdef-bef7-459a-8397-dc28793f59d4" ВерсияФормата="1.0">
            <РегНомер>1</РегНомер>
          </rq1:Документ>
        </rev:AppData>
        <rev:AppDocument>
          <rev:RequestCode>req_4832bdef-bef7-459a-8397-dc28793f59d4</rev:RequestCode>
          <rev:BinaryData>UEsDBBQAAAAIABm=</rev:BinaryData>
        </rev:AppDocument>
      </rev:MessageData>
    </ws:async_getId_SendRequest_Tyrim_Pyrim>
  </soapenv:Body>
</soapenv:Envelope>

Но все равно DigestValue не совпадает... Brick wall

Мне бы хватило и того что бы мне показали как должна выглядеть XML которая у которой DigestValue совпадает с нужным...

Отредактировано пользователем 8 апреля 2013 г. 16:34:43(UTC)  | Причина: добавлено PS

Offline Новожилова Елена  
#14 Оставлено : 9 апреля 2013 г. 19:13:07(UTC)
Новожилова Елена

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

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

Поблагодарили: 99 раз в 95 постах
Цитата:
Спасибо за ссылку, я это читал, но опять таки, не особо понял, что должно получиться в итого в моем случае, ведь, согласно рекомендациям, мне нужно применять канонизация к фрагментам XML...
Или я что-то не так понял и достаточно просто применить канонизация ко всем XML, а потом просто работать с ней?


Вам нужно вычислить хэш-значение не файла целиком, а <soapenv:Body> и его потомков, включая атрибуты.

Цитата:
Но все равно DigestValue не совпадает...
Мне бы хватило и того что бы мне показали как должна выглядеть XML которая у которой DigestValue совпадает с нужным...

Берете нужный узел, при помощи, например, c14n приводите к каноническому виду - хэш-значение должно совпадать.
thanks 1 пользователь поблагодарил Новожилова Елена за этот пост.
GostyCtypto оставлено 11.04.2013(UTC)
Offline GostyCtypto  
#15 Оставлено : 10 апреля 2013 г. 11:31:18(UTC)
GostyCtypto

Статус: Участник

Группы: Участники
Зарегистрирован: 01.04.2013(UTC)
Сообщений: 17
Мужчина
Российская Федерация
Откуда: ООО &quot;ЦентрПрограммСистем&quot;

Сказал «Спасибо»: 8 раз
Цитата:
Берете нужный узел, при помощи, например, c14n приводите к каноническому виду - хэш-значение должно совпадать.

Уже пробовал (взял код второго примера, изменил LoadProducts что бы она возвращала записанную в строку XML для подписи (всю, так как с фрагментом не вышло - ругается на не определенное пространство имен soapenv и т.д.))
Цитата:
var HashedData = ObjCreator("CAdESCOM.HashedData");
HashedData.DataEncoding = CADESCOM_BASE64_TO_BINARY;
HashedData.Algorithm = 100;

HashedData.Hash( Base64.encode('<soapenv:Body wsu:Id="body"><ws:async_getId_SendRequest_Tyrim_Pyrim><rev:Message><rev:Sender><rev:Code>CODE63544</rev:Code><rev:Name>ТутИмя</rev:Name></rev:Sender><rev:Recipient><rev:Code>CODE2</rev:Code><rev:Name>Тест</rev:Name></rev:Recipient><rev:Originator><rev:Code>CODE3</rev:Code><rev:Name>Тест</rev:Name></rev:Originator><rev:ServiceName>ТестВебСервис</rev:ServiceName><rev:TypeCode>GSRV</rev:TypeCode><rev:Status>REQUEST</rev:Status><rev:Date>2012-03-13T12:12:12Z</rev:Date><rev:ExchangeType>1</rev:ExchangeType><rev:RequestIdRef></rev:RequestIdRef><rev:OriginRequestIdRef></rev:OriginRequestIdRef><rev:ServiceCode></rev:ServiceCode><rev:CaseNumber></rev:CaseNumber><rev:TestMsg></rev:TestMsg></rev:Message><rev:MessageData><rev:AppData><rq1:Документ UIDЗапроса="4832bdef-bef7-459a-8397-dc28793f59d4" ВерсияФормата="1.0"><РегНомер>1</РегНомер></rq1:Документ></rev:AppData><rev:AppDocument><rev:RequestCode>req_4832bdef-bef7-459a-8397-dc28793f59d4</rev:RequestCode><rev:BinaryData>UEsDBBQAAAAIABm=</rev:BinaryData></rev:AppDocument></rev:MessageData></ws:async_getId_SendRequest_Tyrim_Pyrim></soapenv:Body>') );

HashedData.Value => "FE93631A13464984BD2BAC4D3DF46D1E1199C2466AD163592EEB98A0762FBB27"

Base64.encode(HashedData.Value, true) => "/pNjGhNGSYS9K6xNPfRtHhGZwkZq0WNZLuuYoHYvuyc=" (это строку HashedData.Value из 64 символа преобразует в массив из 32 байт и работает с ним)
Base64.encode(HashedData.Value) => "RkU5MzYzMUExMzQ2NDk4NEJEMkJBQzREM0RGNDZEMUUxMTk5QzI0NjZBRDE2MzU5MkVFQjk4QTA3NjJGQkIyNw=="

Если меняю в ShowTransformProperties меняю
Цитата:
XmlDsigC14NTransform
на
Цитата:
XmlDsigExcC14NTransform

то
Цитата:
var HashedData = ObjCreator("CAdESCOM.HashedData");
HashedData.DataEncoding = CADESCOM_BASE64_TO_BINARY;
HashedData.Algorithm = 100;

HashedData.Hash( Base64.encode('<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="body"><ws:async_getId_SendRequest_Tyrim_Pyrim xmlns:ws="http://ws.unisoft/"><rev:Message xmlns:rev="http://smev.gosuslugi.ru/rev120315"><rev:Sender><rev:Code>CODE63544</rev:Code><rev:Name>ТутИмя</rev:Name></rev:Sender><rev:Recipient><rev:Code>CODE2</rev:Code><rev:Name>Тест</rev:Name></rev:Recipient><rev:Originator><rev:Code>CODE3</rev:Code><rev:Name>Тест</rev:Name></rev:Originator><rev:ServiceName>ТестВебСервис</rev:ServiceName><rev:TypeCode>GSRV</rev:TypeCode><rev:Status>REQUEST</rev:Status><rev:Date>2012-03-13T12:12:12Z</rev:Date><rev:ExchangeType>1</rev:ExchangeType><rev:RequestIdRef></rev:RequestIdRef><rev:OriginRequestIdRef></rev:OriginRequestIdRef><rev:ServiceCode></rev:ServiceCode><rev:CaseNumber></rev:CaseNumber><rev:TestMsg></rev:TestMsg></rev:Message><rev:MessageData xmlns:rev="http://smev.gosuslugi.ru/rev120315"><rev:AppData><rq1:Документ xmlns:rq1="http://ws.unisoft/CPSSubsidPercent/Rq1" UIDЗапроса="4832bdef-bef7-459a-8397-dc28793f59d4" ВерсияФормата="1.0"><РегНомер>1</РегНомер></rq1:Документ></rev:AppData><rev:AppDocument><rev:RequestCode>req_4832bdef-bef7-459a-8397-dc28793f59d4</rev:RequestCode><rev:BinaryData>UEsDBBQAAAAIABm=</rev:BinaryData></rev:AppDocument></rev:MessageData></ws:async_getId_SendRequest_Tyrim_Pyrim></soapenv:Body>') );

HashedData.Value => "BBA8EC92558050A357A40B5502098BE394075C3D4F233A874344D3CB8240230F"

Base64.encode(HashedData.Value, true) => "u6jsklWAUKNXpAtVAgmL45QHXD1PIzqHQ0TTy4JAIw8=" (это строку HashedData.Value из 64 символа преобразует в массив из 32 байт и работает с ним)
Base64.encode(HashedData.Value) => "QkJBOEVDOTI1NTgwNTBBMzU3QTQwQjU1MDIwOThCRTM5NDA3NUMzRDRGMjMzQTg3NDM0NEQzQ0I4MjQwMjMwRg=="

то есть не совпадает с
Цитата:
M64fZJNYE9Cb4kLc16P40/r+416DTzbJjcibm0voZOo=
это значение устанавливает следующий функция:
Цитата:

void SignXmlFile(string FileName, string SignedFileName, String thumbprint, String pass) {
X509Store certStore = new X509Store(StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadWrite);
X509Certificate2Collection validCerts = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (validCerts.Count == 1) {
X509Certificate2 Certificate = validCerts[0];
System.Xml.XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = false;
doc.Load(new XmlTextReader(FileName));


Gost3410CryptoServiceProvider cert_key = Certificate.PrivateKey as Gost3410CryptoServiceProvider;
if (null != cert_key) {
var cspParameters = new CspParameters();
//копируем параметры csp из исходного контекста сертификата
cspParameters.KeyContainerName = cert_key.CspKeyContainerInfo.KeyContainerName;
cspParameters.ProviderType = cert_key.CspKeyContainerInfo.ProviderType;
cspParameters.ProviderName = cert_key.CspKeyContainerInfo.ProviderName;
cspParameters.Flags = cert_key.CspKeyContainerInfo.MachineKeyStore
? (CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore)
: (CspProviderFlags.UseExistingKey);
cspParameters.KeyPassword = new SecureString();
foreach (var c in pass) {
cspParameters.KeyPassword.AppendChar(c);
}
//задаем криптопровайдер с установленным паролем
Certificate.PrivateKey = new Gost3410CryptoServiceProvider(cspParameters);
}


// Класс с перегруженным GetIdElement для корректной обработки wsu:Id
MySignedXml signedXml = new MySignedXml(doc);
signedXml.SigningKey = Certificate.PrivateKey;
Reference reference = new Reference();
reference.Uri = "#body";

#pragma warning disable 612
//warning CS0612: 'CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3411UrlObsolete' is obsolete
reference.DigestMethod = CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3411UrlObsolete;
#pragma warning restore 612

//XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
//reference.AddTransform(env);
XmlDsigExcC14NTransform c14 = new XmlDsigExcC14NTransform();
reference.AddTransform(c14);
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(Certificate));
signedXml.KeyInfo = keyInfo;
signedXml.SignedInfo.CanonicalizationMethod = c14.Algorithm;

#pragma warning disable 612
//warning CS0612: 'CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3411UrlObsolete' is obsolete
signedXml.SignedInfo.SignatureMethod = CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3410UrlObsolete;
#pragma warning restore 612

signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
doc.GetElementsByTagName("ds:Signature")[0].PrependChild(doc.ImportNode(xmlDigitalSignature.GetElementsByTagName("SignatureValue")[0], true));
doc.GetElementsByTagName("ds:Signature")[0].PrependChild(doc.ImportNode(xmlDigitalSignature.GetElementsByTagName("SignedInfo")[0], true));
doc.GetElementsByTagName("wsse:BinarySecurityToken")[0].InnerText = xmlDigitalSignature.GetElementsByTagName("X509Certificate")[0].InnerText;

//doc.Save(SignedFileName);
using (XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false))) {
doc.WriteTo(xmltw);
}
}
}

Подпись проходит проверку на http://smev.gosuslugi.ru/portal/services-tools.jsp
А с данными на основе приведенного в начале посте кэша - нет d'oh!

Если предположить что хотя бы BinarySecurityToken устанавливается верно
Цитата:
function GetCert(certSubjectName) { // сюда передаётся отпечаток
try {
var oStore = ObjCreator("CAPICOM.store");
oStore.Open();
} catch (err) {
alert('Не удалось создать CAPICOM.store: ' + GetErrorMessage(err));
return;
};
var oCerts = oStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, certSubjectName);
if (oCerts.Count == 0) {
alert("Сертификат не найден");
return;
};
return oStore.Certificates.Item(1).Export(CAPICOM_ENCODE_BASE64);
}

То тогда получается что кэш рассчитывается на правильно, да же если канонизация правильная (или наоборот, не верно канонизируется при правильном расчете кэша).

Кстати, кэш у меня рассчитывается так:
Цитата:
var Base64 = {

// приватное свойство
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// публичный метод кодирования в base64 (если hexToBin = true, то входная строковая запись хеша (шестнадцатеричная строка) перекодируется в последовательность байт)
encode : function (input, hexToBin) {
var output = "";
var bytes, chr1, chr2, chr3, enc1, enc2, enc3, enc4;

input = Base64._utf8_encode(input);
if (hexToBin) bytes = Base64.hexToBin(input);

var i = 0;
while ((hexToBin && (i < bytes.length)) || (!hexToBin && (i < input.length))) {

if (hexToBin) {
chr1 = bytes[i++];
chr2 = bytes[i++];
chr3 = bytes[i++];
} else {
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 += this._keyStr.charAt(enc1) +
this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) +
this._keyStr.charAt(enc4);

}

return output;
},

// публичный метод декодирования из base64 (если hexToBin = true, то результат (из последовательности байт) перекодируется в строковую запись (шестнадцатеричная строка))
decode : function (input, binToHex) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;

input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

while (i < input.length) {

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;

if (binToHex) {
output += Base64.binToHex( [chr1, chr2, chr3] );
} else {
output += String.fromCharCode(chr1);

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

}

output = Base64._utf8_decode(output);

return output.toUpperCase();

},

// публичный метод перекодирования строковой записи хеша (шестнадцатеричной строки без разделителей) в последовательность байт (массив)
hexToBin : function (input) {
var bytes = [];
for (var i = 0, l = input.length; i < l; i += 2) {
bytes.push( parseInt( input.substr(i, 2), 16 ) );
};
return bytes;
},

// публичный метод перекодирования последовательности байт (массива) в строковую запись хеша (шестнадцатеричную строку без разделителей)
binToHex : function (input) {
var str = "", s;
for (var i = 0, l = input.length; i < l; i++) {
s = input[i].toString(16);
str += (s.length == 1 ? "0" : "") + s;
};
return str;
},

// припатный метод для кодирования UTF-8
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";

for (var n = 0; n < string.length; n++) {

var c = string.charCodeAt(n);

if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}

}

return utftext;
},

// приватный метод для декодирования UTF-8
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;

while ( i < utftext.length ) {

c = utftext.charCodeAt(i);

if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}

}

return string;
}

}

Если нужна другая функция Base64, то пожалуйста подскажите какая...

Отредактировано пользователем 10 апреля 2013 г. 11:34:32(UTC)  | Причина: Не указана

Offline GostyCtypto  
#16 Оставлено : 10 апреля 2013 г. 14:45:39(UTC)
GostyCtypto

Статус: Участник

Группы: Участники
Зарегистрирован: 01.04.2013(UTC)
Сообщений: 17
Мужчина
Российская Федерация
Откуда: ООО &quot;ЦентрПрограммСистем&quot;

Сказал «Спасибо»: 8 раз
Почему я так зациклился на подписывании XML для СМЭВ JS через плагин, - потому что наши клиенты использует КриптоПро ЭЦП, он им привычнее.
А если предоставлять им возможность подписывания XML для СМЭВ через, скажем службу (по средствам http запроса, или ещё как-то) на C# (просто разобраться с подписью XML для СМЭВ может уйти много времени), то это потребует от них приобретения КриптоПро .NET, что не есть хорошо.
Offline GostyCtypto  
#17 Оставлено : 10 апреля 2013 г. 16:07:46(UTC)
GostyCtypto

Статус: Участник

Группы: Участники
Зарегистрирован: 01.04.2013(UTC)
Сообщений: 17
Мужчина
Российская Федерация
Откуда: ООО &quot;ЦентрПрограммСистем&quot;

Сказал «Спасибо»: 8 раз
Кажется не тот бубен использовал...

Достаточно было взять пространства имен из Envelope используемое внутри Body ручками подставить в Body, и только потом Body (записанный в строку) скормить c14n.
В этом случае кэш действительно совпадает Dancing Уф-ф-ф-ф...
Offline GostyCtypto  
#18 Оставлено : 11 апреля 2013 г. 8:34:49(UTC)
GostyCtypto

Статус: Участник

Группы: Участники
Зарегистрирован: 01.04.2013(UTC)
Сообщений: 17
Мужчина
Российская Федерация
Откуда: ООО &quot;ЦентрПрограммСистем&quot;

Сказал «Спасибо»: 8 раз
Не смотря на то что кэш побежден ЭП не проходит проверки в Инструментах разработки сервисов Гос.Услуг...

Автор: Новожилова Елена Перейти к цитате
1. Да, BinarySecurityToken должен содержать сертификат, закодированный в BASE64. В вашем первом сообщении вы пытаетесь вместо сертификата записать значение CMS-сообщения. Так делать не нужно. Используйте Certificate.Export(CAPICOM_ENCODE_BASE64).

3. Да, но нужно помнить, что значение цифровой подписи по ГОСТ Р 34.10 - случайно. Не следует здесь ждать совпадения значения подписи с полученным на C#. Даже на C# оно каждый раз будет разным.




Заметил что формируемый BinarySecurityToken на C# имеет длину 3056, а тот что я получаю 1224. Я получаю его так (3):
Цитата:
function GetCert(certSubjectName) {
try {
var oStore = ObjCreator("CAPICOM.store");
oStore.Open();
} catch (err) {
alert('Не удалось создать CAPICOM.store: ' + GetErrorMessage(err));
return;
};
var oCerts = oStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, certSubjectName);
if (oCerts.Count == 0) {
alert("Сертификат не найден");
return;
};
return oStore.Certificates.Item(1).Export(CAPICOM_ENCODE_BASE64);
}

Получается всегда одна и та же строка... Поэтому у меня есть подозрение что я делаю тут что-то не правильно...
Потому что при подписи через C# строка каждый раз разная...
Подозревая что с экспортируемым сертификатом нужно сделать ещё что-то...
Либо получать данные как-то иначе...

В рекомендациях говорится что в <wsse:BinarySecurityToken/> добавляются атрибуты форматов и собственно сам сертификат и атрибут wsu:Id.
Формат сертификата должен соответствовать спецификации X.509 и быть представленным в формате Base64
.

Кажется, что если я и получаю сертификат, то не X.509.



Подпись я формирую так (1):
Код:
function GetSign(certSubjectName, dataToSign) {
    try {
        var oHashedData = ObjCreator("CAdESCOM.HashedData");
        oHashedData.DataEncoding = CADESCOM_BASE64_TO_BINARY;
        oHashedData.Algorithm = 100;
        oHashedData.Hash( Base64.encode(dataToSign) );
        //oHashedData.Hash( dataToSign );
    } catch (err) {
        alert('Не удалось создать CAPICOM.HashedData: ' + GetErrorMessage(err));
        return;
    }
    try {
        var oStore = ObjCreator("CAPICOM.store");
        oStore.Open();
    } catch (err) {
        alert('Не удалось создать CAPICOM.store: ' + GetErrorMessage(err));
        return;
    }; 
    var oCerts = oStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, certSubjectName);
    if (oCerts.Count == 0) {
        alert("Сертификат не найден");
        return;
    };
    var oCert = oCerts.Item(1);
    try {
        var oRawSignature = ObjCreator("CAdESCOM.RawSignature");        
    } catch (err) {
        alert('Не удалось создать CAdESCOM.RawSignature: ' + GetErrorMessage(err));
        return;
    };
    if (oRawSignature) {
        return oRawSignature.SignHash(oHashedData, oCert);
    } else {
        alert("Не удалось создать RawSignature!");
        return;
    }
}

И если оставляю BinarySecurityToken тот что получается на C#, а подпись использую свою, то проверка так же не проходит как бы я не канонизировал SignedInfo.

В рекомендациях говорится что к элементу <ds:SignedInfo> и его потомкам, включая атрибуты, применяется каноникализация http://www.w3.org/2001/10/xml-exc-c14n#, на основе результата рассчитывается электронная подпись по алгоритму ГОСТ Р 34.11-2001 и заносится в <ds:SignatureValue> в формате Base64.


Возможно я то-то не правильно понял и функции написаны верно, тогда в чем может быть проблема ?


PS В свойствах ключа написано:
Цитата:
Алгоритм подписи: ГОСТ Р 34.11/34.10-2001
Алгоритм хэширования подписи: ГОСТ Р 34.11-94
Открытый ключ: ГОСТ Р 34.10-2001 (512 Bit)
Алгоритм отпечатка: sha1

Отредактировано пользователем 11 апреля 2013 г. 10:41:31(UTC)  | Причина: Не указана

Offline GostyCtypto  
#19 Оставлено : 12 апреля 2013 г. 7:10:44(UTC)
GostyCtypto

Статус: Участник

Группы: Участники
Зарегистрирован: 01.04.2013(UTC)
Сообщений: 17
Мужчина
Российская Федерация
Откуда: ООО &quot;ЦентрПрограммСистем&quot;

Сказал «Спасибо»: 8 раз
Сутки прошли, а ответа нет...
То ли ни кто не подписывал XML для СМЭВ, то ли ни кто не хочет помочь...

Что же, надеюсь, что в скором времени появится запить в блоге на подобии "Подпись сообщений SOAP для СМЭВ с использованием КриптоПро .NET" или "Подпись сообщений SOAP для СМЭВ с использованием КриптоПро JCP".

Думаю, что не малому бы числу людей было бы полезно...
А пока я не уверен что так уж много людей вообще знают про КриптоПро ЭЦП Browser plug-in, если судить по числу людей задающих вопросы в темах про него.
Offline alex33  
#20 Оставлено : 16 апреля 2013 г. 17:54:29(UTC)
alex33

Статус: Участник

Группы: Участники
Зарегистрирован: 15.10.2012(UTC)
Сообщений: 11
Откуда: msc

Сказал(а) «Спасибо»: 1 раз
На самом деле, подпись в формате СМЭВ, через browser plugin тема крайне актуальная.
Сейчас приходится морочиться или c COM, но это только IE, либо Java-апплет, ну или "свои" плагины для браузеров.
Хотелось бы, конечно, готовое решение.

Присоединяюсь к вопросу GostyCtypto и слежу за темой.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (2)
3 Страницы<123>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.