Closed SwimUp closed 5 months ago
Добрый день.
Воспроизвести пока не получилось.
Для начала следует обновиться на актуальную версию csp, как указанно в документации. В настоящий момент это 5.0.13000, скачать можно с сайта: https://www.cryptopro.ru/products/csp
Так как в примере явно не передаётся открытый ключ для проверки - для проверки происходит поиск по хранилищу с целью найти доверенный сертификат, содержащий открытый ключ. Следует проверить, является ли сертификат, установленный в хранилище доверенным. Альтернативно можно явно передавать открытый ключ сертификата в метод CheckSignature
.
Обновление до 5 версии помогло, метод стал отдавать true. Есть идеи, почему на framework-е CheckSignature true отдает и на 4 версии?
Подписание и проверка на .Net framework 4.7.2 выглядит почти также
public XmlDocument SignXmlFile(XmlDocument doc)
{
SmevSignedXml signedXml = new SmevSignedXml(doc);
signedXml.SigningKey = Certificate.PrivateKey;
Reference reference = new Reference();
reference.Uri = "#body";
reference.DigestMethod = CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3411_2012_256Url;
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(Certificate));
signedXml.KeyInfo = keyInfo;
XmlDsigExcC14NTransform c14 = new XmlDsigExcC14NTransform();
reference.AddTransform(c14);
signedXml.AddReference(reference);
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
signedXml.SignedInfo.SignatureMethod = CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3410_2012_256Url;
signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
doc.DocumentElement.PrependChild(doc.ImportNode(xmlDigitalSignature, true));
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
return doc;
}
public void VerifyXmlFile(XmlDocument xmlDocument)
{
XmlNodeList nodeList = xmlDocument.GetElementsByTagName(
"Signature", SignedXml.XmlDsigNamespaceUrl);
for (int curSignature = 0; curSignature < nodeList.Count; curSignature++)
{
SmevSignedXml signedXml = new SmevSignedXml(xmlDocument);
signedXml.LoadXml((XmlElement)nodeList[curSignature]);
bool result = signedXml.CheckSignature();
Console.WriteLine(result);
}
}
Вот этот же вариант, но уже под LibCore:
Подписание:
public static XmlDocument SignXml(XmlDocument doc, string id, CpX509Certificate2 CpCertificate)
{
CpSignedXml signedXml = new CpSignedXml(doc);
signedXml.SigningKey = CpCertificate.GetGost3410_2012_256PrivateKey();
CpReference reference = new CpReference();
reference.Uri = $"#{id}";
reference.DigestMethod = CpSignedXml.XmlDsigGost3411_2012_256Url;
CpKeyInfo keyInfo = new CpKeyInfo();
keyInfo.AddClause(new CpKeyInfoX509Data(CpCertificate));
signedXml.KeyInfo = keyInfo;
CpXmlDsigExcC14NTransform c14 = new CpXmlDsigExcC14NTransform();
reference.AddTransform(c14);
signedXml.AddReference(reference);
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
signedXml.SignedInfo.SignatureMethod = CpSignedXml.XmlDsigGost3410_2012_256Url;
signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
doc.DocumentElement.PrependChild(doc.ImportNode(xmlDigitalSignature, true));
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
return doc;
}
Валидация:
public static bool ValidateXmlFile(XmlDocument xmlDocument, CpX509Certificate2 cpX509Certificate2)
{
XmlNodeList nodeList = xmlDocument.GetElementsByTagName(
"Signature", SignedXml.XmlDsigNamespaceUrl);
// Проверяем все подписи.
for (int curSignature = 0; curSignature < nodeList.Count; curSignature++)
{
CpSignedXml signedXml = new CpSignedXml(xmlDocument);
signedXml.LoadXml((XmlElement)nodeList[curSignature]);
return signedXml.CheckSignature(cpX509Certificate2, true);
}
return true;
}
Полный код:
using (var store = new CpX509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
var storeCerts = store.Certificates;
var CpCertificate = store.Certificates.Find(X509FindType.FindByThumbprint, "<>", false)[0];
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("out.xml");
var sig = SignXml(xmlDocument, "body", CpCertificate);
File.WriteAllText("out-signed-text.xml", sig.OuterXml, Encoding.UTF8);
var cc = ValidateXmlFile(sig, CpCertificate);
Console.WriteLine(cc);
}
XML на вход:
<?xml version="1.0" encoding="utf-8"?>
<CoordinateTaskMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CoordinateTaskDataMessage Id="body">
<Task>
<MessageId>c9d37a8b-04ae-41f3-b371-8637c3b85f84</MessageId>
</Task>
</CoordinateTaskDataMessage>
</CoordinateTaskMessage>
В итоге - проверка false
берем XML и пробуем завалидировать на сайте
Для корректной работы Libcore требуется последняя актуальная версия csp 5.0, как указанно в документации.
В более старых версиях csp может отсутствовать требуемая функциональность необходима для корректной работы, так как код работы с сертификатами и XML Был полностью переписан, по сравнению с версией КриптоПро.Net для .net Framework.
Добрый день. Пытаюсь подписать XML и проверить её подпись по документации https://dss.cryptopro.ru/libcore/docs/04-%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B/04-03-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-xml-%D0%BF%D0%BE%D0%B4%D0%BF%D0%B8%D1%81%D0%B8.html
Проблема в том, что подписанная хмл не проходит проверку, CheckSignature всегда возвращает false, при этом на сайте https://saas.cryptopro.ru/verifycpca/#/signature подпись проверку проходит.
Спека: .NET 8.0 LibCore 27.06.2024 Windows 10 CryptoPro CSP 4.0
На вход подаю XML
Затем, читаю + подписываю
Методы подписания и проверки просто копипаста с доков.
Проверял способ подписания и проверки на .net framework 4.7.2, непосредственно с либами криптопро - там подпись проверку проходит.