Как подписать XML-файл ключом RSA в .NET? - PullRequest
4 голосов
/ 01 декабря 2009

Я пытаюсь подписать XML-файл в C # .NET 3.5 с помощью частного RSA Ключа, сгенерированного OpenSSL .

Вот как я поступил: я преобразовал ключ RSA из формата PEM в формат XML с помощью фреймворка chilkat (www.example-code.com/csharp/cert_usePrivateKeyFromPEM.asp)

С моим ключом XML я теперь могу использовать нативные функции .NET, которые мне больше нравятся. Поэтому я использовал методы, описанные на MSDN .

Итак, в итоге мой исходный код выглядит так:

RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();

//Load the private key from xml file
XmlDocument xmlPrivateKey = new XmlDocument();
xmlPrivateKey.Load("PrivateKey.xml");
rsaProvider.FromXmlString(xmlPrivateKey.InnerXml);

 // Create a SignedXml object.
 SignedXml signedXml = new SignedXml(Doc);

 // Add the key to the SignedXml document.
 signedXml.SigningKey = Key;

 // Create a reference to be signed.
 Reference reference = new Reference();
 reference.Uri = "";

 // Add an enveloped transformation to the reference.
 XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
 reference.AddTransform(env);

 // Add the reference to the SignedXml object.
 signedXml.AddReference(reference);

 // Compute the signature.
 signedXml.ComputeSignature();

 // Get the XML representation of the signature and save
 // it to an XmlElement object.
 XmlElement xmlDigitalSignature = signedXml.GetXml();

 // Append the element to the XML document.
 Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));

Подписанный XML, который я получаю с помощью этой функции, выглядит хорошо, у меня есть элемент XML в конце файла, как это должно быть:

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
  <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
  <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
  <Reference URI="">
    <Transforms>
      <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
    </Transforms>
    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
    <DigestValue>qoGPSbe4oR9e2XKN6MzP+7XlXYI=</DigestValue>
  </Reference>
</SignedInfo>
<SignatureValue>iPQ6IET400CXfchWJcP22p2gK6RpEc9mkSgfoA94fL5UM6+AB5+IO6BbjsNt31q6MB8hR6lAIcnjzHzc5SeXvFP8Py2bqHTYJvcSA6KcKCQl1LiDNt12UwWiKpSkus2p0LdAeeZJNy9aDxjC/blUaZEr4uPFt0kGCD7h1NQM2SY=</SignatureValue>

Проблема в том, что когда я пытаюсь проверить подпись с помощью xmlsec по этому URL: http://www.aleksey.com/xmlsec/xmldsig-verifier.html., я получаю сообщение о том, что подпись недействительна.

Я искал ошибку в своем коде в течение нескольких дней и не могу ее найти. Я начинаю думать, что преобразование из файла PEM в XML может быть проблемой, но я не знаю, как это проверить. Более того, я не нашел другого способа конвертировать в ключ или напрямую использовать файл PEM в .NET.

Кому-нибудь удалось получить действительную подпись в .NET?

Ответы [ 5 ]

2 голосов
/ 01 декабря 2009

Да, мне удалось это сделать. Я думаю, что проблема с вашей ссылкой. URI должен указывать на идентификатор элемента, для которого предназначена подпись. В любом случае, проверьте приведенный ниже код, надеюсь, он направит вас в правильном направлении.

/ Klaus

/// <summary>
    /// Signs an XmlDocument with an xml signature using the signing certificate given as argument to the method.
    /// </summary>
    /// <param name="doc">The XmlDocument to be signed</param>
    /// <param name="id">The is of the topmost element in the xmldocument</param>
    /// <param name="cert">The certificate used to sign the document</param>
    public static void SignDocument(XmlDocument doc, string id, X509Certificate2 cert)
    {
        SignedXml signedXml = new SignedXml(doc);
        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
        signedXml.SigningKey = cert.PrivateKey;

        // Retrieve the value of the "ID" attribute on the root assertion element.
        Reference reference = new Reference("#" + id);

        reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
        reference.AddTransform(new XmlDsigExcC14NTransform());

        signedXml.AddReference(reference);

        // Include the public key of the certificate in the assertion.
        signedXml.KeyInfo = new KeyInfo();
        signedXml.KeyInfo.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.WholeChain));

        signedXml.ComputeSignature();
        // Append the computed signature. The signature must be placed as the sibling of the Issuer element.
        XmlNodeList nodes = doc.DocumentElement.GetElementsByTagName("Issuer", Saml20Constants.ASSERTION);
        // doc.DocumentElement.InsertAfter(doc.ImportNode(signedXml.GetXml(), true), nodes[0]);            
        nodes[0].ParentNode.InsertAfter(doc.ImportNode(signedXml.GetXml(), true), nodes[0]);
    }
1 голос
/ 20 января 2015

У меня была такая же проблема при проверке подписанного XML с помощью XML-Signer. Это было решено, когда я добавил: doc.PreserveWhitespace = False перед загрузкой XML-документа для подписи

Хороший пример можно найти здесь: http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signature(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

1 голос
/ 09 августа 2013

У меня сегодня такая же проблема, один из моих коллег подозревает, что это возможно, потому что .net xml C14 transform не соответствует стандарту XML, который реализован в xmlsec. Я постараюсь выполнить преобразование самостоятельно и сообщу, действительно ли это проблема.

1 голос
/ 08 декабря 2009

Попробуйте заменить

dataObject.Data = Doc.ChildNodes;

с этим:

dataObject.Data = Doc.GetElementsByTagName("YourRootNodeNameHere");
1 голос
/ 01 декабря 2009

Мне кажется, что вы подписываете все что угодно в xml: reference.Uri = "";

Возможно, вы сломаете подпись, когда вставите ее в документ или вставите ее неправильно.

Также помните о пространствах имен и пробелах, некоторые из них также подписаны, что может вызвать проблемы позже при работе с подписанным документом.

...