2016-03-28 3 views
1

Ich bin ziemlich neu in C# und besonders neu in der Unterzeichnung mit X509. Ich habe eine XML-Vorlage, in der ich das verwendete Zertifikat (done) hinzufügen und den Zeitstempel (TS-1), das binäre Sicherheitstoken und den Body (id-1) signieren muss. Außerdem muss ich den Digest-Wert dieser 3 Elemente schreiben (z. B. Platzhalter ersetzen) und den Signaturwert hinzufügen.Wie Xml mit X509-Zertifikat signieren, Digest-Wert und Signatur zu XML-Vorlage hinzufügen

enter image description here

Aber ich wirklich nicht verstehen, das Konzept, z.B. Wie macht man das. Ich lese ein paar Webseiten, z.B. signing a xml document with x509 certificate aber ich kann den Code nicht an mein Problem anpassen. Hier

ist, was ich versucht:

public static string SignXml(string template) 
{ 

    XmlDocument document = new XmlDocument(); 
    document.LoadXml(template); 

     // define elements that will be signed 
     XmlNode securityToken = null; 
     XmlNode validityPeriod = null; 
     XmlNode body = null; 
     XmlNode signedInfo = null; 
     XmlNode signatureValue = null; 
     XmlNodeList digestTags = null; 



     XmlNamespaceManager namespaces = new XmlNamespaceManager(document.NameTable); 
     namespaces.AddNamespace("ns", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
     namespaces.AddNamespace("nu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); 
     namespaces.AddNamespace("bo", "http://schemas.xmlsoap.org/soap/envelope/"); 
     namespaces.AddNamespace("si", "http://www.w3.org/2000/09/xmldsig#"); 
     namespaces.AddNamespace("sinfo", "soapenv xd xe"); 

     document.LoadXml(template); 
     //XmlNode idNode = document.SelectSingleNode("/My_RootNode/ns:id", namespaces); 

     securityToken = document.SelectSingleNode("descendant::ns:BinarySecurityToken", namespaces); 
     validityPeriod = document.SelectSingleNode("descendant::nu:Timestamp", namespaces); 
     body = document.SelectSingleNode("descendant::bo:Body", namespaces); 
     signedInfo = document.SelectSingleNode("descendant::si:SignedInfo", namespaces); 
     signatureValue = document.SelectSingleNode("descendant::si::sinfo:SignatureValue", namespaces); 
     digestTags = document.SelectNodes("descendant::si:DigestValue", namespaces); 

     // add the digests (to know where to write the digests) 
     String nodeName = null; 
     for (int counter = 0; counter < digestTags.Count; counter++) 
     { 
      nodeName = digestTags[counter].FirstChild.InnerText; 
      if (WebserviceConstants.PLACEHOLDER_AUTHNREQUEST_DIGEST.Equals(nodeName)) 
      { 

       generateDigest(body, digestTags[counter]); 
      } 
      else if (WebserviceConstants.PLACEHOLDER_CERTIFICATE_DIGEST.Equals(nodeName)) 
      { 

       generateDigest(securityToken, digestTags[counter]); 
      } 
      else if (WebserviceConstants.PLACEHOLDER_TIMESTAMP_TAG_DIGEST.Equals(nodeName)) 
      { 

       generateDigest(validityPeriod, digestTags[counter]); 
      } 
     } 



     SignedXml signedXml = new SignedXml(document); 



    X509Certificate2 cert = new X509Certificate2(); 
    cert = getbase(); 

    signedXml.SigningKey = cert.PrivateKey; 

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

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

     return document.OuterXml; 
    } 
} 

Ich bin in Frage mich:

  • Wie erhalte ich den Digest-Wert und wie es zu dem entsprechenden XML-Knoten
  • Wie zu schreiben den Signaturwert berechnen, da er die signierten Informationen aller 3 Referenzen "enthält" ???

Wie Sie sehen können, fehlt mir einige allgemeine Hintergrund und Verständnis. Wäre wirklich cool wenn du mir helfen könntest!

Danke

Antwort

1

Sie haben noch manuell die Knoten der Signatur zu erstellen, nachdem Sie die Signatur berechnen rufen Sie die Methode GetXml (Sie bereits tun es: signedXml.GetXml()) und diesen Willen Geben Sie etwas zurück:

<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>   
    <X509Data> 
     <X509Certificate>MIIF3jCCBUegAwIBAgIEPQa1....</X509Certificate> 
    </X509Data> 
    </KeyInfo> 
</Signature> 

Dann müssen Sie nur den gesamten Signaturknoten in Ihrer XML-Vorlage ersetzen.

im Auge --Keeping, dass die SignedXml Sie jetzt diese Struktur gebe ich werde Ihre Fragen

Ihre erste Frage beantworten ist es um den Digest-Wert Ihrer Referenzen? Wenn dies der Fall ist, berechnet die ComputeSignature-Methode sie und fügt sie dem entsprechenden XML-Knoten hinzu.

Der Signaturwert wird berechnet, wenn Sie die Signatur berechnen, die Sie nicht selbst berechnen müssen.

Wenn Sie die ComputeSignature-Methode aufrufen, nehmen Sie den SignedInfo-Knoten und verdauen Sie ihn. Ihre Referenzen sind in diesem Knoten, so dass Sie den Signaturwert erhalten die Informationen über alle Ihre Referenzen

Dies ist, wie die ComputeSignature Methode erhält den Digest-Wert des SignedInfo Knoten, mit diesem Wert berechnet er den Signaturwert enthält:

XmlElement e = this.SignedInfo.GetXml(); //get the signedinfo nodes 
document.AppendChild(document.ImportNode(e, true)); 
Transform canonicalizationMethodObject=this.SignedInfo.CanonicalizationMethodObject; 
canonicalizationMethodObject.LoadInput(document); 
canonicalizationMethodObject.GetDigestedOutput(hash); //digest the signedinfo node 
Verwandte Themen