import com.ibm.xml.crypto.dsig.*;
import com.ibm.xml.crypto.dsig.dom.*;
import com.ibm.xml.crypto.dsig.dom.transform.*;
import javax.xml.crypto.*;
import javax.xml.crypto.dom.*;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.spec.*;
import javax.xml.crypto.dsig.keyinfo.*;
import javax.xml.crypto.dsig.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.*;
import java.security.*;
import java.io.*;
import java.util.*;
import org.w3c.dom.*;

/****************************************************
*  Adapted from Sun example available at: 
*  http://download.java.net/jdk6/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html
*****************************************************/

public class XMLDSigSample {

  public static void main(String[] args){
    if (args.length == 0) {
	System.err.println("Must specify document\n  java XMLDSigSample <document>");
	System.exit(-1);
    }
    try {
      //loading provider if it is not added in the java.security file
      Class provClass = java.lang.Class.forName("com.ibm.xml.crypto.IBMXMLCryptoProvider");
      Provider prov = (Provider)provClass.newInstance();
      java.security.Security.addProvider(prov);

      
      //creating an XMLSignatureFactory with for "DOM"
      XMLSignatureFactory xmlsigfac = XMLSignatureFactory.getInstance("DOM", "IBMXMLCRYPTO");


      //read a document from the command-line
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      dbf.setNamespaceAware(true);
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document d = db.parse(new FileInputStream(args[0]));


      //Generate a keypair for signing
      KeyPairGenerator keypairgen = KeyPairGenerator.getInstance("DSA");
      keypairgen.initialize(512);
      KeyPair keypair = keypairgen.generateKeyPair();

      
      DOMSignContext dsc = new DOMSignContext
      (keypair.getPrivate(), d.getDocumentElement());
      
      //Assembling Signature pieces
      Reference ref = xmlsigfac.newReference
      ("", xmlsigfac.newDigestMethod(DigestMethod.SHA1, null),
      Collections.singletonList
      (xmlsigfac.newTransform(Transform.ENVELOPED,
        (TransformParameterSpec) null)), null, null);

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


      KeyInfoFactory kif = xmlsigfac.getKeyInfoFactory();
      KeyValue kv = kif.newKeyValue(keypair.getPublic());
      KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));

      //create an XMLSignature object
      XMLSignature signature = xmlsigfac.newXMLSignature(si, ki);

      //sign the document
      signature.sign(dsc);

      //output signed document to System.out
      OutputStream os;
      os = System.out;
      TransformerFactory tf = TransformerFactory.newInstance();
      Transformer trans = tf.newTransformer();
      trans.transform(new DOMSource(d), new StreamResult(os));


    } catch (Exception e){
        System.err.println("Sample Failed");
        System.err.println(e.getMessage());
    }
  }

}
