/*
 * Copyright 2006 The Apache Software Foundation.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
/*
 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
 */
package javax.xml.crypto.test.dsig;

import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dom.*;
import javax.xml.crypto.dsig.keyinfo.*;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import java.security.*;
import java.util.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;

import junit.framework.*;

/**
 * This is a simple example of generating and validating a Detached XML 
 * Signature using the JSR 105 API. The resulting signature will look 
 * like (key and signature values will be different):
 *
 * <pre><code>
 * <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#dsa-sha1"/>
 *     <Reference URI="http://www.w3.org/TR/xml-stylesheet">
 *       <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
 *       <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
 *     </Reference>
 *   </SignedInfo>
 *   <SignatureValue>
 *     DpEylhQoiUKBoKWmYfajXO7LZxiDYgVtUtCNyTgwZgoChzorA2nhkQ==
 *   </SignatureValue>
 *   <KeyInfo>
 *     <KeyValue>
 *       <DSAKeyValue>
 *	   <P>
 *           rFto8uPQM6y34FLPmDh40BLJ1rVrC8VeRquuhPZ6jYNFkQuwxnu/wCvIAMhukPBL
 *           FET8bJf/b2ef+oqxZajEb+88zlZoyG8g/wMfDBHTxz+CnowLahnCCTYBp5kt7G8q
 *           UobJuvjylwj1st7V9Lsu03iXMXtbiriUjFa5gURasN8=
 *         </P>
 *         <Q>
 *           kEjAFpCe4lcUOdwphpzf+tBaUds=
 *         </Q>
 *         <G>
 *           oe14R2OtyKx+s+60O5BRNMOYpIg2TU/f15N3bsDErKOWtKXeNK9FS7dWStreDxo2
 *           SSgOonqAd4FuJ/4uva7GgNL4ULIqY7E+mW5iwJ7n/WTELh98mEocsLXkNh24HcH4
 *           BZfSCTruuzmCyjdV1KSqX/Eux04HfCWYmdxN3SQ/qqw=
 *         </G>
 *         <Y>
 *           pA5NnZvcd574WRXuOA7ZfC/7Lqt4cB0MRLWtHubtJoVOao9ib5ry4rTk0r6ddnOv
 *           AIGKktutzK3ymvKleS3DOrwZQgJ+/BDWDW8kO9R66o6rdjiSobBi/0c2V1+dkqOg
 *           jFmKz395mvCOZGhC7fqAVhHat2EjGPMfgSZyABa7+1k=
 *         </Y>
 * 	 </KeyValue>
 *     </DSAKeyValue>
 *   </KeyInfo>
 * </Signature>
 *
 * @author Sean Mullan
 */
public class DetachedTest extends TestCase {

    static {
        Security.insertProviderAt
            (new org.jcp.xml.dsig.internal.dom.XMLDSigRI(), 1);
    }

    public DetachedTest(String name) {
        super(name);
    }
    
    public void test() {
        try {
            //
    	    // PART 1 : Creating the detached signature
    	    //
    
    	    // Create a factory that will be used to generate the signature 
            // structures
    	    XMLSignatureFactory fac = XMLSignatureFactory.getInstance
                ("DOM", new org.jcp.xml.dsig.internal.dom.XMLDSigRI());
    
    	    // Create a Reference to an external URI that will be digested
    	    Reference ref = fac.newReference
                ("http://www.w3.org/TR/xml-stylesheet", 
		fac.newDigestMethod(DigestMethod.SHA1, null));
    
    	    // Create a DSA KeyPair
    	    KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
    	    kpg.initialize(1024, 
		new SecureRandom("not so random bytes".getBytes()));
    	    KeyPair kp = kpg.generateKeyPair();
    
    	    // Create a KeyValue containing the generated DSA PublicKey
    	    KeyInfoFactory kif = fac.getKeyInfoFactory();
    	    KeyValue kv = kif.newKeyValue(kp.getPublic());
    
    	    // Create a KeyInfo and add the KeyValue to it
    	    KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));

	    // Create SignedInfo
	    SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(
		CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, 
		(C14NMethodParameterSpec) null), 
		fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null), 
		Collections.singletonList(ref));

	    // Create XMLSignature
	    XMLSignature signature = fac.newXMLSignature(si,ki,null,null,null);
    
    	    // Create an XMLSignContext and set the 
            // DSA PrivateKey for signing
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            dbf.setValidating(false);
            Document doc = dbf.newDocumentBuilder().newDocument();
    	    DOMSignContext signContext = new DOMSignContext(kp.getPrivate(), doc);
    	    signContext.putNamespacePrefix(XMLSignature.XMLNS, "ds");

    	    // Generate (and sign) the XMLSignature
    	    signature.sign(signContext);
    
    	    //
    	    // PART 2 : Validating the detached signature
    	    //
    
    	    // Create a XMLValidateContext & set the DSAPublicKey for validating
	    XMLValidateContext vc = new DOMValidateContext(kp.getPublic(),
		doc.getDocumentElement());
    
    	    // Validate the Signature (generated above)
    	    boolean coreValidity = signature.validate(vc); 
    
    	    // Check core validation status
    	    if (coreValidity == false) {
    	        // check the validation status of each Reference
    	        Iterator i = signature.getSignedInfo().getReferences().iterator();
    	        for (int j=0; i.hasNext(); j++) {
		    Reference reference = (Reference) i.next();
    		    boolean refValid = reference.validate(vc);
    	        }
    	        fail("Signature failed core validation");
    	    }
    
    	    // You can also validate an XML Signature which is in XML format.
    	    // Unmarshal and validate an XMLSignature from a DOMValidateContext
    	    signature = fac.unmarshalXMLSignature(vc);
    	    coreValidity = signature.validate(vc);
    	    assertTrue("Core validity of unmarshalled XMLSignature is false", 
	        coreValidity);
        } catch(Exception ex) {
            fail("Exception: " + ex);
        }
    }

    public static void main(String[] args) throws Exception {
        DetachedTest dt = new DetachedTest("");
        dt.test();
    }
}
