Using .NET to verify digital signature generation using Java CXF / WSS4J application - namespace problem?

Cliff's Notes

Digital signatures created by .NET using .NET and Java WSS4J, signatures created by Java WSS4J are not verified with .NET, but are verified using Java. Perhaps (?) Invoked by the XML namespaces generated in WSS4J.

Question meat

I have the following method that validates digital signatures in SOAP XML:

public static bool VerifySignature(XmlDocument soap, bool verifySignatureOnly, bool verifyUsername)
{
    // Create namespace manager needed for xpath selections
    XmlNamespaceManager soapNamespaces = GetSoapNamespaces(soap.NameTable);

    // Use xPath constants to get binary security token
    string inputb64BinarySecurityToken = soap.SelectSingleNode(SxpBinarySecurityToken, soapNamespaces).InnerText;

    // Get public key from the binary security token string
    var certificate = new X509Certificate2(Convert.FromBase64String(inputb64BinarySecurityToken));

    // Get signature element
    var signature = soap.SelectSingleNode(SxpSignatureElement, soapNamespaces) as XmlElement;

    // Load into SignedXml, verify and return
    var xml = new SignedXml(soap);
    xml.LoadXml(signature);

    return xml.CheckSignature(certificate, verifySignatureOnly);
}

I have the following methods that generate digital signatures

private static void PerformSoapSecurity(XmlDocument soapDom, XmlNamespaceManager soapNamespaces, string certificateThumbprint)
{
    X509Certificate2 certificate = GetDigitalCertificate(certificateThumbprint);
    long certId = GenerateCertificateId(certificate);

    //Cerate Soap BinarySecurityToken Element
    XmlDocumentFragment securityToken = soapDom.CreateDocumentFragment();
    securityToken.InnerXml = GetBinarySecurityToken(certId, GetDigitalCertificate(certificateThumbprint));

    // Create Soap Signature Element
    // Here passing in the whole Xml document to 'GetSignature'
    // means the generated signature element doesn't need to 
    // be imported into the dom before inserting]
    XmlElement signature = GetSignature(soapDom, certificate);

    //Create Soap Key Info Element
    XmlDocumentFragment keyinfo = soapDom.CreateDocumentFragment();
    keyinfo.InnerXml = GetKeyInfo(certId);

    //Append the created elemnts into the Soap message ***the order here IS important***
    soapDom.SelectSingleNode(SxpSecurityElement, soapNamespaces).AppendChild(securityToken);
    soapDom.SelectSingleNode(SxpSecurityElement, soapNamespaces).AppendChild(signature);
    soapDom.SelectSingleNode(SxpSignatureElement, soapNamespaces).AppendChild(keyinfo);

    // Assign the subject CN of the signing certificate as the user name (removing CN= prefix)
    soapDom.SelectSingleNode(SxpUsername, soapNamespaces).InnerText = certificate.Subject.Remove(0, 3);
}

private static XmlElement GetSignature(XmlDocument document, X509Certificate2 dsigCertificate)
{
    Reference reference = new Reference("#Timestamp-1");
    reference.AddTransform(new XmlDsigExcC14NTransform());

    var signed = new SignedXmlWithId(document);
    signed.SigningKey = dsigCertificate.PrivateKey;
    signed.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
    signed.AddReference(reference);
    signed.ComputeSignature();

    XmlElement signatureElement = signed.GetXml();
    return signatureElement;
}

And this is the method I use to create XmlNamespaceManager:

private static XmlNamespaceManager GetSoapNamespaces(XmlNameTable nameTable)
{
    XmlNamespaceManager soapNamespaces = new XmlNamespaceManager(nameTable);

    soapNamespaces.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
    soapNamespaces.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
    soapNamespaces.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
    soapNamespaces.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
    soapNamespaces.AddNamespace("addressing", "http://www.w3.org/2005/08/addressing");

    return soapNamespaces;
}

Now all this works fine, I can generate a SOAP XML with a signature, and then verify the signature in .NET and Java. For example, if I sign the following:

<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-1">
    <wsu:Created>2011-03-02T10:51:18.178Z</wsu:Created>
    <wsu:Expires>2011-03-02T11:06:18.178Z</wsu:Expires>
</wsu:Timestamp>

I get:

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
        <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        <Reference URI="#Timestamp-1">
            <Transforms>
                <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>eC4H+inxmOWEAYTBAZCwcnK4tUA=</DigestValue>
        </Reference>
    </SignedInfo>
    <SignatureValue>--- SIGNATURE BASE64 ----</SignatureValue>
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#" Id="KeyId--6846455287902010833">
        <wsse:SecurityTokenReference 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" wsu:Id="STRId-A0FC813092018230">
            <wsse:Reference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" URI="#CertId--6846455287902010832" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
        </wsse:SecurityTokenReference>
    </KeyInfo>
</Signature>

Java, CXF WSS4J. , Java. Java XML- Timestamp, , , .NET. , , XML XML. Java :

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-2">
    <ds:SignedInfo>
        <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        <ds:Reference URI="#Timestamp-1">
            <ds:Transforms>
                <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>eC4H+inxmOWEAYTBAZCwcnK4tUA=</ds:DigestValue>
        </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>--- SIGNATURE BASE64 ----</ds:SignatureValue>
    <ds:KeyInfo Id="KeyId-D5343AC748043302DD12990630782012">
        <wsse:SecurityTokenReference 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" wsu:Id="STRId-D5343AC748043302DD12990630782013">
            <wsse:Reference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" URI="#CertId-D5343AC748043302DD12990630781901" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
        </wsse:SecurityTokenReference>
    </ds:KeyInfo>
</ds:Signature>

"ds". , DigestValues ​​ , . . , Java ds .NET SignatureValue, . , , SignedXml , XML- sans-namespace .

, System.Security.Cryptography.Xml.SignedXml ( ), , . , / (, .NET, ) XML, , , .

, , -, ?

, Java .

+3

Source: https://habr.com/ru/post/1795780/


All Articles