Статус: Новичок
Группы: Участники
Зарегистрирован: 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>
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 14.10.2011(UTC) Сообщений: 144 Поблагодарили: 31 раз в 30 постах
|
Добрый день! К сожалению, это особенность реализации XMLDSig в .NET Framework. SignedXml не умеет работать с префиксами, более того, даже если Вы заранее подготовите шаблон с узлом SignedInfo, укажете в нём префиксы, то при выполнении ComputeSignature они будут удалены. Под "подпись ломается" имеется в виду, что её проверка не проходит? Проверяете через тот же SignedXml? Если да, то рекомендую включить трассировку XMLDSig, по ней можно посмотреть результаты каноникализации: https://social.msdn.micr...buglog?forum=xmlandnetfx |
|
1 пользователь поблагодарил Георгий Садофьев за этот пост.
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 29.04.2020(UTC) Сообщений: 2 Откуда: Пермь Сказал(а) «Спасибо»: 1 раз
|
Привет, а как тогда подписывать XML, чтобы была подпись с ds: и встроена в сам xml? (нужно подписать весь документ)
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 14.10.2011(UTC) Сообщений: 144 Поблагодарили: 31 раз в 30 постах
|
|
|
1 пользователь поблагодарил Георгий Садофьев за этот пост.
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 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)
| Причина: Не указана
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close