package testgenerator;

import iaik.ixsil.algorithms.CanonicalizationAlgorithmImplCanonicalXML;
import iaik.ixsil.algorithms.DigestAlgorithmImplSHA1;
import iaik.ixsil.algorithms.SignatureAlgorithmImplRSA;
import iaik.ixsil.algorithms.Transform;
import iaik.ixsil.algorithms.TransformImplBase64Decode;
import iaik.ixsil.algorithms.TransformImplEnvelopedSignature;
import iaik.ixsil.algorithms.TransformImplXSLT;
import iaik.ixsil.core.Position;
import iaik.ixsil.core.Signer;
import iaik.ixsil.core.SignerManifest;
import iaik.ixsil.core.SignerReference;
import iaik.ixsil.core.SignerSignature;
import iaik.ixsil.core.SignerSignedInfo;
import iaik.ixsil.init.IXSILConstants;
import iaik.ixsil.keyinfo.KeyManagerImpl;
import iaik.ixsil.keyinfo.x509.KeyProviderImplX509Data;
import iaik.ixsil.keyinfo.x509.X509Data;
import iaik.ixsil.util.URI;

import iaik.pkcs.pkcs12.PKCS12;
import iaik.utils.Base64OutputStream;

import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import at.gv.egovernment.moa.util.Base64Utils;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.EntityResolverChain;
import at.gv.egovernment.moa.util.MOAEntityResolver;
import at.gv.egovernment.moa.util.MOAErrorHandler;
import at.gv.egovernment.moa.util.StreamEntityResolver;

/**
 * @author Gregor Karlinger
 */
public class TestGeneratorFeature41 extends TestCases
{

  String datadirectory = "data/feature41/";

  public static void main(String[] args) throws Exception
  {
    TestGeneratorFeature41 testcase = new TestGeneratorFeature41();

    testcase.create001();
    testcase.create002();
    testcase.create003();
    testcase.create004();
    testcase.create005();
  }

  /* ==================================================================================================== */

  public TestGeneratorFeature41() throws Exception
  {

    super();

    // Set config properties
    configuration_.setProperty("TestClass", "TestGeneratorFeature41");

    iaik.security.provider.IAIK.addAsJDK14Provider();
    iaik.security.ecc.provider.ECCProvider.addAsProvider();
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public Document createPKCS12Sig(
    String TestNumber,
    String data,
    boolean env,
    boolean mani,
    String data2,
    boolean env2)
    throws Exception
  {
    String resFile =
      configuration_.getProperty("baseDir")
        + datadirectory
        + configuration_.getProperty("TestClass")
        + "."
        + TestNumber
        + ".Res.xml";

    PKCS12 pkcs12 =
      decryptPKCS12(configuration_.getProperty("PKCS12file"), configuration_.getProperty("PKCS12password"));

    // Create signature generator
    URI baseURI = new URI(IXSILConstants.DUMMY_ABSURI_);
    Signer signer = new Signer(baseURI);

    // Configure signed information

    // Get interface for signed information
    SignerSignature signature = signer.getSignature();
    SignerSignedInfo signedInfo = signer.getSignature().getSignerSignedInfo();

    // Set canonicalization algorithm
    CanonicalizationAlgorithmImplCanonicalXML c14nAlg = new CanonicalizationAlgorithmImplCanonicalXML();
    signedInfo.setCanonicalizationAlgorithm(c14nAlg);

    // Set signature algorithm
    SignatureAlgorithmImplRSA signatureAlg = new SignatureAlgorithmImplRSA();
    RSAPrivateKey privateKey = getPrivateKey(pkcs12);
    signatureAlg.setSignerKey(privateKey);
    signedInfo.setSignatureAlgorithm(signatureAlg);

    if (!mani)
    {
      SignerReference reference = signedInfo.createReference();
      if (env)
      {
        iaik.ixsil.core.Object object = null;
        //object = signature.createObject(data);
        if (data.startsWith("<xml"))
        {
          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc = db.parse(new ByteArrayInputStream(data.getBytes()));

          object = signature.createObject(doc.getDocumentElement());
        }
        else if (data.startsWith("<Testdaten"))
        {

          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc =
            db.parse(
              new ByteArrayInputStream(("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + data).getBytes()));

          object = signature.createObject(doc.getDocumentElement());
        }
        else if (data.startsWith("b64:"))
        {
          data = data.substring(4);
          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc = db.newDocument();
          Element root = doc.createElement("root");
          doc.appendChild(root);
          //String encoded = Base64Utils.encode(data.getBytes());
          String encoded = Base64Utils.encode(data.getBytes());
          /*encoded = replaceStringAll(encoded,"\n","");
          encoded = replaceStringAll(encoded,"\r","");*/
          Text textnode = doc.createTextNode(encoded);

          System.out.println("Encoded:" + encoded);
          //root.appendChild(textnode);

          DocumentFragment df = doc.createDocumentFragment();

          df.appendChild(textnode);

          object = signature.createObject(df);

          TransformImplBase64Decode trans = new TransformImplBase64Decode();
          InputStream s = new ByteArrayInputStream(encoded.getBytes());
          trans.setInput(s, null);

          reference.insertTransformAt(trans, 0);
        }
        else
        {
          object = signature.createObject(data);
        }

        object.setId("signed-data-1-1-1");
        signature.addObject(object);

        DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
        reference.setDigestAlgorithm(digestAlg);

        reference.setURI(new URI("#xpointer(id('signed-data-1-1-1')/node())"));

      }
      else
      {
        // Create and configure reference
        URI refURI = null;
        String baseDir = configuration_.getProperty("baseDir");
        refURI = new URI(data);

        reference.setURI(refURI);
        DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
        reference.setDigestAlgorithm(digestAlg);
      }
      reference.setId("reference-1-1");
      signedInfo.addReference(reference);
    }

    if (data2 != null)
    {
      SignerReference reference = signedInfo.createReference();
      reference = signedInfo.createReference();
      if (env2)
      {
        iaik.ixsil.core.Object object = null;
        if (data2.startsWith("<xml"))
        {
          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc = db.parse(new ByteArrayInputStream(data.getBytes()));

          object = signature.createObject(doc.getDocumentElement());
        }
        else if (data2.startsWith("<Testdaten"))
        {

          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc =
            db.parse(
              new ByteArrayInputStream(("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + data).getBytes()));

          object = signature.createObject(doc.getDocumentElement());
        }
        else
          object = signature.createObject(data2);

        if (!env)
          object.setId("signed-data-1-2-1");
        else
          object.setId("signed-data-1-2-1");
        signature.addObject(object);

        DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
        reference.setDigestAlgorithm(digestAlg);

        if (!env)
          reference.setURI(new URI("#xpointer(id('signed-data-1-2-1')/node())"));
        else
          reference.setURI(new URI("#xpointer(id('signed-data-1-2-1')/node())"));
      }
      else
      {
        // Create and configure reference
        URI refURI = null;
        String baseDir = configuration_.getProperty("baseDir");
        refURI = new URI(data2);

        reference.setURI(refURI);
        DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
        reference.setDigestAlgorithm(digestAlg);
      }
      reference.setId("reference-1-2");
      signedInfo.addReference(reference);
    }

    // Add reference to signature

    if (mani)
    {

      /*iaik.ixsil.core.Object object = null;
      if(env)
          object = signature.createObject(readFile(data));
      else
        object = signature.createObject(data);
        
        object.setId("envelopedData");
        signature.addObject(object);*/
      SignerReference reference = signedInfo.createReference();
      SignerManifest manifest = signer.createManifest();
      SignerReference manifestRef = manifest.createReference();

      DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
      manifestRef.setDigestAlgorithm(digestAlg);

      manifestRef.setURI(new URI(data));
      manifestRef.setId("reference-1-1");

      manifest.addReference(manifestRef);
      manifest.setId("dsig-manifest-1-1");
      iaik.ixsil.core.Object manifestObject = signature.createObject(manifest);
      signature.addObject(manifestObject);
      manifest.computeDigestValues();

      reference = signedInfo.createReference();
      reference.setURI(new URI("#dsig-manifest-1-1"));
      reference.setType(new URI(IXSILConstants.REFERENCETYPE_ATTR_VALUE_MANIFEST_));
      reference.setDigestAlgorithm(new DigestAlgorithmImplSHA1());

      // Add reference to signature
      signedInfo.addReference(reference);

      /*Element envelopedDataElem =
      signer.toDocument().createElement("EnvelopedDataElement");
      
      if(env)
      {
        envelopedDataElem.appendChild(
        signer.toDocument().createTextNode(readFile(data)));
      }
      else
      {
        envelopedDataElem.appendChild(
        signer.toDocument().createTextNode(data));
      }
      
      iaik.ixsil.core.Object object = signature.createObject(envelopedDataElem);
      signature.addObject(object);
      
      // Create Manifest with a single reference pointing to the enveloped data
      SignerManifest manifest = signer.createManifest();
      SignerReference manifestRef = manifest.createReference();
      manifestRef.setURI(
        new URI(
          null,
          null,
          null,
          null,
          "xmlns(dsig="
            + IXSILConstants.NAMESPACE_URI_XMLSIGNATURE_ELEM_
            + ") "
            + "xpointer(here()/ancestor::dsig:Signature[1]/dsig:Object[1]/descendant::node())"));
      manifestRef.setDigestAlgorithm(new DigestAlgorithmImplSHA1());
      manifest.addReference(manifestRef);
      
      // Add Manifest to signature structure (use an Object) and compute digest values for manifest reference
      iaik.ixsil.core.Object manifestObject = signature.createObject(manifest);
      signature.addObject(manifestObject);
      manifest.computeDigestValues();
      
      // Create and configure reference to manifest
      reference = signedInfo.createReference();
      reference.setURI(
        new URI(
          null,
          null,
          null,
          null,
          "xmlns(dsig="
            + IXSILConstants.NAMESPACE_URI_XMLSIGNATURE_ELEM_
            + ") "
            + "xpointer(here()/ancestor::dsig:Signature[1]/dsig:Object[2]/dsig:Manifest)"));
      reference.setType(new URI(IXSILConstants.REFERENCETYPE_ATTR_VALUE_MANIFEST_));
      reference.setDigestAlgorithm(new DigestAlgorithmImplSHA1());
      
      // Add reference to signature
      signedInfo.addReference(reference);*/
    }

    // Create key information
    KeyManagerImpl keyManager = new KeyManagerImpl(signer.toDocument());

    X509Certificate[] certs = getCertificates(pkcs12);
    X509Data x509Data = new X509Data();
    x509Data.insertHintAt(certs[1], 0);
    /*for (int i = 0; i < certs.length; i++)
    {
      
    }*/

    KeyProviderImplX509Data x509DataKeyProvider = new KeyProviderImplX509Data(signer.toDocument());
    x509DataKeyProvider.insertX509DataAt(x509Data, 0);

    // X509Data key information (certificate chain)
    keyManager.addKeyProvider(x509DataKeyProvider);

    signer.getSignature().setKeyManager(keyManager);
    signer.getSignature().setId("signature-1-1");
    // Compute signature value
    signer.getSignature().sign();

    return signer.toDocument();
  }

  public Document createPKCS12Sig(
    String TestNumber,
    String data,
    boolean env,
    boolean mani,
    String data2,
    boolean env2,
    String id1,
    String id2)
    throws Exception
  {
    String resFile =
      configuration_.getProperty("baseDir")
        + datadirectory
        + configuration_.getProperty("TestClass")
        + "."
        + TestNumber
        + ".Res.xml";

    PKCS12 pkcs12 =
      decryptPKCS12(configuration_.getProperty("PKCS12file"), configuration_.getProperty("PKCS12password"));

    // Create signature generator
    URI baseURI = new URI(IXSILConstants.DUMMY_ABSURI_);
    Signer signer = new Signer(baseURI);

    // Configure signed information

    // Get interface for signed information
    SignerSignature signature = signer.getSignature();
    SignerSignedInfo signedInfo = signer.getSignature().getSignerSignedInfo();

    // Set canonicalization algorithm
    CanonicalizationAlgorithmImplCanonicalXML c14nAlg = new CanonicalizationAlgorithmImplCanonicalXML();
    signedInfo.setCanonicalizationAlgorithm(c14nAlg);

    // Set signature algorithm
    SignatureAlgorithmImplRSA signatureAlg = new SignatureAlgorithmImplRSA();
    RSAPrivateKey privateKey = getPrivateKey(pkcs12);
    signatureAlg.setSignerKey(privateKey);
    signedInfo.setSignatureAlgorithm(signatureAlg);

    if (!mani)
    {
      SignerReference reference = signedInfo.createReference();
      if (env)
      {
        iaik.ixsil.core.Object object = null;
        //object = signature.createObject(data);
        if (data.startsWith("<xml"))
        {
          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc = db.parse(new ByteArrayInputStream(data.getBytes()));

          object = signature.createObject(doc.getDocumentElement());
        }
        else if (data.startsWith("<Testdaten"))
        {

          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc =
            db.parse(
              new ByteArrayInputStream(("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + data).getBytes()));

          object = signature.createObject(doc.getDocumentElement());
        }
        else if (data.startsWith("b64:"))
        {
          data = data.substring(4);
          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc = db.newDocument();
          Element root = doc.createElement("root");
          doc.appendChild(root);
          //String encoded = Base64Utils.encode(data.getBytes());
          String encoded = Base64Utils.encode(data.getBytes());
          /*encoded = replaceStringAll(encoded,"\n","");
          encoded = replaceStringAll(encoded,"\r","");*/
          Text textnode = doc.createTextNode(encoded);

          System.out.println("Encoded:" + encoded);
          //root.appendChild(textnode);

          DocumentFragment df = doc.createDocumentFragment();

          df.appendChild(textnode);

          object = signature.createObject(df);

          TransformImplBase64Decode trans = new TransformImplBase64Decode();
          InputStream s = new ByteArrayInputStream(encoded.getBytes());
          trans.setInput(s, null);

          reference.insertTransformAt(trans, 0);
        }
        else
        {
          object = signature.createObject(data);
        }

        object.setId("signed-data-1-1-1");
        signature.addObject(object);

        DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
        reference.setDigestAlgorithm(digestAlg);

        reference.setURI(new URI("#xpointer(id('signed-data-1-1-1')/node())"));

      }
      else
      {
        // Create and configure reference
        URI refURI = null;
        String baseDir = configuration_.getProperty("baseDir");
        refURI = new URI(data);

        reference.setURI(refURI);
        DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
        reference.setDigestAlgorithm(digestAlg);
      }
      reference.setId("reference-2-1");
      signedInfo.addReference(reference);
    }

    if (data2 != null)
    {
      SignerReference reference = signedInfo.createReference();
      reference = signedInfo.createReference();
      if (env2)
      {
        iaik.ixsil.core.Object object = null;
        if (data2.startsWith("<xml"))
        {
          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc = db.parse(new ByteArrayInputStream(data.getBytes()));

          object = signature.createObject(doc.getDocumentElement());
        }
        else if (data2.startsWith("<Testdaten"))
        {

          DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          Document doc =
            db.parse(
              new ByteArrayInputStream(("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + data).getBytes()));

          object = signature.createObject(doc.getDocumentElement());
        }
        else
          object = signature.createObject(data2);

        if (!env)
          object.setId("signed-data-1-2-1");
        else
          object.setId("signed-data-1-2-1");
        signature.addObject(object);

        DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
        reference.setDigestAlgorithm(digestAlg);

        if (!env)
          reference.setURI(new URI("#xpointer(id('signed-data-1-2-1')/node())"));
        else
          reference.setURI(new URI("#xpointer(id('signed-data-1-2-1')/node())"));
      }
      else
      {
        // Create and configure reference
        URI refURI = null;
        String baseDir = configuration_.getProperty("baseDir");
        refURI = new URI(data2);

        reference.setURI(refURI);
        DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
        reference.setDigestAlgorithm(digestAlg);
      }
      reference.setId("reference-1-2");
      signedInfo.addReference(reference);
    }

    // Add reference to signature

    if (mani)
    {

      /*iaik.ixsil.core.Object object = null;
      if(env)
          object = signature.createObject(readFile(data));
      else
        object = signature.createObject(data);
        
        object.setId("envelopedData");
        signature.addObject(object);*/
      SignerReference reference = signedInfo.createReference();
      SignerManifest manifest = signer.createManifest();
      SignerReference manifestRef = manifest.createReference();

      DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
      manifestRef.setDigestAlgorithm(digestAlg);

      manifestRef.setURI(new URI(data));
      manifestRef.setId("reference-1-1");

      manifest.addReference(manifestRef);
      manifest.setId("dsig-manifest-1-1");
      iaik.ixsil.core.Object manifestObject = signature.createObject(manifest);
      signature.addObject(manifestObject);
      manifest.computeDigestValues();

      reference = signedInfo.createReference();
      reference.setURI(new URI("#dsig-manifest-1-1"));
      reference.setType(new URI(IXSILConstants.REFERENCETYPE_ATTR_VALUE_MANIFEST_));
      reference.setDigestAlgorithm(new DigestAlgorithmImplSHA1());

      // Add reference to signature
      signedInfo.addReference(reference);

      /*Element envelopedDataElem =
      signer.toDocument().createElement("EnvelopedDataElement");
      
      if(env)
      {
        envelopedDataElem.appendChild(
        signer.toDocument().createTextNode(readFile(data)));
      }
      else
      {
        envelopedDataElem.appendChild(
        signer.toDocument().createTextNode(data));
      }
      
      iaik.ixsil.core.Object object = signature.createObject(envelopedDataElem);
      signature.addObject(object);
      
      // Create Manifest with a single reference pointing to the enveloped data
      SignerManifest manifest = signer.createManifest();
      SignerReference manifestRef = manifest.createReference();
      manifestRef.setURI(
        new URI(
          null,
          null,
          null,
          null,
          "xmlns(dsig="
            + IXSILConstants.NAMESPACE_URI_XMLSIGNATURE_ELEM_
            + ") "
            + "xpointer(here()/ancestor::dsig:Signature[1]/dsig:Object[1]/descendant::node())"));
      manifestRef.setDigestAlgorithm(new DigestAlgorithmImplSHA1());
      manifest.addReference(manifestRef);
      
      // Add Manifest to signature structure (use an Object) and compute digest values for manifest reference
      iaik.ixsil.core.Object manifestObject = signature.createObject(manifest);
      signature.addObject(manifestObject);
      manifest.computeDigestValues();
      
      // Create and configure reference to manifest
      reference = signedInfo.createReference();
      reference.setURI(
        new URI(
          null,
          null,
          null,
          null,
          "xmlns(dsig="
            + IXSILConstants.NAMESPACE_URI_XMLSIGNATURE_ELEM_
            + ") "
            + "xpointer(here()/ancestor::dsig:Signature[1]/dsig:Object[2]/dsig:Manifest)"));
      reference.setType(new URI(IXSILConstants.REFERENCETYPE_ATTR_VALUE_MANIFEST_));
      reference.setDigestAlgorithm(new DigestAlgorithmImplSHA1());
      
      // Add reference to signature
      signedInfo.addReference(reference);*/
    }

    // Create key information
    KeyManagerImpl keyManager = new KeyManagerImpl(signer.toDocument());

    X509Certificate[] certs = getCertificates(pkcs12);
    X509Data x509Data = new X509Data();
    x509Data.insertHintAt(certs[1], 0);
    /*for (int i = 0; i < certs.length; i++)
    {
      
    }*/

    KeyProviderImplX509Data x509DataKeyProvider = new KeyProviderImplX509Data(signer.toDocument());
    x509DataKeyProvider.insertX509DataAt(x509Data, 0);

    // X509Data key information (certificate chain)
    keyManager.addKeyProvider(x509DataKeyProvider);

    signer.getSignature().setKeyManager(keyManager);
    signer.getSignature().setId("signature-2-1");
    // Compute signature value
    signer.getSignature().sign();

    return signer.toDocument();
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public Element getElement(String data) throws Exception
  {
    String etsinamespace = "http://uri.etsi.org/01903/v1.1.1#";

    getX509Content();

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    //dbf.setNamespaceAware(true);
    //dbf.setValidating(true);

    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

    Element qualprop = doc.createElementNS(etsinamespace, "etsi:QualifyingProperties");
    qualprop.setAttributeNS(null, "Target", "#signature-1-1");
    qualprop.setAttributeNS(IXSILConstants.NAMESPACE_URI_NAMESPACES_, "xmlns:etsi", etsinamespace);
    //qualprop.setPrefix("etsi");*/
    //qualprop.setAttributeNodeNS(doc.createAttributeNS(etsinamespace,"etsi"));
    Element signprop = doc.createElementNS(etsinamespace, "etsi:SignedProperties");
    Element signsigprop = doc.createElementNS(etsinamespace, "etsi:SignedSignatureProperties");
    Element signdataobjectprop = doc.createElementNS(etsinamespace, "etsi:SignedDataObjectProperties");
    Element signdate = doc.createElementNS(etsinamespace, "etsi:SigningTime");
    Text datevalue = doc.createTextNode("2003-05-10T00:01:01");
    Element signcert = doc.createElementNS(etsinamespace, "etsi:SigningCertificate");
    Element cert = doc.createElementNS(etsinamespace, "etsi:Cert");
    Element signpolyident = doc.createElementNS(etsinamespace, "etsi:SignaturePolicyIdentifier");
    Element signpolyimp = doc.createElementNS(etsinamespace, "etsi:SignaturePolicyImplied");
    Element certdig = doc.createElementNS(etsinamespace, "etsi:CertDigest");
    Element digmeth = doc.createElementNS(etsinamespace, "etsi:DigestMethod");
    digmeth.setAttribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
    Element digvalue = doc.createElementNS(etsinamespace, "etsi:DigestValue");

    ByteArrayOutputStream fos = new ByteArrayOutputStream();
    Base64OutputStream base64os = new Base64OutputStream(fos);
    base64os.write(this.X509hash.getBytes());
    base64os.flush();

    Text dig_value = doc.createTextNode(fos.toString());
    Element is = doc.createElementNS(etsinamespace, "etsi:IssuerSerial");
    Element i = doc.createElement("dsig:X509IssuerName");
    Text i_value = doc.createTextNode(this.X509name);
    Element s = doc.createElement("dsig:X509SerialNumber");
    Text s_value = doc.createTextNode(this.X509number.toString());
    Element dataobjformat = doc.createElementNS(etsinamespace, "etsi:DataObjectFormat");
    dataobjformat.setAttribute("ObjectReference", "#reference-1-1");
    Element mimetype = doc.createElementNS(etsinamespace, "etsi:MimeType");
    //mimetype.setNodeValue("text/plain");
    Text mimevalue = doc.createTextNode("text/plain");

    qualprop.appendChild(signprop);
    signprop.appendChild(signsigprop);
    signsigprop.appendChild(signdate);
    signdate.appendChild(datevalue);
    signsigprop.appendChild(signcert);
    signcert.appendChild(cert);
    cert.appendChild(certdig);
    certdig.appendChild(digmeth);
    certdig.appendChild(digvalue);
    digvalue.appendChild(dig_value);
    cert.appendChild(is);
    is.appendChild(i);
    i.appendChild(i_value);
    is.appendChild(s);
    s.appendChild(s_value);
    signsigprop.appendChild(signpolyident);
    signpolyident.appendChild(signpolyimp);
    signprop.appendChild(signdataobjectprop);
    signdataobjectprop.appendChild(dataobjformat);
    dataobjformat.appendChild(mimetype);
    mimetype.appendChild(mimevalue);

    return qualprop;
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public void create001() throws Exception
  {

    String testNumber = "001";

    String resFile =
      configuration_.getProperty("baseDir")
        + datadirectory
        + configuration_.getProperty("TestClass")
        + "."
        + testNumber
        + ".Res.xml";

    PKCS12 pkcs12 =
      decryptPKCS12(configuration_.getProperty("PKCS12file"), configuration_.getProperty("PKCS12password"));

    // Create signature generator
    URI baseURI = new URI(IXSILConstants.DUMMY_ABSURI_);
    Signer signer = new Signer(baseURI);

    // Configure signed information

    // Get interface for signed information
    SignerSignature signature = signer.getSignature();
    SignerSignedInfo signedInfo = signer.getSignature().getSignerSignedInfo();

    // Set canonicalization algorithm
    CanonicalizationAlgorithmImplCanonicalXML c14nAlg = new CanonicalizationAlgorithmImplCanonicalXML();
    signedInfo.setCanonicalizationAlgorithm(c14nAlg);

    // Set signature algorithm
    SignatureAlgorithmImplRSA signatureAlg = new SignatureAlgorithmImplRSA();
    RSAPrivateKey privateKey = getPrivateKey(pkcs12);
    signatureAlg.setSignerKey(privateKey);
    signedInfo.setSignatureAlgorithm(signatureAlg);

    // Create and configure reference
    String baseDir = configuration_.getProperty("baseDir");
    InputStream dataIS = new FileInputStream(baseDir + "resources/documents/testDaten.txt");

    SignerReference reference = signedInfo.createReference();
    reference.setURI(new URI("testDaten.txt"));
    reference.setExplicitData(dataIS, SignerReference.EXPLICITDATATYPE_RAW_);
    DigestAlgorithmImplSHA1 digestAlg = new DigestAlgorithmImplSHA1();
    reference.setDigestAlgorithm(digestAlg);
    reference.setId("reference-1-1");
    signedInfo.addReference(reference);

    // Create key information
    KeyManagerImpl keyManager = new KeyManagerImpl(signer.toDocument());

    X509Certificate[] certs = getCertificates(pkcs12);
    X509Data x509Data = new X509Data();
    x509Data.insertHintAt(certs[1], 0);
    KeyProviderImplX509Data x509DataKeyProvider = new KeyProviderImplX509Data(signer.toDocument());
    x509DataKeyProvider.insertX509DataAt(x509Data, 0);

    // X509Data key information (certificate chain)
    keyManager.addKeyProvider(x509DataKeyProvider);

    signer.getSignature().setKeyManager(keyManager);
    signer.getSignature().setId("signature-1-1");
    // Compute signature value
    signer.getSignature().sign();

    String erg = makeOutputFile(signer.toDocument());
    writeFile(resFile, erg);
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public void create002() throws Exception
  {

    String testNumber = "002";

    String resFile =
      configuration_.getProperty("baseDir")
        + datadirectory
        + configuration_.getProperty("TestClass")
        + "."
        + testNumber
        + ".Res.xml";

    Document signatureDoc = createPKCS12Sig(testNumber, "b64:Dies sind Testdaten", true, false, null, false);
    String erg = makeOutputFile(signatureDoc);
    writeFile(resFile, erg);
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public void create003() throws Exception
  {

    String testNumber = "003";

    String resFile =
      configuration_.getProperty("baseDir")
        + datadirectory
        + configuration_.getProperty("TestClass")
        + "."
        + testNumber
        + ".Res.xml";

    InputStream bis =
      new ByteArrayInputStream(
        ("<data:Document xmlns:data=\"http://uri.data.org\">"
          + readFile(configuration_.getProperty("baseDir") + "resources/documents/testSimple.txt")
          + "</data:Document>")
          .getBytes());

    //Document-Builder holen
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    DocumentBuilder builder = factory.newDocumentBuilder();
    //Dokument Parsen
    Document reqDoc = builder.parse(bis);

    System.out.println(DOMUtils.serializeNode(reqDoc.getDocumentElement()));
    //Position f�r die Signatur angeben
    String xPath_Pos = "/node()";
    //XPAth-Pr�fixe deklarieren
    String xPath_Prefix = "data xmlns:data=\"http://uri.data.org\"";
    Position pos = new Position(xPath_Pos, xPath_Prefix, 0);

    CreatePKCSSignature cpkcs = new CreatePKCSSignature();
    //Signer erzeugen, der das obige Doc als Basis nimmt, und die Signatur an der besagten stelle einf�gt
    cpkcs.init(reqDoc, pos, "signature-1-1");
    cpkcs.setCanoncialization(1);
    cpkcs.createReference(
      false,
      configuration_.getProperty("webbaseDir") + "resources/documents/testSimple.txt",
      "reference-1-1");
    cpkcs.setKeyInformation(1);

    Document doc = cpkcs.returnSig();

    String output =
      makeOutputFile(
        doc,
        "<data:Document xmlns:data=\"http://uri.data.org\">",
        cutXML(readFile(configuration_.getProperty("baseDir") + "resources/documents/testSimple.txt"))
          + "</data:Document>");

    writeFile(resFile, output);
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public void create004() throws Exception
  {

    String testNumber = "004";

    String resFile =
      configuration_.getProperty("baseDir")
        + datadirectory
        + configuration_.getProperty("TestClass")
        + "."
        + testNumber
        + ".Res.xml";

    InputStream bis =
      new ByteArrayInputStream(
        ("<data:Document xmlns:data=\"http://uri.data.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" attr=\"document\" xsi:schemaLocation=\"http://uri.data.org http://anywhere.org/testDocument.schema.xsd\">Dies sind Testdaten</data:Document>")
          .getBytes());

    //Document-Builder holen
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    factory.setValidating(true);
    DocumentBuilder builder = factory.newDocumentBuilder();

    Map m = new HashMap();
    m.put(
      "http://anywhere.org/testDocument.schema.xsd",
      new ByteArrayInputStream(
        ("<xsd:schema targetNamespace=\"http://uri.data.org\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://uri.data.org\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\" id=\"tollesSchema\">"
          + "<xsd:element name=\"Document\">"
          + "<xsd:complexType mixed=\"true\">"
          + "<xsd:sequence maxOccurs=\"unbounded\" minOccurs=\"0\">"
          + "<xsd:any namespace=\"##any\" processContents=\"lax\"/>"
          + "</xsd:sequence>"
          + "<xsd:attribute name=\"attr\" type=\"xsd:ID\" use=\"required\"/>"
          + "</xsd:complexType>"
          + "</xsd:element></xsd:schema>")
          .getBytes()));

    EntityResolverChain chain = new EntityResolverChain();
    chain.addEntityResolver(new StreamEntityResolver(m));
    chain.addEntityResolver(new MOAEntityResolver());
    builder.setEntityResolver(chain);

    //Dokument Parsen
    Document reqDoc =
      DOMUtils.parseDocument(bis, true, Constants.ALL_SCHEMA_LOCATIONS, null, chain, new MOAErrorHandler());

    System.out.println(DOMUtils.serializeNode(reqDoc.getDocumentElement()));

    //Position f�r die Signatur angeben
    String xPath_Pos = "//data:Document";

    //XPAth-Prefixe deklarieren
    String xPath_Prefix = "data http://uri.data.org";

    Position pos = new Position(xPath_Pos, xPath_Prefix, 0);

    CreatePKCSSignature cpkcs = new CreatePKCSSignature();
    //Signer erzeugen, der das obige Doc als Basis nimmt, und die Signatur an der besagten stelle einf�gt
    cpkcs.init(reqDoc, pos, "signature-1-1");
    cpkcs.setCanoncialization(1);

    //Enveloped Transformation
    Transform[] tr = new Transform[1];
    TransformImplEnvelopedSignature trans = new TransformImplEnvelopedSignature();
    tr[0] = trans;
    cpkcs.createReferenceWithTransforms(new URI("#document"), tr, "reference-1-1");

    cpkcs.setKeyInformation(1);

    Document doc = cpkcs.returnSig();

    String output =
      makeOutputFile(
        doc,
        "<data:Document xmlns:data=\"http://uri.data.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" attr=\"document\" xsi:schemaLocation=\"http://uri.data.org http://anywhere.org/testDocument.schema.xsd\">",
        readFile(configuration_.getProperty("baseDir") + "resources/documents/testSimple.txt")
          + "</data:Document>");

    writeFile(resFile, output);
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public void create005() throws Exception
  {

    String testNumber = "005";
    String resFile =
      configuration_.getProperty("baseDir")
        + datadirectory
        + configuration_.getProperty("TestClass")
        + "."
        + testNumber
        + ".Res.xml";

    CreatePKCSSignature cpkcs = new CreatePKCSSignature();
    cpkcs.init("signature-1-1");
    cpkcs.setCanoncialization(1);

    Transform[] tr = new Transform[1];
    TransformImplXSLT trans = new TransformImplXSLT();
    URL u = new URL(configuration_.getProperty("webbaseDir") + "resources/stylesheets/ref.book.notavailable.xsl");
    URLConnection hu = u.openConnection();

    trans.setStyleSheet(
      hu.getInputStream(),
      new URI(configuration_.getProperty("webbaseDir") + "resources/stylesheets/ref.book.notavailable.xsl"));
    tr[0] = trans;

    cpkcs.createReferenceWithTransforms(
      new URI(configuration_.getProperty("webbaseDir") + "resources/documents/bookData.xml"),
      tr,
      "reference-1-1");

    cpkcs.setKeyInformation(1);

    Document doc = cpkcs.returnSig();
    String output = makeOutputFile(doc);
    writeFile(resFile, output);
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public void writeFile(String filename, String data) throws Exception
  {
    BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
    bw.write(data);
    bw.close();
  }

  /* ---------------------------------------------------------------------------------------------------- */

  private String makeOutputFile(Document signatureDoc) throws Exception
  {
    ArrayList foundNodes = new ArrayList();
    findNode(signatureDoc.getDocumentElement(), "dsig:Signature", foundNodes);

    Node outputNode = null;

    if (foundNodes.size() > 0)
    {
      outputNode = (Node) foundNodes.get(0);
    }

    String erg = Node2String(outputNode);

    // remove the <?xml ?> Prologue
    int pos = erg.indexOf("<dsig");
    erg = erg.substring(pos);

    // insert the dsig:signature element in a MOA Response Message
    erg =
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
        + "<CreateXMLSignatureResponse\n"
        + "   xmlns=\"http://reference.e-government.gv.at/namespace/moa/20020822#\"\n"
        + "   >"
        + 
      //"   xmlns:etsi=\"http://uri.etsi.org/01903/v1.1.1#\">\n"+
  "<SignatureEnvironment>" + erg + "</SignatureEnvironment></CreateXMLSignatureResponse>";

    return erg;
  }

  /* ---------------------------------------------------------------------------------------------------- */

  private String makeOutputFile(Document signatureDoc, Document signatureDoc2) throws Exception
  {
    ArrayList foundNodes = new ArrayList();
    findNode(signatureDoc.getDocumentElement(), "dsig:Signature", foundNodes);

    Node outputNode = null;

    if (foundNodes.size() > 0)
    {
      outputNode = (Node) foundNodes.get(0);
    }

    String erg = Node2String(outputNode);

    // remove the <?xml ?> Prologue
    int pos = erg.indexOf("<dsig");
    erg = erg.substring(pos);

    foundNodes.clear();
    findNode(signatureDoc2.getDocumentElement(), "dsig:Signature", foundNodes);

    outputNode = null;

    if (foundNodes.size() > 0)
    {
      outputNode = (Node) foundNodes.get(0);
    }

    String erg2 = Node2String(outputNode);

    // remove the <?xml ?> Prologue
    pos = erg2.indexOf("<dsig");
    erg2 = erg2.substring(pos);

    // insert the dsig:signature element in a MOA Response Message
    erg =
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
        + "<CreateXMLSignatureResponse\n"
        + "   xmlns=\"http://reference.e-government.gv.at/namespace/moa/20020822#\"\n"
        + "    >"
        + "<SignatureEnvironment>"
        + erg
        + "</SignatureEnvironment><SignatureEnvironment>"
        + erg2
        + "</SignatureEnvironment> </CreateXMLSignatureResponse>";

    //erg = replaceString(erg,"Id=\"signature-1-1\"","Id=\"signature-2-1\"");
    //erg = replaceString(erg,"Id=\"reference-1-1\"","Id=\"reference-2-1\"");

    return erg;
  }

  /* ---------------------------------------------------------------------------------------------------- */

  public String makeOutputFile(Document signatureDoc, String prefix, String suffix) throws Exception
  {
    ArrayList foundNodes = new ArrayList();
    findNode(signatureDoc.getDocumentElement(), "dsig:Signature", foundNodes);

    Node outputNode = null;

    if (foundNodes.size() > 0)
    {
      outputNode = (Node) foundNodes.get(0);
    }

    String erg = Node2String(outputNode);

    // remove the <?xml ?> Prologue
    int pos = erg.indexOf("<dsig");
    erg = erg.substring(pos);

    // insert the dsig:signature element in a MOA Response Message
    erg =
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
        + "<CreateXMLSignatureResponse"
        + "   xmlns=\"http://reference.e-government.gv.at/namespace/moa/20020822#\""
        + "   >"
        + 
      //"   xmlns:etsi=\"http://uri.etsi.org/01903/v1.1.1#\">"+
  "<SignatureEnvironment>"
    + prefix
    + erg
    + suffix
    + "</SignatureEnvironment> </CreateXMLSignatureResponse>";

    return erg;
  }

}