2009-12-01 2 views
4

J'essaie de signer un fichier XML en C# .NET 3.5 avec un RSA privé Clé générée par OpenSSL.Comment signer un fichier XML avec une clé RSA dans .NET?

Voici comment je continuai: Je me suis converti la clé RSA de PEM le format au format XML en utilisant le cadre chilkat (www.example-code.com/csharp/cert_usePrivateKeyFromPEM.asp)

Avec ma clé XML, je suis maintenant capable d'utiliser les fonctions .NET natives, que je préfère. J'ai donc utilisé les méthodes décrites sur MSDN.

Ainsi, à la fin, mon code source ressemble à ceci:

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)); 

Le XML Signé je reçois avec cette fonction semble OK, j'ai l'élément XML à la fin du fichier, comme il est censé être:

<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> 

le problème est que lorsque je tente de vérifier la signature en utilisant xmlsec à l'adresse suivante: http://www.aleksey.com/xmlsec/xmldsig-verifier.html. Je reçois un message me disant que la signature est invalide.

J'ai cherché l'erreur dans mon code pendant des jours et je ne peux pas trouver. Je commence à penser que la conversion de PEM en fichier XML pourrait être le problème mais je ne sais pas comment le tester. De plus, je n'ai trouvé aucun autre moyen de convertir en clé ou d'utiliser directement le fichier PEM dans .NET.

Est-ce que quelqu'un a réussi à obtenir une signature valide dans .NET?

Répondre

2

Oui, j'ai réussi à le faire. Je pense que le problème est avec votre référence. L'uri doit pointer vers l'identifiant de l'élément pour lequel la signature est destinée. Quoi qu'il en soit, vérifiez le code ci-dessous, espérons qu'il vous indique dans la bonne direction.

/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

Avec les « » vous signes implicites tous les XML si vous utilisez un identifiant vous signe que des pièces de il. –

+0

La signature que je dois faire doit suivre la règle "Seul ce qui est vu doit être signé". J'ai supposé que je devais signer l'ensemble du document, mais j'ai peut-être tort ... Je vais essayer de changer le Uri de la référence. Espérons pleinement qu'il fera l'affaire. –

+0

Comment définissez-vous l'ID de l'élément supérieur? J'ai essayé ceci: // Crée un objet de données pour contenir les données à signer. DataObject dataObject = new DataObject(); dataObject.Data = Doc.ChildNodes; dataObject.Id = "MyObjectId"; // Ajouter l'objet de données à la signature. signedXml.AddObject (dataObject); // Ajouter la clé au document SignedXml. signedXml.SigningKey = Clé; // Créer une référence à signer. Référence de référence = new Référence ("# MyObjectId"); Mais je reçois une exception ... –

1

Il me semble que vous signez le everrything dans le xml: reference.Uri = "";

Purhaps vous casser la signature lorsque vous l'insérez dans le document ou l'insérer dans un mauvais façon.

Soyez également conscient des espaces de noms et des espaces blancs dont certains sont également signés, ce qui peut causer des problèmes plus tard lorsque vous travaillez sur le document signé.

1

Essayez de remplacer

dataObject.Data = Doc.ChildNodes; 

avec ceci:

dataObject.Data = Doc.GetElementsByTagName("YourRootNodeNameHere"); 
1

Je suis le même problème aujourd'hui, l'un de mes collègue soupçonne qu'il est peut-être parce que .net xml C14 transformer n » t suivre la norme XML qui est implémentée dans xmlsec. Je vais essayer de faire la transformation moi-même et vous dire si c'est vraiment le problème.

+0

Eh bien, est-ce le même problème? Veuillez développer votre réponse dans ce cas. –

Questions connexes