2014-04-30 17 views
9

Za każdym razem, gdy próbuję wysłać podpisany XML, weryfikator usług sieciowych odrzuca go.podpisywanie dokumentu xml z certyfikatem x509

Aby podpisać dokument Właśnie dostosowany ten przykładowy kod dostarczony przez Microsoft:

http://msdn.microsoft.com/es-es/library/ms229745(v=vs.110).aspx

Moje wykonanie:

public static XmlDocument FirmarXML(XmlDocument xmlDoc) 
    { 
     try 
     { 
      X509Certificate2 myCert = null; 
      var store = new X509Store(StoreLocation.CurrentUser); //StoreLocation.LocalMachine fails too 
      store.Open(OpenFlags.ReadOnly); 
      var certificates = store.Certificates; 
      foreach (var certificate in certificates) 
      { 
       if (certificate.Subject.Contains("xxx")) 
       { 
        myCert = certificate; 
        break; 
       } 
      } 

      if (myCert != null) 
      { 
       RSA rsaKey = ((RSA)myCert.PrivateKey); 

       // Sign the XML document. 
       SignXml(xmlDoc, rsaKey);      
      } 

     } 
     catch (Exception e) 
     { 
      MessageBox.Show(e.Message); 
     } 
     return xmlDoc; 
    } 


    // Sign an XML file. 
    // This document cannot be verified unless the verifying 
    // code has the key with which it was signed. 
    public static void SignXml(XmlDocument xmlDoc, RSA Key) 
    { 
     // Check arguments. 
     if (xmlDoc == null) 
      throw new ArgumentException("xmlDoc"); 
     if (Key == null) 
      throw new ArgumentException("Key"); 

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

     // 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. 
     xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true)); 

    } 

myślę ja wykonując te same czynności przy użyciu mój własny certyfikat, jednak nie działa zgodnie z oczekiwaniami.

Wszelkie sugestie będą mile widziane.

Odpowiedz

8

W jaki sposób serwer wie, z jakiego certyfikatu podpisano dokument? Wydaje się, aby nie obejmować cert w podpisanym dokumencie:

KeyInfo keyInfo = new KeyInfo(); 
    KeyInfoX509Data keyInfoData = new KeyInfoX509Data(Key); 
    keyInfo.AddClause(keyInfoData); 
    signedXml.KeyInfo = keyInfo; 

Jeśli potrzebujesz więcej szczegółów, skontaktuj się moja notka

http://www.wiktorzychla.com/2012/12/interoperable-xml-digital-signatures-c_20.html

+0

Witam Wiktor, twój blog był bardzo interesujący i użyłem próbek, które pokazujesz do przetestowania. Niestety nadal mam ten sam problem, podpis jest odrzucany. Zamieszczę więcej informacji poniżej. –

3

już kilka zmian następujących próbek Wiktora. Jednak podpis nadal odrzucony przez serwis internetowy.

Sposób używam podpisać teraz to:

public static string SignXml(XmlDocument Document, X509Certificate2 cert) 
{ 
    SignedXml signedXml = new SignedXml(Document); 
    signedXml.SigningKey = cert.PrivateKey; 

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

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

    //canonicalize 
    XmlDsigC14NTransform c14t = new XmlDsigC14NTransform(); 
    reference.AddTransform(c14t); 

    KeyInfo keyInfo = new KeyInfo(); 
    KeyInfoX509Data keyInfoData = new KeyInfoX509Data(cert); 
    KeyInfoName kin = new KeyInfoName(); 
    kin.Value = "Public key of certificate"; 
    RSACryptoServiceProvider rsaprovider = (RSACryptoServiceProvider)cert.PublicKey.Key; 
    RSAKeyValue rkv = new RSAKeyValue(rsaprovider); 
    keyInfo.AddClause(kin); 
    keyInfo.AddClause(rkv); 
    keyInfo.AddClause(keyInfoData); 
    signedXml.KeyInfo = keyInfo; 

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

    Document.DocumentElement.AppendChild(
     Document.ImportNode(xmlDigitalSignature, true)); 

    return Document.OuterXml; 
} 

oraz podpis wygląda jak ten w dokumencie:

<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" /> 
       <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /> 
      </Transforms> 
      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> 
      <DigestValue>zRSPtja5EtX7hVbyJ11EjoYTRDk=</DigestValue> 
     </Reference> 
    </SignedInfo> 
    <SignatureValue>Ua1/WP28WzfXaxUj....</SignatureValue> 
    <KeyInfo> 
     <KeyName>Public key of certificate</KeyName> 
     <KeyValue> 
      <RSAKeyValue> 
       <Modulus>0mmCc5Rlibh44o/C/k5....</Modulus> 
       <Exponent>AQAB</Exponent> 
      </RSAKeyValue> 
     </KeyValue> 
     <X509Data> 
      <X509Certificate>MIIF3jCCBUegAwIBAgIEPQa1....</X509Certificate> 
     </X509Data> 
    </KeyInfo> 
</Signature> 

Gdy prawo dokument jest wysyłany do serwera, to zwraca Podpis ten użyłem jako tupu do zidentyfikowania niezbędnych pól:

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
    <ds:SignedInfo> 
     <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /> 
     <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> 
     <ds:Reference URI=""> 
      <ds:Transforms> 
       <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> 
       <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /> 
      </ds:Transforms> 
      <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> 
      <ds:DigestValue>nQOtmW194/aI+hedq+Dqp+n3IuU=</ds:DigestValue> 
     </ds:Reference> 
    </ds:SignedInfo> 
    <ds:SignatureValue>kyp+a6arETylW8ZuucKJyd....</ds:SignatureValue> 
    <ds:KeyInfo> 
     <ds:KeyName>Public key of certificate</ds:KeyName> 
     <ds:KeyValue> 
      <ds:RSAKeyValue> 
       <ds:Modulus>t0Yial28LxcIoPj16PlLIzaV...</ds:Modulus> 
       <ds:Exponent>AQAB</ds:Exponent> 
      </ds:RSAKeyValue> 
     </ds:KeyValue> 
     <ds:X509Data> 
      <ds:X509Certificate>MIIHOTCCBiGgAwIBAgICVJIwDQYJKo....</ds:X509Certificate> 
     </ds:X509Data> 
    </ds:KeyInfo> 
</ds:Signature> 

Wydaje mi się dobrze. Jednak nadal nie działa. Ktoś ma jakąś wskazówkę?

+0

Istnieje dwóch możliwych winowajców. Najpierw byłby to prawdziwy certyfikat, z jakiegoś powodu można go odrzucić. Drugi byłby sposób wysyłania XML, może być zmieniony w drodze do serwera (formatowanie, odstępy, cokolwiek). Gdybym był tobą, po prostu skontaktowałbym się z dostawcą serwera i zapytałbym, co jest nie tak. –

+0

Uświadomiłem sobie, że to moja wina. Nie zaimplementowałem przed Twoją metodą weryfikacji podpisu. Teraz zrobiłem to i zawsze otrzymuję "fałszywe". Następnie błąd jest po mojej stronie. Jestem bardzo zdezorientowany, odkąd podążyłem za krokami na twoim blogu, a także dodałem jeszcze parę do wypełnienia w tym samym formacie, w jakim serwer powraca po zaakceptowaniu dokumentu. To jest mój podpisany plik: http://tinyurl.com/lb5o6m9 Jak mogę zrobić, aby znaleźć niewłaściwą wartość? Z góry dziękuję. –

+0

możesz wysłać mi wiadomość e-mail ze szczegółami dotyczącymi wdrożenia? Widzę serwis internetowy jako winowajcę, ale potrzebuję zarówno serwera, jak i kodu klienta, aby spróbować ci pomóc. Wysyłam również podpisane dokumenty przez http i nie mam żadnych problemów. –

Powiązane problemy