2012-08-01 4 views
7

ich die Methode unten bin mit XML-Dokumente zu unterschreiben:ein XML-Dokument mit RSA-Signaturverfahren SHA256 Ausgabe Signing

public static XmlDocument SignDocument(XmlDocument doc) 
    { 
     string signatureCanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#"; 
     string signatureMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; 
     string digestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256"; 

     string signatureReferenceURI = "#_73e63a41-156d-4fda-a26c-8d79dcade713"; 

     CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), signatureMethod); 

     var signingCertificate = GetCertificate(); 

     SignedXml signer = new SignedXml(doc); 
     signer.SigningKey = signingCertificate.PrivateKey; 
     signer.KeyInfo = new KeyInfo(); 
     signer.KeyInfo.AddClause(new KeyInfoX509Data(signingCertificate)); 

     signer.SignedInfo.CanonicalizationMethod = signatureCanonicalizationMethod; 
     signer.SignedInfo.SignatureMethod = signatureMethod; 

     XmlDsigEnvelopedSignatureTransform envelopeTransform = new XmlDsigEnvelopedSignatureTransform(); 
     XmlDsigExcC14NTransform cn14Transform = new XmlDsigExcC14NTransform(); 

     Reference signatureReference = new Reference(); 
     signatureReference.Uri = signatureReferenceURI; 
     signatureReference.AddTransform(envelopeTransform); 
     signatureReference.AddTransform(cn14Transform); 
     signatureReference.DigestMethod = digestMethod; 

     signer.AddReference(signatureReference); 

     signer.ComputeSignature(); 
     XmlElement signatureElement = signer.GetXml(); 

     doc.DocumentElement.AppendChild(signer.GetXml()); 

     return doc; 
    } 


     private static X509Certificate2 GetCertificate() 
    { 

     X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); 
     store.Open(OpenFlags.ReadOnly); 
     X509Certificate2 card = null; 
     foreach (X509Certificate2 cert in store.Certificates) 
     { 
      if (!cert.HasPrivateKey) continue; 

      if (cert.Thumbprint.Equals("a_certain_thumb_print", StringComparison.OrdinalIgnoreCase)) 
      { 
       card = cert; 
       break; 
      } 
     } 
     store.Close(); 

     return card; 
    } 

Eine Ausnahme vom Typ System.Security.Cryptography.CryptographicException ausgelöst wird, wenn die zu berechnen versucht Signatur mit der Fehlermeldung Ungültiger Algorithmus angegeben. Irgendwelche Ideen?

Maschine: Windows Server 2008 R2

.Net Framework: 4.0.

IDE: Visual Studio 2010.

+4

I wird wie folgt gelöst nicht implementiert dieses Problem (Dank Phillip): /* fügen Sie die folgenden Codezeilen nach var Signing = GetCertificate(); */ CspParameters cspParams = neue CspParameters (24); cspParams.KeyContainerName = "XML_DISG_RSA_KEY"; RSACryptoServiceProvider Schlüssel = neuer RSACryptoServiceProvider (cspParams); key.FromXmlString (signingCertificate.PrivateKey.ToXmlString (true)); /* den Signierschlüssel des Unterzeichners mit dem neuen Schlüssel versehen */ metadataSigner.SigningKey = Schlüssel; – UncleZen

+0

Thx UncleZen, die es behoben, aber cspParams.KeyContainerName = "XML_DISG_RSA_KEY" ist nicht notwendig, es funktioniert auch ohne es. – BitSchupser

Antwort

2

Vielen Dank für diesen Blog. Es hat mein Problem gelöst. Übrigens, wenn das Zertifikat aus der Datei geladen wird, sollte es exportierbar sein: X509Certificate2 x509Key = new X509Certificate2 ("xxxxx.pfx", "123", X509KeyStorageFlags.Exportable);

+0

Dies beantwortet nicht die Frage –

+4

Das beantwortet die Frage nicht, aber nach dem Implementieren von UncleZen-Lösung erhalten Sie den Fehler "Schlüssel nicht gültig für die Verwendung im angegebenen Zustand", wenn der Schlüssel nicht als exportierbar gekennzeichnet war. – BitSchupser

1

Die Antwort von @minhj erwähnt einige Blog, aber der Link ist nicht da.

Durch Hinzufügen der Klasse here und Registrierung wurde das Problem jedoch behoben. Scheint, es sollte nur einmal pro App-Domain registriert werden.