question

View: New views
6 Messages — Rating Filter:   Alert me  

question

by Jean-Charles Laurent :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


What I am trying to do is to sign a the BODY element of the XML file (detached form) and insert the signature inside the <Security> tag.

I am using the apache security package (1.4.1). I seem to be able to verify the signature on my side but it cannot be verified on the client side.

One thing I haved noticed is (andI can't explain);

        CanonicalizationMethod Algorithim is "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>

but the

        Transform Algorithm is "http://www.w3.org/2001/10/xml-exc-c14n#"
         <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>


Hope someone will be able to help me out as I am running out of ideas.

Thanks

JC


Below is the output file followed by the java code and the keystore used. Please comment the code if you wish. I am new to XML Signature.

Here is the output xml file:

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:Header>
   <Security s:actor="IntervenantEmetteur" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:Reference URI="#PJC_01" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">oNbIWOzgYk4X9634QnN5uA4bTHc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
pohyKWQgfhSNe1BC/QJbR/CsDP8hSaJyQeoyJJ6TYkDa4xs7UznQV+heP/lK7zQH3jRaGO61OxhB
+rHpIVlYHl2vHRBCp6+dWu+e2/e16DfMOz2zb9K55+24GhOP3wo26riduDWg6BGQeKGCwLxyvn3r
KIe3nU/00hc4f/duh4M=
</ds:SignatureValue>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Certificate xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
MIIB6jCCAVMCBEeCcWUwDQYJKoZIhvcNAQEEBQAwPDELMAkGA1UEBhMCQ0ExDDAKBgNVBAoTA1BK
QzERMA8GA1UECxMIQ2VudHJlUngxDDAKBgNVBAMTA0pDTDAeFw0wODAxMDcxODM3MjVaFw0wODA0
MDYxODM3MjVaMDwxCzAJBgNVBAYTAkNBMQwwCgYDVQQKEwNQSkMxETAPBgNVBAsTCENlbnRyZVJ4
MQwwCgYDVQQDEwNKQ0wwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOQWVGHiDaV7lcDNWhZy
L2+nR66VAjgryXio6wh4dhuqTU+XSAcSlpTSUh6OBcScTQsKvqci3O3rfUpYh0l6WC6vBOb9M1Rh
MDne6NmUtEx2LP/iJkutob+joO08LKx4g73NMuPgjlYVRMfXvFb92mzgBuxpM0RyctcDeNazayCP
AgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAi216ZxtAIOxZgIpDUfAyElsPTKEt/FKmmX90DgNeQNt4
zGWeJZJKwlnFkxfa0U64puTPw6BZscBCUhkzRUpzPT0Rxc5iPaGnq9xPiYsf8T3Uqx5+bD++em9z
nEKBTfKd7mM6JQAKKq7wlcYsKHcfupsHITRnYmPJ0F+fLVY/B4Y=
</ds:X509Certificate>
</ds:X509Data>
<ds:KeyValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:RSAKeyValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Modulus xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
5BZUYeINpXuVwM1aFnIvb6dHrpUCOCvJeKjrCHh2G6pNT5dIBxKWlNJSHo4FxJxNCwq+pyLc7et9
SliHSXpYLq8E5v0zVGEwOd7o2ZS0THYs/+ImS62hv6Og7TwsrHiDvc0y4+COVhVEx9e8Vv3abOAG
7GkzRHJy1wN41rNrII8=
</ds:Modulus>
<ds:Exponent xmlns:ds="http://www.w3.org/2000/09/xmldsig#">AQAB</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</ds:Signature></Security>
</s:Header>
<s:Body Id="PJC_01">
Some text to sign. </s:Body>
</s:Envelope>


Java code:


import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureInput;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Constants;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;


public class SignXMLDetached {

    /** {@link org.apache.commons.logging} logging facility */
    static org.apache.commons.logging.Log log =
        org.apache.commons.logging.LogFactory.getLog(SignXMLDetached.class.getName());

    // Name of the output file.
    private static final String OUTPUT_FILE_NAME = "signature.xml";

    // All the parameters for the keystore (RSA)
    private String keystoreType = "JKS";
    private String algoSignature = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;

    /**
     * This is sample test. It call the method that will sign an XML
     * document represented as a Striong object.
     *
     * @param unused Arguments are for main signature but are not used.
     * @throws Exception If any of the exception are encountered such
     *         as file not found, xml parsing errors, xml signature error, etc...
     */
    public static void main(String unused[]) throws Exception {
        String keystorePass = "ab987c";
        String privateKeyAlias = "test";
        String privateKeyPass = "kpi135";
        String keystoreFile = "keystore/pjc.jks";
       
        String xmlStream =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            +"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
            +"<s:Header>\n"
            +"   <Security s:actor=\"IntervenantEmetteur\" xmlns=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">\n"
            +"    </Security>\n"
            +"</s:Header>\n"
            +"<s:Body Id=\"PJC_01\">\n"
            +"Some text to sign."
            +" </s:Body>\n"
            +"</s:Envelope>\n";

        SignXMLDetached signXml = new SignXMLDetached();
        String signedXML = signXml.signIt(keystoreFile, keystorePass, privateKeyAlias,
                                          privateKeyPass, xmlStream);  

        FileWriter out = new FileWriter(OUTPUT_FILE_NAME);
        out.write(signedXML);
        out.flush();
        out.close();

        System.out.println("Finished signing. View file in '"+ OUTPUT_FILE_NAME +"'.");
    }

    /**
     * This method create an XML document using the given String object.
     * Then we transform (normalize) add key information and sign the XML
     * document. Finally we convert document to a String object that represents the XML document.
     * @param keyStorePath : name and location of the keystore file.
     * @param keystorePass : the password to open keystore.
     * @param privateKeyAlias : the private key and certificate alias as stored inside the keystore.
     * @param privateKeyPass : the private key password needed to retrieve private key.
     * @param strXML : A String object that represents the XML document to sign.
     * @return Returns a String representing the sign XML document.
     * @throws Exception If any of the exception are encountered such
     *         as file not found, xml parsing errors, xml signature error, etc...
     */
    public String signIt(String keyStorePath, String keystorePass,
            String privateKeyAlias, String privateKeyPass, String strXML)
    throws Exception {
        org.apache.xml.security.Init.init();

        KeyStore ks = KeyStore.getInstance(keystoreType);
        FileInputStream fis = new FileInputStream(keyStorePath);

        // Load the keystore information.
        ks.load(fis, keystorePass.toCharArray());

        // Get the private key from keystore (will be used for signing).
        PrivateKey privateKey = (PrivateKey) ks.getKey(privateKeyAlias,
                                                       privateKeyPass.toCharArray());

        // Create a document factory to build the xml file to sign.
        javax.xml.parsers.DocumentBuilderFactory dbf =
            javax.xml.parsers.DocumentBuilderFactory.newInstance();

        // XML Signature needs to be namespace aware
        dbf.setNamespaceAware(true);

        // Create XML document using given string (that represents the xml document).
        javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();  
        org.w3c.dom.Document doc = db.parse(new InputSource(new StringReader(strXML)));
        NodeList nodeList = doc.getElementsByTagName("Security");
        Node root = nodeList.item(0);
               
        // Create the transforms object for the Document/Reference
        Transforms transforms = new Transforms(doc);

        // Canonicalized part of the signature element.
        transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);

        // Create an XML Signature object from the document.
        String baseURI = null;  
        XMLSignature sig = new XMLSignature(doc, baseURI, algoSignature);

        // Add the above Document/Reference to signature.
        // The signature is going to be injected inside the root node.
        root.appendChild(sig.getElement());
        sig.addDocument("#PJC_01", transforms, Constants.ALGO_ID_DIGEST_SHA1);
       
        // Get the certificate from keystore. Then add it in the KeyInfo element
        // along with the public key. Note, this could have its own alias but
        // we will considered it to be the same as the private key alias.
        X509Certificate cert =
            (X509Certificate) ks.getCertificate(privateKeyAlias);
        sig.addKeyInfo(cert);
        sig.addKeyInfo(cert.getPublicKey());
        sig.sign(privateKey);

        // Convert XML Doc to String.
        return xmlToString(doc);
    }

    /*
     * Convert the given xml Document object to a String object.
     * If an error occurs, log it and return a null object.
     *
     * @param doc : A Document object to convert to a String object.
     * @return Returns a String object representing the given Document object.
     */
    private static String xmlToString(org.w3c.dom.Document doc) {
        try {
            Source source = new DOMSource(doc);
            StringWriter stringWriter = new StringWriter();
            Result result = new StreamResult(stringWriter);
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();
            transformer.transform(source, result);
            return stringWriter.getBuffer().toString();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
        return null;
    }
}

 





Jean-Charles Laurent
Analyste / Analyst
Le Groupe Jean Coutu (PJC) Inc.
tél: 450-463-1890 (3363)
fax: 450-646-0567
jclaurent@...
AVERTISSEMENT CONCERNANT LA CONFIDENTIALITE

Ce message, incluant ses pieces jointes, est strictement reserve a l'usage de l'individu ou de l'entite a qui il est
adresse et contient de l'information privilegiee et confidentielle. La dissemination, distribution ou copie de cette
communication est strictement prohibee.  Si vous n'etes pas le destinataire projete veuillez retourner
immediatement un courrier electronique a l'expediteur et effacez toutes les copies.


CONFIDENTIALITY WARNING

This message, including its attachments, is strictly intended for the use of the individual or the entity to which it is addressed
and contains privileged and confidential information. Disclosure, distribution or copy of this communication is strictly
prohibited. If you are not the intended recipient please notify us immediately by returning the e-mail to the originator and
deleting all copies.


pjc.jks (1K) Download Attachment

Re: question

by Brent Putman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This is a fairly common issue.  If you're signing a document and then inserting the ds:Signature into another context where it will be verified (e.g. inside a SOAP Envelope, either Security header or an enveloped signature in the body), then you pretty much have to use exclusive canonicalization as the algorithm for the ds:Signature/ds:CanonicalizatonMethod.  This is because if you instead use inclusive c14n, including it as a subordinate element within another document will cause the visible namespaces to be included as a part of the ds:SignedInfo, and this will almost certainly break the signature on verification.  The same is true for the c14n transform of any same-document References included in signature (assuming the referent has also been inserted into a new context that has additional visible namespaces).

The Apache xmlsec lib has various means by which you can set the c14n method prior to signing, it probably just defaults to inclusive.

--Brent


Jean-Charles Laurent wrote:

What I am trying to do is to sign a the BODY element of the XML file (detached form) and insert the signature inside the <Security> tag.

I am using the apache security package (1.4.1). I seem to be able to verify the signature on my side but it cannot be verified on the client side.

One thing I haved noticed is (andI can't explain);

        CanonicalizationMethod Algorithim is "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>

but the

        Transform Algorithm is "http://www.w3.org/2001/10/xml-exc-c14n#"
         <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>


Hope someone will be able to help me out as I am running out of ideas.

Thanks

JC


Below is the output file followed by the java code and the keystore used. Please comment the code if you wish. I am new to XML Signature.

Here is the output xml file:

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:Header>
   <Security s:actor="IntervenantEmetteur" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:Reference URI="#PJC_01" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">oNbIWOzgYk4X9634QnN5uA4bTHc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
pohyKWQgfhSNe1BC/QJbR/CsDP8hSaJyQeoyJJ6TYkDa4xs7UznQV+heP/lK7zQH3jRaGO61OxhB
+rHpIVlYHl2vHRBCp6+dWu+e2/e16DfMOz2zb9K55+24GhOP3wo26riduDWg6BGQeKGCwLxyvn3r
KIe3nU/00hc4f/duh4M=
</ds:SignatureValue>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Certificate xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
MIIB6jCCAVMCBEeCcWUwDQYJKoZIhvcNAQEEBQAwPDELMAkGA1UEBhMCQ0ExDDAKBgNVBAoTA1BK
QzERMA8GA1UECxMIQ2VudHJlUngxDDAKBgNVBAMTA0pDTDAeFw0wODAxMDcxODM3MjVaFw0wODA0
MDYxODM3MjVaMDwxCzAJBgNVBAYTAkNBMQwwCgYDVQQKEwNQSkMxETAPBgNVBAsTCENlbnRyZVJ4
MQwwCgYDVQQDEwNKQ0wwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOQWVGHiDaV7lcDNWhZy
L2+nR66VAjgryXio6wh4dhuqTU+XSAcSlpTSUh6OBcScTQsKvqci3O3rfUpYh0l6WC6vBOb9M1Rh
MDne6NmUtEx2LP/iJkutob+joO08LKx4g73NMuPgjlYVRMfXvFb92mzgBuxpM0RyctcDeNazayCP
AgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAi216ZxtAIOxZgIpDUfAyElsPTKEt/FKmmX90DgNeQNt4
zGWeJZJKwlnFkxfa0U64puTPw6BZscBCUhkzRUpzPT0Rxc5iPaGnq9xPiYsf8T3Uqx5+bD++em9z
nEKBTfKd7mM6JQAKKq7wlcYsKHcfupsHITRnYmPJ0F+fLVY/B4Y=
</ds:X509Certificate>
</ds:X509Data>
<ds:KeyValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:RSAKeyValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Modulus xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
5BZUYeINpXuVwM1aFnIvb6dHrpUCOCvJeKjrCHh2G6pNT5dIBxKWlNJSHo4FxJxNCwq+pyLc7et9
SliHSXpYLq8E5v0zVGEwOd7o2ZS0THYs/+ImS62hv6Og7TwsrHiDvc0y4+COVhVEx9e8Vv3abOAG
7GkzRHJy1wN41rNrII8=
</ds:Modulus>
<ds:Exponent xmlns:ds="http://www.w3.org/2000/09/xmldsig#">AQAB</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</ds:Signature></Security>
</s:Header>
<s:Body Id="PJC_01">
Some text to sign. </s:Body>
</s:Envelope>


Java code:


import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureInput;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Constants;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;


public class SignXMLDetached {

    /** {@link org.apache.commons.logging} logging facility */
    static org.apache.commons.logging.Log log =
        org.apache.commons.logging.LogFactory.getLog(SignXMLDetached.class.getName());

    // Name of the output file.
    private static final String OUTPUT_FILE_NAME = "signature.xml";

    // All the parameters for the keystore (RSA)
    private String keystoreType = "JKS";
    private String algoSignature = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;

    /**
     * This is sample test. It call the method that will sign an XML
     * document represented as a Striong object.
     *
     * @param unused Arguments are for main signature but are not used.
     * @throws Exception If any of the exception are encountered such
     *         as file not found, xml parsing errors, xml signature error, etc...
     */
    public static void main(String unused[]) throws Exception {
        String keystorePass = "ab987c";
        String privateKeyAlias = "test";
        String privateKeyPass = "kpi135";
        String keystoreFile = "keystore/pjc.jks";
       
        String xmlStream =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            +"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
            +"<s:Header>\n"
            +"   <Security s:actor=\"IntervenantEmetteur\" xmlns=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">\n"
            +"    </Security>\n"
            +"</s:Header>\n"
            +"<s:Body Id=\"PJC_01\">\n"
            +"Some text to sign."
            +" </s:Body>\n"
            +"</s:Envelope>\n";

        SignXMLDetached signXml = new SignXMLDetached();
        String signedXML = signXml.signIt(keystoreFile, keystorePass, privateKeyAlias,
                                          privateKeyPass, xmlStream);  

        FileWriter out = new FileWriter(OUTPUT_FILE_NAME);
        out.write(signedXML);
        out.flush();
        out.close();

        System.out.println("Finished signing. View file in '"+ OUTPUT_FILE_NAME +"'.");
    }

    /**
     * This method create an XML document using the given String object.
     * Then we transform (normalize) add key information and sign the XML
     * document. Finally we convert document to a String object that represents the XML document.
     * @param keyStorePath : name and location of the keystore file.
     * @param keystorePass : the password to open keystore.
     * @param privateKeyAlias : the private key and certificate alias as stored inside the keystore.
     * @param privateKeyPass : the private key password needed to retrieve private key.
     * @param strXML : A String object that represents the XML document to sign.
     * @return Returns a String representing the sign XML document.
     * @throws Exception If any of the exception are encountered such
     *         as file not found, xml parsing errors, xml signature error, etc...
     */
    public String signIt(String keyStorePath, String keystorePass,
            String privateKeyAlias, String privateKeyPass, String strXML)
    throws Exception {
        org.apache.xml.security.Init.init();

        KeyStore ks = KeyStore.getInstance(keystoreType);
        FileInputStream fis = new FileInputStream(keyStorePath);

        // Load the keystore information.
        ks.load(fis, keystorePass.toCharArray());

        // Get the private key from keystore (will be used for signing).
        PrivateKey privateKey = (PrivateKey) ks.getKey(privateKeyAlias,
                                                       privateKeyPass.toCharArray());

        // Create a document factory to build the xml file to sign.
        javax.xml.parsers.DocumentBuilderFactory dbf =
            javax.xml.parsers.DocumentBuilderFactory.newInstance();

        // XML Signature needs to be namespace aware
        dbf.setNamespaceAware(true);

        // Create XML document using given string (that represents the xml document).
        javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();  
        org.w3c.dom.Document doc = db.parse(new InputSource(new StringReader(strXML)));
        NodeList nodeList = doc.getElementsByTagName("Security");
        Node root = nodeList.item(0);
               
        // Create the transforms object for the Document/Reference
        Transforms transforms = new Transforms(doc);

        // Canonicalized part of the signature element.
        transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);

        // Create an XML Signature object from the document.
        String baseURI = null;  
        XMLSignature sig = new XMLSignature(doc, baseURI, algoSignature);

        // Add the above Document/Reference to signature.
        // The signature is going to be injected inside the root node.
        root.appendChild(sig.getElement());
        sig.addDocument("#PJC_01", transforms, Constants.ALGO_ID_DIGEST_SHA1);
       
        // Get the certificate from keystore. Then add it in the KeyInfo element
        // along with the public key. Note, this could have its own alias but
        // we will considered it to be the same as the private key alias.
        X509Certificate cert =
            (X509Certificate) ks.getCertificate(privateKeyAlias);
        sig.addKeyInfo(cert);
        sig.addKeyInfo(cert.getPublicKey());
        sig.sign(privateKey);

        // Convert XML Doc to String.
        return xmlToString(doc);
    }

    /*
     * Convert the given xml Document object to a String object.
     * If an error occurs, log it and return a null object.
     *
     * @param doc : A Document object to convert to a String object.
     * @return Returns a String object representing the given Document object.
     */
    private static String xmlToString(org.w3c.dom.Document doc) {
        try {
            Source source = new DOMSource(doc);
            StringWriter stringWriter = new StringWriter();
            Result result = new StreamResult(stringWriter);
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();
            transformer.transform(source, result);
            return stringWriter.getBuffer().toString();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
        return null;
    }
}

 





Jean-Charles Laurent
Analyste / Analyst
Le Groupe Jean Coutu (PJC) Inc.
tél: 450-463-1890 (3363)
fax: 450-646-0567
jclaurent@...
AVERTISSEMENT CONCERNANT LA CONFIDENTIALITE

Ce message, incluant ses pieces jointes, est strictement reserve a l'usage de l'individu ou de l'entite a qui il est
adresse et contient de l'information privilegiee et confidentielle. La dissemination, distribution ou copie de cette
communication est strictement prohibee.  Si vous n'etes pas le destinataire projete veuillez retourner
immediatement un courrier electronique a l'expediteur et effacez toutes les copies.


CONFIDENTIALITY WARNING

This message, including its attachments, is strictly intended for the use of the individual or the entity to which it is addressed
and contains privileged and confidential information. Disclosure, distribution or copy of this communication is strictly
prohibited. If you are not the intended recipient please notify us immediately by returning the e-mail to the originator and
deleting all copies.

Parent Message unknown Re: question

by Brent Putman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Well, first off: you can set the boolean system property "org.apache.xml.security.ignoreLineBreaks" to true to supposedly get it to not emit most (all?) newlines in the signature output.  I haven't used it personally, not sure if that that gets you what you are asking for.

However:  this really isn't the solution to the problem.  If the signature is valid when you created it (with or without linebreaks), then it's valid, period. If the remote peer fails to validate it successfully, then there are several possibilities including: 1) the signature is getting corrupted prior to the validation, possibly as a part of the serialization or deserialization process on either side.  The addition or removal of whitespace is a common error here (or conversion, as in conversion of Unix-style newlines to windows CRLF form) 2) they aren't using the right key to validate (what was the exact validation error on their side, if any?)  3) their XML Signature impl is broken.  Specifically, if they expect or require no whitespace in the SignedInfo or something like that, then that's broken behavior.


--Brent


Jean-Charles Laurent wrote:

Thanks Brent

I was missing the Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS parameter in the constructor.

XMLSignature sig = new XMLSignature(doc, baseURI, algoSignature, Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

However, it is still not valid at the third party's end. Someone here managed to send a valid xml file that was generated with dot.net and the only thing that is different (from what we can see) is that the SignedInfo is on a single line. It seems that with dot-net program they used an option that omits white space or something like that.

Is there something that I can use to get the complet SignedInfo element on a single line?

Thanks for your help


Note:

they have this on a single line:

<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="#PJC_01"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>CtRKtN9v0WVA7onJ4OBA9PSaz/U=</DigestValue></Reference></SignedInfo>


where the output with apache is something like:

<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="#PJC_01">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>CtRKtN9v0WVA7onJ4OBA9PSaz/U=</DigestValue>
</Reference>
</SignedInfo>

Jean-Charles Laurent
Analyste / Analyst
Le Groupe Jean Coutu (PJC) Inc.
tél: 450-463-1890 (3363)
fax: 450-646-0567
jclaurent@...




Parent Message unknown Re: question

by Brent Putman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 


Jean-Charles Laurent wrote:

Thanks Brent,

I agree, the removel of line break is not the perfect solution. My guest would be be some kind of serialization or deserialization problem.

That's probably the most common problem with signatures that fail to validate after being sent to a remote peer.


The xml is signed on a AS400 (using java), then validated on a windows PC with BizTalk and dot-net. We dot not have control on the PC side so we must do with what we have.


Well it sounds like the problem is on their side, not yours, unless you are corrupting when you serialize.  Have you tried signing, writing it out to a file etc, then rereading and parsing and validating on your side?  If that works, then it's almost certainly a problem on their side (unless there's a bug in Apache XML Security or something).


Other cies have managed to sign in Java (using Bouncy Castle) it seems.

Well, BC just provides the crypto (JCA/JCE support), not XML Signature support AFAIK, so I doubt that's relevant.  You can also configure the BC JCE and use that with Apache XML Security if you like.  I doubt that is the problem, however.


To set the system property we need to do something like this?

   System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");

Yes, or you can specify as an arg to the JVM with a -D parameter, e.g.  -Dorg.apache.xml.security.ignoreLineBreaks=true




If so when should do this. I'am doing it like this:

public String signIt(String keyStorePath, String keystorePass,
       String privateKeyAlias, String privateKeyPass, String strXML) throws Exception {

   //
   System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");      
   org.apache.xml.security.Init.init();


This gets set as a static member variable, so it's only going to get evaluated once, when the class loads.  If you do with System.setProperty, you'd have to make sure to do very early on in your code, before the XMLUtils class gets loaded by the classloader.  The safest/surest way is probably just to use a -D arg to your JVM.

org.apache.xml.security.utils.XMLUtils:

  private static boolean ignoreLineBreaks = false;
   static {
      try {
         ignoreLineBreaks = Boolean.getBoolean
        ("org.apache.xml.security.ignoreLineBreaks");
      } catch (Exception e) {
         // ignore exceptions
      }
   }



--Brent






Parent Message unknown Re: question

by Brent Putman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

(Please hit reply-to-all when you reply so that your email goes to the list and not just to me).



Jean-Charles Laurent wrote:

Hi Brent,

Yes I did write to a file and I validate it with a Java tool (found on the web) or with a Java program that I got in the sample directory of xml security package. I am quite sure what we are sending is a valid xml signature file. I think this is an issue with dot-net.

Well, then ultimately it's not your problem, and if I were you, I personally would not waste my time trying to work around someone else's broken code.  Ask them to fix it.




Here someone did a signature with a dot-net program and for it to validate on the peer side, they needed to use some dot-net parameter to prevent blanks or newline characters in the signature. We know that it is not being corrupted on the way (since we can send the dot-net result and it is valide). Their resulting sign XML file has the SignedInfo tag on a single line with no carriage return characters. This is what I am trying to reproduce with my Java application.

I understand.  Good luck.  Even if you get the line breaks feature working, realize this very may not actually fix your problem, given everything that you've said.  I'd be very wary.

Out of curiosity: do you know whether the .NET code that is being used to validate is some standard .NET XML Signature library, or something that someone just wrote up for this particular application?  If the former, I'd be interested to know what it is, just for future reference...



I tried to set the parameter "org.apache.xml.security.ignoreLineBreaks" and I semm to have no effect on my signature. I must be doing something wrong. I tried as you suggested via the -D option ("java -Dorg.apache.xml.security.ignoreLineBreaks=true ..."). To make sure the parameter is set correctly, I do a

         System.out.println("ignoreLineBreaks="+System.getProperty("org.apache.xml.security.ignoreLineBreaks"));

which displays true.


I haven't personally used this feature, perhaps someone on the Apache xml security dev team can comment.  But one thing is (and sorry I didn't realize this before): according to SVN the last Java xmlsec release (1.4.1) was tagged in May 2007, and this ignore line breaks feature wasn't added until October 2007, so you would have to be running with a xmlsec jar built from recent source, or perhaps try with the 1.4.2 beta (or release candidate?) that I believe Sean currently has out there somewhere.

--Brent


Re: question

by Jean-Charles Laurent :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Thanks Brent for all your help and quick response.

We finaly talk to the client/3rd-party and convinced them that they were doing something wrong. They finaly admitted that they were removing carriage returns and blanks spaces in the signed info.




Jean-Charles Laurent
Analyste / Analyst
Le Groupe Jean Coutu (PJC) Inc.
tél: 450-463-1890 (3363)
fax: 450-646-0567
jclaurent@...



Brent Putman <putmanb@...>

27/05/2008 06:10 PM

A
Jean-Charles Laurent <jclaurent@...>, security-dev@...
cc
Objet
Re: question





(Please hit reply-to-all when you reply so that your email goes to the list and not just to me).



Jean-Charles Laurent wrote:


Hi Brent,


Yes I did write to a file and I validate it with a Java tool (found on the web) or with a Java program that I got in the sample directory of xml security package. I am quite sure what we are sending is a valid xml signature file. I think this is an issue with dot-net.


Well, then ultimately it's not your problem, and if I were you, I personally would not waste my time trying to work around someone else's broken code.  Ask them to fix it.




Here someone did a signature with a dot-net program and for it to validate on the peer side, they needed to use some dot-net parameter to prevent blanks or newline characters in the signature. We know that it is not being corrupted on the way (since we can send the dot-net result and it is valide). Their resulting sign XML file has the SignedInfo tag on a single line with no carriage return characters. This is what I am trying to reproduce with my Java application.

I understand.  Good luck.  Even if you get the line breaks feature working, realize this very may not actually fix your problem, given everything that you've said.  I'd be very wary.

Out of curiosity: do you know whether the .NET code that is being used to validate is some standard .NET XML Signature library, or something that someone just wrote up for this particular application?  If the former, I'd be interested to know what it is, just for future reference...



I tried to set the parameter "
org.apache.xml.security.ignoreLineBreaks" and I semm to have no effect on my signature. I must be doing something wrong. I tried as you suggested via the -D option ("java -Dorg.apache.xml.security.ignoreLineBreaks=true ..."). To make sure the parameter is set correctly, I do a

         
System.out.println("ignoreLineBreaks="+System.getProperty("org.apache.xml.security.ignoreLineBreaks"));

which displays true.



I haven't personally used this feature, perhaps someone on the Apache xml security dev team can comment.  But one thing is (and sorry I didn't realize this before): according to SVN the last Java xmlsec release (1.4.1) was tagged in May 2007, and this ignore line breaks feature wasn't added until October 2007, so you would have to be running with a xmlsec jar built from recent source, or perhaps try with the 1.4.2 beta (or release candidate?) that I believe Sean currently has out there somewhere.

--Brent

AVERTISSEMENT CONCERNANT LA CONFIDENTIALITE

Ce message, incluant ses pieces jointes, est strictement reserve a l'usage de l'individu ou de l'entite a qui il est
adresse et contient de l'information privilegiee et confidentielle. La dissemination, distribution ou copie de cette
communication est strictement prohibee.  Si vous n'etes pas le destinataire projete veuillez retourner
immediatement un courrier electronique a l'expediteur et effacez toutes les copies.


CONFIDENTIALITY WARNING

This message, including its attachments, is strictly intended for the use of the individual or the entity to which it is addressed
and contains privileged and confidential information. Disclosure, distribution or copy of this communication is strictly
prohibited. If you are not the intended recipient please notify us immediately by returning the e-mail to the originator and
deleting all copies.
LightInTheBox - Buy quality products at wholesale price!