Question

I have a requirement that I must build a SOAP message and then sign it using an X509 cert before sending it to a service via POST. I have NO idea what type of service this is but I was given a SOAP example.

I tried to use the example on MSDN but it's limited and incomplete and I am not able to instantiate the Security object. But even if I could, how do I associate it with the SoapEnvelope?

http://msdn.microsoft.com/en-us/library/aa529277.aspx

The SOAP message is built via Xslt. I need to get it signed anyway I can. Having a hard time finding anything. any ideas?

I'm currently using the following code to sign the xml and then I inject it into the SOAP xml.

private static XmlElement EncryptMessage(XmlElement msgBody)
    {
        StoreName storeName = (StoreName)Enum.Parse(typeof(StoreName), "My");
        StoreLocation storeLocation = (StoreLocation)Enum.Parse(typeof(StoreLocation), "LocalMachine");

        X509Certificate2 cert = X509Helper.GetCertificate(storeName, storeLocation, "CN=Something"); 
        SignedXml signedXml = new SignedXml(msgBody);

        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
        signedXml.SigningKey = cert.PrivateKey;
        signedXml.KeyInfo.AddClause(new System.Security.Cryptography.Xml.KeyInfoX509Data(cert));

        Reference tRef = new Reference(""); 

        XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();

        tRef.AddTransform(env);

        signedXml.AddReference(tRef);
        signedXml.ComputeSignature();

        XmlElement xmlDsig = signedXml.GetXml();
        xmlDsig.SetAttribute("Id", "Signature-1");

        return xmlDsig;
    }

which returns

    <SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
  <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
  <Reference URI="">
    <Transforms>
      <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
    </Transforms>
    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
    <DigestValue>iGDf7TGuTzLDv/PYYF7/DC7xcZs=</DigestValue>
  </Reference>
</SignedInfo>
<SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#">nALPlzIs96AE6/oMeFLFgxNJEeExwbvVLQI5HmevtthSX8hppH6Wr3OSk6/GSBtfyw6x1rXZXVbiXLuZ5jxiOsFfz314gBhoRzAskIxEer2SVmJ3BGUknEj+8pAAWfHFd3S8I4xPDjXvNPKalPsos8SBIDGNztACuG/aTb8FfomtxeJuzuIxQMPzXcJmX3bc1Sm7vkfrImY0Ep6LgFhl7NH5cl9R51APoSyRAjAxgPSQ/B3cdYxKwRO4Xe0A3XmFhdVWbFz+IfZGoWWqol0pOlVjkyzagqaMKl6Qstg3qmoqwspiQ/sUcyl+BOqXUtOw8ItFNUhrCeHxp4Utq8Hlqg==</SignatureValue>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  <X509Data>
    <X509Certificate>MIIDAjCCAeqgAwIBAgIQdTFx7HlggYRD6LNeHg9uITANBgkqhkiG9w0BAQUFADAqMSgwJgYDVQQDEx9kZGF2aXMtUEMuaW50cmFuZXQud2VibWV0cm8uY29tMB4XDTExMDExODIxNDAyNFoXDTEyMDExODAwMDAwMFowKjEoMCYGA1UEAxMfZGRhdmlzLVBDLmludHJhbmV0LndlYm1ldHJvLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALMTgt9dnWwPEquCzW0sfUvRN5VLqX8BGeT9IL3MSXT9jdY2fWHav6SNdoXGp2RnSmQnTjHoz7WRu0r8UHfV9H7W6bUwiE+Ek1mQcbTGM3v/MOzzpbK4OT/OexP8LLFV0DihtX3PHinaTIvczledUHj135hOF6q6YDgLg/XkYUiuXk2DzYSIFSTQ5cPgt7k7fYwpVPiqddU56djKov2xWbnJKmNyO7XbKQiHYUADvqem3WE4NcTHIwScmjXdLxrN3xKKhh+UFvRRXeMyV+I4yvHGRUx1ZSsJ7yvC8rMYWuq3n8GymYSXJyWZKzEKxISbl9RTeri4ToyghpEcqiQ0oBUCAwEAAaMkMCIwCwYDVR0PBAQDAgQwMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBBQUAA4IBAQAWlISMloQU+SmZ1vAvup6WngUUsWc27h/mkA2wO1/H8GfjiiUrS/BCIqL37L/x0uFw6uUF4v0qbK2/weuqKPCUYu676k4D9fuwdTLwZaoIclSrM7XWwcbp/m4IHzHuW3BZ+r4MWe0Jv49CDlVj5A2kT0FXDc+qemulPtP4OOb0f8UzBoPuWTM86rjjY290F1jUdtEtgY9EJWxNAC2AnIY2dxXBZZm5v3FBPcqXTQXxCAmMV9xXfGb6Rg2j8IiL04qJ/2y4u+G3VKjWRyqDvKQ293qO7JMAdDnBleRxgwPNTJ/B5R5UcRT5AAwqbSfUgmcZeJN1ZCWMEdX41oONzkJJ</X509Certificate>
  </X509Data>
</KeyInfo>

Based on what I read here: http://www.trl.ibm.com/projects/xml/soap/wp/wp.html all I need is what I have so I can just inject it into the header.

Was it helpful?

Solution

You don't need WSE, you can sign the message by generating a signature from the body of the message. The code you're using is correct. Just change it to process the body of the message and then put the xml returned by your method int he header of the soap message. Also, it looks like you need to add a reference. The URL should be whatever the ID you gave the body.

OTHER TIPS

I made it in the following way, first take the certificate and keep it in stock certificates, after we access the certificate from the store and sign the soap message

in this link you will find the same example and other similar http://www.systemdeveloper.info/2013/11/digital-signature-in-c.html

This is an example of how I did it:

    public static getDataResponse queryingData(string name)
    {
        proxy.BanWS conexion = new proxy.Banws();

        //VALIDATION OF CONNECTION V3
        X509Certificate2 elCert = new X509Certificate2(@"C:\portecle-1.5\12345.P12", "12345");
        conexion.ClientCertificates.Add(elCert);

        // Copy the certificate to the certificate store using ASPNET
        // spent the path and password
        X509Certificate2 certificate = new X509Certificate2(@"C:\portecle-1.5\12345.P12", "12345");
        X509Store stores = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        stores.Open(OpenFlags.ReadWrite);
        stores.Add(certificate);
        stores.Close();

        String sto = X509CertificateStore.MyStore;
        // Open the Certificates Stores
        X509CertificateStore store = X509CertificateStore.CurrentUserStore(sto);
        store.OpenRead();

        // We look for the certificate that we will use to perform the signature
        String certname = "conticert";

        Microsoft.Web.Services2.Security.X509.X509CertificateCollection certcoll = store.FindCertificateBySubjectString(certname);

        if (certcoll.Count != 0)
        {
            Microsoft.Web.Services2.Security.X509.X509Certificate cert = certcoll[0];

            SoapContext ctx = conexion.RequestSoapContext;
            SecurityToken tok = new X509SecurityToken(cert);
            ctx.Security.Timestamp.TtlInSeconds = 120;
            ctx.Security.Tokens.Add(tok);
            // We signed the request
            ctx.Security.Elements.Add(new MessageSignature(tok));
        }

        //remote call
        getDataResponse response = new getDataResponse();

        response = conexion.getData(name);

        return response;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top