C# Add wsse:Security and BinarySecurityToken to Envelope xml file programmatically without Web Reference

10,129

The BinarySecurityToken is simply the base 64 encoded version of the cert. If you export the cert and copy to file making sure you clicked the Base-64 encoded option you will see the value that is used in the BinarySecurityToken element. You can see this by opening the exported file in notepad.

To programmatically populate your xml element directly from the Client cert do something like this:

var cert = new X509Certificate2(ClientCertificateFilePath, ClientCertificatePassword);
        var export = cert.Export(X509ContentType.Cert, ClientCertificatePassword);
        var base64 = Convert.ToBase64String(export);
Share:
10,129
jasilva
Author by

jasilva

Fullstack developer and gamer

Updated on June 29, 2022

Comments

  • jasilva
    jasilva almost 2 years

    Currently I have to generate an XML file, simulating a SOAP request, this file should be signed with an X.509 certificate

    At this moment I have this method to sign the file

    public static void SignXml(XmlDocument xmlDoc, X509Certificate2 uidCert)
    {
        CspParameters cspParams = new CspParameters();
        cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
    
        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
    
        // Check arguments. 
        if (xmlDoc == null)
            throw new ArgumentException("xmlDoc");
        if (rsaKey == null)
            throw new ArgumentException("Key");
    
        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(xmlDoc);
    
        // Add the key to the SignedXml document.
        signedXml.SigningKey = rsaKey;
    
        // Specify a canonicalization method.
        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
    
        // Set the InclusiveNamespacesPrefixList property.        
        XmlDsigExcC14NTransform canMethod = (XmlDsigExcC14NTransform)signedXml.SignedInfo.CanonicalizationMethodObject;
        canMethod.InclusiveNamespacesPrefixList = "sol soapenv";
    
        // Create a reference to be signed.
        Reference reference = new Reference();
        Reference reference1 = new Reference();
        reference.Uri = "";            
        reference1.Uri = "";
    
        string referenceDigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
        reference.DigestMethod = referenceDigestMethod;
        reference1.DigestMethod = referenceDigestMethod;
    
        // Add an enveloped transformation to the reference.
        //XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        //reference.AddTransform(env);
    
        XmlDsigExcC14NTransform c14n = new XmlDsigExcC14NTransform();
        c14n.InclusiveNamespacesPrefixList = "wsse sol soapenv";
    
        reference.AddTransform(c14n);
    
        XmlDsigExcC14NTransform c14n1 = new XmlDsigExcC14NTransform();
        c14n1.InclusiveNamespacesPrefixList = "sol";
        reference1.AddTransform(c14n1);
    
        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);
        signedXml.AddReference(reference1);
    
        // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
        KeyInfo keyInfo = new KeyInfo();
    
        SecurityTokenReference skr = new SecurityTokenReference();
        skr.Reference = "some";
        skr.ValueType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";
    
        keyInfo.AddClause(skr);
        signedXml.KeyInfo = keyInfo;
    
        // Compute the signature.
        signedXml.ComputeSignature();
    
        // Get the XML representation of the signature and save 
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();
    
        System.Console.WriteLine(signedXml.GetXml().InnerXml);
    
        // Append the element to the XML docu0ment.
        //xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
        XmlElement root = (XmlElement)xmlDoc.GetElementsByTagName("soapenv:Envelope")[0];
        string query = string.Format("//*[@Id='{0}']", "IDH"); //Search the Header tag to add signature
        XmlElement myElement = (XmlElement)xmlDoc.DocumentElement.SelectSingleNode(query);
        myElement.AppendChild(xmlDigitalSignature);
    }
    

    I can generate this file

    <soapenv:Envelope xmlns:sol="
    http://www.sol.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Header Id="IDH">
            <sol:authentication>
                <id>4942014103</id>
                <userid>ME.8494</userid>
            </sol:authentication>
            <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
                <SignedInfo>
                    <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <InclusiveNamespaces PrefixList="sol soapenv" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    </CanonicalizationMethod>
                    <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#">
                                <InclusiveNamespaces PrefixList="wsse sol soapenv" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                            </Transform>
                        </Transforms>
                        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                        <DigestValue>BEZBfqQ1QGgbhxvtB83/tr2Yt/8uJPEfvrh8Tn5O6oQ=</DigestValue>
                    </Reference>
                    <Reference URI="">
                        <Transforms>
                            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                                <InclusiveNamespaces PrefixList="sol" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                            </Transform>
                        </Transforms>
                        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                        <DigestValue>BEZBfqQ1QGgbhxvtB83/tr2Yt/8uJPEfvrh8Tn5O6oQ=</DigestValue>
                    </Reference>
                </SignedInfo>
                <SignatureValue>MiOL7D2YfIModsGXh+mm+Ok+oApaYMNenX8xFgwMCXcxW7blHqAPJ2VKGhraAdqy9crAvzEgT6MqD/T9ZWPnK1IHOcQlCt5XICkAlJVnLB78rWkYaTsjNLak2KSvQVCqEDIp0GEwGE6S+5cJykWmbOGiZg50VFFN8QRUlYiIB8I=</SignatureValue>
                <KeyInfo>
                    <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                        <wsse:Reference URI="#some" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
                    </wsse:SecurityTokenReference>
                </KeyInfo>
            </Signature>
        </soapenv:Header>
        <soapenv:Body>
            <sol:solbus>
                <in>H4sIAAAAAAAEAI1VXW+bMBR9n7T/YPFcvgJJW9RQUZJ0aAnpAp26vVQWOK2lgCPjJM2/nwEHTEKk8cY59/heHx/Dw+NXtgF7RAtM8rFiaoby6H7/9rBmiTPzYt97X079CeBFeeFWF8FXisfDK2dXT9cDhoB0sj9EMfGIapvy3mUfKJMqjivGAwT5AiVMUajpUdzR2CktRhGHGIrdeQJZAdt/xtbyryBOZJyGc4F1aqUsBnBKCacoGKAn6gaIuSCuQw7+hEKE9x/uGTbAvzYxC684n39+VZuy8fLZpr9p39oPdWSqvEFOZFhhmrCnY5o0d38Vbr+jhJukIJwnuJe41q3QUhicRmYu6LW9lfS2S4FDeaGm/nuWxdY5fOdQ19pmS37e7AS5LSqrrkfCRB/iCbFFGJFHS5jT1Od3DT4ZqwFfIptGku+g+njRq/UoY9Uu9HqjUc3Yk4NfesUxvCDL1/GYblvf/aoYKc1YiqGaYFK0vdhbcKPDCZzsFq6QfLeu2W7lXPoWDjZeR7oRA16NlU+n+MdSXNEtnn3HXbepJtgRdv9RN4v6fh6xR4/CVeTMMYmDdg4oVPr6sN34MjNGSdaVxPvryl/nHFITD+KYYbzNqPloz1SJ4wZZ9BviZA7+ZKvxqsmroWSTmvT3BT/k9AsqO0dGusLN5CRerUWaoT/bN71F6Ymjh9q6S36nngMxEmBLFwcAAA==</in>
            </sol:solbus>
        </soapenv:Body>
    </soapenv:Envelope>
    

    In method SingXml xmlDoc contains this xml, anfter sing I add to header

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sol="http://www.sol.com">
      <soapenv:Header Id="IDH">
        <sol:authentication>
          <id></id><userid></userid> <------ With info
        </sol:authentication>
      </soapenv:Header>
      <soapenv:Body>
        <sol:siatbus>
          <in></in> <-----With info
        </sol:siatbus>
      </soapenv:Body>
    </soapenv:Envelope>
    

    I need something more, Signature must be within a Security tag inside Header tag, with a BinarySecurityToken element

    For example

    <soapenv:Header> <!-- extrac of the example file -->
      <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu=" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-D53CCD6983E4CE0BD7142791021078262">
            MIIDbDgg4iF74cqiF6NcnzBnD9qA2MB6hSo38e0RISilEFSzWikDqBtOjgm7ux9fdeHojDm4uvhsSfbEyGmGTAQRzg9yIiD3ovjOzuZsf+I3HWS9F6xl6sb2+wvYXD4DFk/OD+N7UszGsoWFZg
        </wsse:BinarySecurityToken>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
              .....
        </ds:Signature>
    

    I can add <wsse:Security tag with hard code String, but I do not know if it affects the BinarySecurityToken inside

    How is the internal data (MIIDbDgg4i....) of the token is generated?

    What I have to do to add the Security tag?

    Extra

    How I can add the prefix ds to the Signature and its children?

    • Habeeb
      Habeeb over 8 years
      Did you already find a solution for this?
    • randomstudious
      randomstudious almost 7 years
      To add the ds prefix to the signature and its children: you can add a foreach loop for all xmlDigitalSignature.ChildNodes and write childNode.Prefix = "ds" inside it, which will assign the prefix to all the child nodes.