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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline ainurwf  
#1 Оставлено : 1 марта 2019 г. 13:35:06(UTC)
ainurwf

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

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

Сказал(а) «Спасибо»: 1 раз
Есть программа, которая подписывает xml и проверяет подпись.
У другой стороны есть требование, чтобы узел Signature и все его подузлы содержали префикс ds.
На просторах интернета был найдет только один способ добавления этого префикса, который по идее должен сделать это до того, как будет вычисляться подпись.
Для этого создается класс CustomSignedXml, наследуемый от SignedXml.
Данный класс вроде как отрабатывает корректно, то есть если подписывать с его помощью не вставляя префикс, подпись проходит проверку.
Но если вставлять префикс, то подпись ломается и не проходит проверку.
Метод подписи файла:
public static void SignXmlFile(string FileName, string SignedFileName, X509Certificate2 Key)
{
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = false;
doc.Load(new XmlTextReader(FileName));
CustomSignedXml signedXml = new CustomSignedXml(doc);
signedXml.SigningKey = Key.PrivateKey;
Reference reference = new Reference();
reference.Uri = "";
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(Key));
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature("ds", Key);
XmlElement xmlDigitalSignature = signedXml.GetXml("ds");
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
using (XmlTextWriter xmltw = new XmlTextWriter(SignedFileName,
new UTF8Encoding(false)))
{
doc.WriteTo(xmltw);
}
}

Наследованный класс для добавления префикса:
internal sealed class CustomSignedXml : SignedXml
{
XmlElement obj = null;
public CustomSignedXml(XmlDocument xml)
: base(xml)
{
}

public CustomSignedXml(XmlElement xmlElement)
: base(xmlElement)
{

}

public XmlElement GetXml(string prefix)
{
XmlElement e = this.GetXml();
SetPrefix(prefix, e);
return e;
}

public void ComputeSignature(string prefix, X509Certificate2 signingKey)
{
this.BuildDigestedReferences();
//AsymmetricAlgorithm signingKey = this.SigningKey;
if (signingKey == null)
{
throw new CryptographicException("Cryptography_Xml_LoadKeyFailed");
}
if (this.SignedInfo.SignatureMethod == null)
{
if (!(signingKey is X509Certificate2))
{
if (!(signingKey is RSA))
{
throw new CryptographicException("Cryptography_Xml_CreatedKeyFailed");
}
if (this.SignedInfo.SignatureMethod == null)
{
this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
}
}
else
{
this.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411";
}
}
SignatureDescription description = CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription;
if (description == null)
{
throw new CryptographicException("Cryptography_Xml_SignatureDescriptionNotCreated");
}
HashAlgorithm hash = description.CreateDigest();
if (hash == null)
{
throw new CryptographicException("Cryptography_Xml_CreateHashAlgorithmFailed");
}
this.GetC14NDigest(hash, prefix);
this.m_signature.SignatureValue = description.CreateFormatter(signingKey.PrivateKey).CreateSignature(hash);
}

private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
{

XmlDocument document = new XmlDocument();
document.PreserveWhitespace = false;
XmlElement e = this.SignedInfo.GetXml();
document.AppendChild(document.ImportNode(e, true));

Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;
SetPrefix(prefix, document.DocumentElement); //Set the prefix before getting the HASH
canonicalizationMethodObject.LoadInput(document);
return canonicalizationMethodObject.GetDigestedOutput(hash);
}

private void BuildDigestedReferences()
{
Type t = typeof(SignedXml);
MethodInfo m = t.GetMethod("BuildDigestedReferences", BindingFlags.NonPublic | BindingFlags.Instance);
m.Invoke(this, new object[] { });
}

private void SetPrefix(string prefix, XmlNode node)
{
foreach (XmlNode n in node.ChildNodes)
SetPrefix(prefix, n);
node.Prefix = prefix;
}
}
Как должна выглядеть подпись (ну она так и выглядит в итоге, только подпись ломается):
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>joBOdsGR/aJnhkVporDTurH1GVk=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
U38R5hnGEiaBo5t/SVdN6QomwxEYHTAYWWV0Op0V071owc6L7EyoLHgj5F57bNI0BGNWMRdQokTl4J5rkfp9Cg==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
...
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
Offline Георгий Садофьев  
#2 Оставлено : 5 марта 2019 г. 14:07:07(UTC)
Георгий Садофьев

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

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

Поблагодарили: 31 раз в 30 постах
Добрый день!

К сожалению, это особенность реализации XMLDSig в .NET Framework.
SignedXml не умеет работать с префиксами, более того, даже если Вы заранее подготовите шаблон с узлом SignedInfo, укажете в нём префиксы, то при выполнении ComputeSignature они будут удалены.

Под "подпись ломается" имеется в виду, что её проверка не проходит? Проверяете через тот же SignedXml?
Если да, то рекомендую включить трассировку XMLDSig, по ней можно посмотреть результаты каноникализации:
https://social.msdn.micr...buglog?forum=xmlandnetfx

Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Георгий Садофьев за этот пост.
ainurwf оставлено 06.03.2019(UTC)
Offline Cnapmak  
#3 Оставлено : 30 апреля 2020 г. 9:21:28(UTC)
Cnapmak

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

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

Сказал(а) «Спасибо»: 1 раз
Привет,
а как тогда подписывать XML, чтобы была подпись с ds: и встроена в сам xml? (нужно подписать весь документ)
Offline Георгий Садофьев  
#4 Оставлено : 30 апреля 2020 г. 11:04:54(UTC)
Георгий Садофьев

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

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

Поблагодарили: 31 раз в 30 постах
Добрый день!

Вы можете воспользоваться COM интерфейсом из КриптоПро ЭЦП SDK:
http://cpdn.cryptopro.ru/default.asp?url=content/cades/class_c_ad_e_s_c_o_m_1_1_signed_x_m_l.html
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Георгий Садофьев за этот пост.
Cnapmak оставлено 30.04.2020(UTC)
Offline Cnapmak  
#5 Оставлено : 30 апреля 2020 г. 15:24:00(UTC)
Cnapmak

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

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

Сказал(а) «Спасибо»: 1 раз
Спасибо за информацию,

По ссылке не нашел подписания xml используя COM, на c++ нашел часть https://cpdn.cryptopro.r...des/samplexadessign.html
там говорится, что полный текст примера см. SDK файл SimplifiedSignVerifyXadesBes.cpp.
скачал SDK там такого примера нет, не могли бы Вы скинуть ссылку для скачивания полного примера подписания XML используя c++ или COM?

Отредактировано пользователем 30 апреля 2020 г. 15:24:33(UTC)  | Причина: Не указана

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