Add namespace prefixes when signing XML document

0 投票
最新提问 用户: (740 分)

I have this XML document:

<saml2p:ArtifactResolve ID="id-55f5dd37-96aa-4892-a0de-247275430d06"
                        IssueInstant="2017-05-16T08:08:23.278Z"
                        Version="2.0"
                        xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
                        xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                        xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                        xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
    <saml2:Issuer>example.com</saml2:Issuer>
    <saml2p:Artifact>AAQAAKFbFR94fxqmioAqjJUwfyUtjJbvQA6bE2NWQoXtJp^%^2FFiaXn3DXM1Iw^%^3D</saml2p:Artifact>
</saml2p:ArtifactResolve>

I sign it using Java code:

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Arrays.asList;

public class CreateSignature2
{
    private static final String PRIVATE_KEY_ALIAS = "test-alias";
    private static final String PRIVATE_KEY_PASS = "12345";
    private static final String KEY_STORE_PASS = "passpass";
    private static final String KEY_STORE_TYPE = "JKS";

    public static String signXmlArtifactResolve(String artifactResolve) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableEntryException, ParserConfigurationException, SAXException, MarshalException, XMLSignatureException, TransformerException
    {
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

        Reference ref = fac.newReference(
                "",
                fac.newDigestMethod(DigestMethod.SHA1, null),
                asList(
                        fac.newTransform(Transform.XPATH2, new XPathFilter2ParameterSpec(asList(new XPathType("here()/ancestor::saml2p:ArtifactResolve[1]", XPathType.Filter.INTERSECT)))),
                        fac.newTransform(Transform.XPATH2, new XPathFilter2ParameterSpec(asList(new XPathType("here()/ancestor::ds:Signature[1]", XPathType.Filter.SUBTRACT)))),
                        fac.newTransform(CanonicalizationMethod.EXCLUSIVE, new ExcC14NParameterSpec(asList("ds", "saml2", "saml2p", "xenc")))),
                null,
                null);

        SignedInfo si = fac.newSignedInfo(
                fac.newCanonicalizationMethod("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", (C14NMethodParameterSpec) null),
                fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                Collections.singletonList(ref));

        KeyStore ks = KeyStore.getInstance(KEY_STORE_TYPE);
        ks.load(new FileInputStream("C:/keystore.jks"), KEY_STORE_PASS.toCharArray());
        KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(PRIVATE_KEY_ALIAS, new KeyStore.PasswordProtection(PRIVATE_KEY_PASS.toCharArray()));
        X509Certificate cert = (X509Certificate) keyEntry.getCertificate();

        KeyInfoFactory kif = fac.getKeyInfoFactory();
        List x509Content = new ArrayList();
        x509Content.add(cert);
        X509Data xd = kif.newX509Data(x509Content);
        KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(new ByteArrayInputStream(artifactResolve.getBytes(UTF_8)));

        Node nextSibling = doc.getDocumentElement().getChildNodes().item(3);
        DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement(), nextSibling);
        dsc.putNamespacePrefix("ds", "http://www.w3.org/2000/09/xmldsig#");
        dsc.putNamespacePrefix("dsig-xpath", "http://www.w3.org/2002/06/xmldsig-filter2");
        dsc.putNamespacePrefix("ec", "http://www.w3.org/2001/10/xml-exc-c14n#");
        dsc.setIdAttributeNS(doc.getDocumentElement(), null, "ID");

        XMLSignature signature = fac.newXMLSignature(si, ki);

        signature.sign(dsc);


        ByteArrayOutputStream os = new ByteArrayOutputStream();
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(doc), new StreamResult(os));

        return new String(os.toByteArray(), UTF_8);
    }
}

It produces signed XML document:

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:ArtifactResolve xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                        xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
                        xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                        xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
                        ID="id-b67625d2-461e-49b1-8919-5e5d14c2b0df"
                        IssueInstant="2017-05-16T07:47:50.720Z" Version="2.0">
    <saml2:Issuer>example.com</saml2:Issuer>
    <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/2002/06/xmldsig-filter2">
                        <XPath xmlns="http://www.w3.org/2002/06/xmldsig-filter2" Filter="intersect">
                            here()/ancestor::saml2p:ArtifactResolve[1]
                        </XPath>
                    </Transform>
                    <Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2">
                        <XPath xmlns="http://www.w3.org/2002/06/xmldsig-filter2" Filter="subtract">
                            here()/ancestor::ds:Signature[1]
                        </XPath>
                    </Transform>
                    <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"
                                             PrefixList="ds saml2 saml2p xenc"/>
                    </Transform>
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <DigestValue>ZyrJgQIlQdH7KnKSLiyXvVQ8JHA=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>
            ZHUxIGM88RNNXym2aTTxx+wIRPRc2xyVgclMg01SxTk4rH2xAnCH6nYe1Ots7FOQ/B3X6hC40nMyWXiaOs3votw0X/MDVkkqHTBvEtkvPZSWHT63vbf+hBLlpS9u/WbXkGWZH70LlEPVU86BoVU4MIVJzSpDQkXXpkJsHIbmPTm0KW2F3lRTfqHR0SMSvsGyH2uEnGlgdPgtLb3mDlUB8i4nrGxZKQlU4wDzgOQJDXCADCiaURfYbzDHD/rms1LzISIqs3W8+VT95bYQlJzcYeVQmlx0vL2UyYuRNvmOfQSLncmJzux7e4A3oYRx2Ae4ZV7eBJ+VCmSN0eM/QO+ryg==
        </SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>
                    MIIDPjCCAiagAwIBAgICAQEwDQYJKoZIhvcNAQELBQAwXTELMAkGA1UEBhMCUEwxDDAKBgNVBAoTA0NQSTEfMB0GA1UECxMWQ1BJIENBIGZvciBlcHVhcCBURVNUMjEfMB0GA1UEAxMWQ1BJIENBIGZvciBlcHVhcCBURVNUMjAeFw0xNzAyMTQwMDAwMDBaFw0xOTAyMTMyMzU5NTlaMEsxCzAJBgNVBAYTAlBMMQwwCgYDVQQKEwNDT0kxFjAUBgNVBAsTDXRlc3Rvd2EtZmlybWExFjAUBgNVBAMTDXRlc3Rvd2EtZmlybWEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDlzLF38u+EPjC0LnaB2is1K5wbZliA5yOs+HSkgYtJIvCYHYT0+V+UTLRE1BDveyt4jFgaaUe/U3iTUM/Qy9vJZUbwgNon65wSdqw30TTaSChvFD/kUmRJqieVV9yDk3Jd8ZxaGhwqvyErvVYKwZ2+OkSsmug7rD3r0EBAZddVBVNCPi1zzUX8pYRednlm5Va+iW/ng1F54cwDqOFm0Dl31fYfGeVgWh+z09pMLtk3ddtcoXSDGgPeXXfA9rpOJxjroeRrxoAMjjG7CnKuvuICzpbSMHNl8LSS2GsIKEFPyda9B8ytPchhGllUs+KL4Iw6HaA81QVf8wg6bRFqFZm/AgMBAAGjGjAYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IBAQBZqlHWtSwLIgCGa0PgHuP2J3j3rEXYoZUsCwPQM45vW6CzpRGe+yEvZD4JT8bctggYy1xIXMykX/qRvude2VS8O+nbnAqEjG7qyUe5xqnNjMS4EAcMALDTbVv6+SYcBNpFGE6OGH4MzEOj3zRYY/9OjHmqyHM0n9bXNVuM/gfDapqSScrFPxUAGo6biXouWCPJGBnPz9LNyBsSAjr9XiuRkhU68QHSWWC9Y+ddkKHmI2Xos33ieHfg35oKLLeKAV6KwZJ/7k8SpLumCtsIOW4gYXZSYaK6cBmjxXtdbwbh8r3GCGv125Tb01w0Nb+fdYBEvUDMZDk1QIyVhRZj6rFb
                </X509Certificate>
            </X509Data>
        </KeyInfo>
    </Signature>
    <saml2p:Artifact>AAQAAKFbFR94fxqmioAqjJUwfyUtjJbvQA6bE2NWQoXtJp^%^2FFiaXn3DXM1Iw^%^3D
    </saml2p:Artifact>
</saml2p:ArtifactResolve>

Next I send this document as SOAP body. I get an error saying that document signature is invalid. I suspect that it is caused by prefixes not being added to tags: Signature, SignedInfo etc. I want to force Java XML APIs to add those prefixes. How can I do that?

I want Java XML APIs to generate this document instead:

        <saml2p:ArtifactResolve xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
                                xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                                xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                                xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
                                ID="ID_736c1d00-c436-425a-ad01-7c854849479b"
                                IssueInstant="2014- 06-30T08:28:10.982Z" Version="2.0">
            <saml2:Issuer>example.com</saml2:Issuer>
            <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/2002/06/xmldsig-filter2">
                                <dsig-xpath:XPath
                                        xmlns:dsig-xpath="http://www.w3.org/2002/06/xmldsig-filter2"
                                        Filter="intersect">
                                    here()/ancestor::saml2p:ArtifactResolve[1]
                                </dsig-xpath:XPath>
                            </ds:Transform>
                            <ds:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2">
                                <dsig-xpath:XPath
                                        xmlns:dsig-xpath="http://www.w3.org/2002/06/xmldsig-filter2"
                                        Filter="subtract">here()/ancestor::ds:Signature[1]
                                </dsig-xpath:XPath>
                            </ds:Transform>
               

登录 或者 注册 后回答这个问题。

欢迎来到 Security Q&A ,有什么不懂的可以尽管在这里提问,你将会收到社区其他成员的回答。
...