Создание XML подписи
static XmlDocument SignXmlFile(
XmlDocument doc,
AsymmetricAlgorithm Key,
CpX509Certificate Certificate,
string DigestMethod = CpSignedXml.XmlDsigGost3411_2012_256Url)
{
// Создаем объект SignedXml по XML документу.
CpSignedXml signedXml = new CpSignedXml(doc);
// Добавляем ключ в SignedXml документ.
signedXml.SigningKey = Key;
// Создаем ссылку на node для подписи.
// При подписи всего документа проставляем "".
CpReference reference = new CpReference();
reference.Uri = "";
// Явно проставляем алгоритм хэширования,
// по умолчанию SHA1.
reference.DigestMethod = DigestMethod;
// Добавляем transform на подписываемые данные
// для удаления вложенной подписи.
CpXmlDsigEnvelopedSignatureTransform env =
new CpXmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Добавляем СМЭВ трансформ.
signedXml.SafeCanonicalizationMethods.Add("urn://smev-gov-ru/xmldsig/transform");
XmlDsigSmevTransform smev =
new XmlDsigSmevTransform();
reference.AddTransform(smev);
// Добавляем transform для канонизации.
CpXmlDsigC14NTransform c14 = new CpXmlDsigC14NTransform();
reference.AddTransform(c14);
// Добавляем ссылку на подписываемые данные
signedXml.AddReference(reference);
// Создаем объект KeyInfo.
CpKeyInfo keyInfo = new CpKeyInfo();
// Добавляем сертификат в KeyInfo
keyInfo.AddClause(new CpKeyInfoX509Data(Certificate));
// Добавляем KeyInfo в SignedXml.
signedXml.KeyInfo = keyInfo;
// Можно явно проставить алгоритм подписи: ГОСТ Р 34.10 2012 256
// Если сертификат ключа подписи ГОСТ Р 34.10 2012 256
// и алгоритм ключа подписи не задан, то будет использован
// XmlDsigGost3410_2012_256Url
// signedXml.SignedInfo.SignatureMethod =
// CPSignedXml.XmlDsigGost3410_2012_256Url;
// Вычисляем подпись.
signedXml.ComputeSignature();
// Получаем XML представление подписи и сохраняем его
// в отдельном node.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Добавляем node подписи в XML документ.
doc.DocumentElement.AppendChild(doc.ImportNode(
xmlDigitalSignature, true));
// При наличии стартовой XML декларации ее удаляем
// (во избежание повторного сохранения)
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
return doc;
}
Проверка XML подписи
static bool ValidateXmlFIle(XmlDocument xmlDocument)
{
// Ищем все node "Signature" и сохраняем их в объекте XmlNodeList
XmlNodeList nodeList = xmlDocument.GetElementsByTagName(
"Signature", CpSignedXml.XmlDsigNamespaceUrl);
// Проверяем все подписи.
bool result = true;
for (int curSignature = 0; curSignature < nodeList.Count; curSignature++)
{
// Создаем объект SignedXml для проверки подписи документа.
CpSignedXml signedXml = new CpSignedXml(xmlDocument);
// добавляем SMEV трансформ
signedXml.SafeCanonicalizationMethods.Add("urn://smev-gov-ru/xmldsig/transform");
// Загружаем узел с подписью.
signedXml.LoadXml((XmlElement)nodeList[curSignature]);
// Проверяем подпись и выводим результат.
result &= signedXml.CheckSignature();
}
return result;
}