package testgenerator;

import iaik.asn1.CodingException;
import iaik.asn1.ObjectID;
import iaik.asn1.structures.AlgorithmID;
import iaik.asn1.structures.Attribute;
import iaik.asn1.structures.ChoiceOfTime;
import iaik.cms.CMSException;
import iaik.cms.ContentInfoStream;
import iaik.cms.SignedDataStream;
import iaik.cms.SignerInfo;
import iaik.utils.StreamCopier;
import iaik.x509.X509Certificate;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.security.SignatureException;


/**
 * @author Administrator
 *
 * To change this generated comment edit the template variable "typecomment":
 * Window>Preferences>Java>Templates.
 * To enable and disable the creation of type comments go to
 * Window>Preferences>Java>Code Generation.
 */
public class TestCMS {

	public static void main(String[] args) 
	{
		try {
			iaik.security.provider.IAIK.addAsProvider(true);
			
			Provider [] list = Security.getProviders();
			for(int counter=0;counter<list.length;counter++)
			{
				System.out.println(list[counter].getName());
			}
			
			KeyStore.getInstance("IAIKKeyStore");
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public static String getSignedDataStream(byte[] signedData, byte[] message,boolean two_users) throws CMSException, IOException {

    // we are testing the stream interface
    ByteArrayInputStream is = new ByteArrayInputStream(signedData);
    // create the ContentInfo object
    ContentInfoStream cis = new ContentInfoStream(is);
    System.out.println("This ContentInfo holds content of type " + cis.getContentType().getName());
    SignedDataStream signed_data = null;

    if (message == null) {
      // implicitly signed; get the content
      signed_data = (SignedDataStream)cis.getContent();
    }
    else {
      // explicitly signed; set the data stream for digesting the message
      AlgorithmID[] algIDs = { AlgorithmID.sha1, AlgorithmID.md5 };
      signed_data = new SignedDataStream(new ByteArrayInputStream(message), algIDs);

    }

    // get an InputStream for reading the signed content
    InputStream data = signed_data.getInputStream();
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    StreamCopier sc = new StreamCopier(data, os);
    sc.copyStream();


    if (message != null) {
      // if explicitly signed read now the DER encoded object
      // an explicit S/MIME signed message also consits of message|signature
      signed_data.decode(cis.getContentInputStream());
    }

    System.out.println("SignedData contains the following signer information:");
    SignerInfo[] signer_infos = signed_data.getSignerInfos();

    for (int i=0; i<signer_infos.length; i++) {
      try {
        // verify the signed data using the SignerInfo at index i
        X509Certificate signer_cert = signed_data.verify(i);
        // if the signature is OK the certificate of the signer is returned
        System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
        Attribute signingTime = signer_infos[i].getSignedAttribute(ObjectID.signingTime);
        if (signingTime != null) {
          ChoiceOfTime cot = new ChoiceOfTime(signingTime.getValue()[0]);
          System.out.println("This message has been signed at " + cot.getDate());
        }
        Attribute contentType = signer_infos[i].getSignedAttribute(ObjectID.contentType);
        if (contentType != null) {
          System.out.println("The content has CMS content type " + contentType.getValue()[0]);
        }

      } catch (SignatureException ex) {
        // if the signature is not OK a SignatureException is thrown
        System.out.println("Signature ERROR from signer: "+signed_data.getCertificate((signer_infos[i].getSignerIdentifier())).getSubjectDN());
        ex.printStackTrace();
      } catch (CodingException ex) {
        System.out.println("Attribute decoding error: " + ex.getMessage());
        ex.printStackTrace();
      }
    }
    
    return os.toString();
  }

}