package org.bouncycastle.cms.test;

import java.io.ByteArrayInputStream;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.mail.internet.MimeBodyPart;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.jce.cert.CertStore;
import org.bouncycastle.jce.cert.CollectionCertStoreParameters;

public class SignedDataTest
    extends TestCase
{

    boolean DEBUG = true;

    MimeBodyPart    msg;

    String          signDN;
    KeyPair         signKP;
    X509Certificate signCert;

    String          origDN;
    KeyPair         origKP;
    X509Certificate origCert;

    String          reciDN;
    KeyPair         reciKP;
    X509Certificate reciCert;

    KeyPair         dsaSignKP;
    X509Certificate dsaSignCert;

    KeyPair         dsaOrigKP;
    X509Certificate dsaOrigCert;

    /*
     *
     *  INFRASTRUCTURE
     *
     */

    public SignedDataTest(String name) {
        super(name);
    }

    public static void main(String args[]) {

        junit.textui.TestRunner.run(SignedDataTest.class);
    }

    public static Test suite() {
        return new TestSuite(SignedDataTest.class);
    }

    public void log(Exception _ex) {
        if(DEBUG) {
            _ex.printStackTrace();
        }
    }

    public void log(String _msg) {
        if(DEBUG) {
            System.out.println(_msg);
        }
    }

    public void setUp()
    {
        try
        {
            signDN   = "O=Bouncy Castle, C=AU";
            signKP   = CMSTestUtil.makeKeyPair();  
            signCert = CMSTestUtil.makeCertificate(signKP, signDN, signKP, signDN);

            origDN   = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU";
            origKP   = CMSTestUtil.makeKeyPair();
            origCert = CMSTestUtil.makeCertificate(origKP, origDN, signKP, signDN);
        }
        catch(Exception ex)
        {
            log(ex);
            fail();
        }
    }

    public void tearDown() {

    }

    /*
     *
     *  TESTS
     *
     */

    public void testSHA1WithRSAEncapsulated()
    {
        try
        {
            ArrayList           certList = new ArrayList();
            CMSProcessable      msg = new CMSProcessableByteArray("Hello World!".getBytes());

            certList.add(origCert);
            certList.add(signCert);

            CertStore           certs = CertStore.getInstance("Collection",
                            new CollectionCertStoreParameters(certList), "BC");

            CMSSignedDataGenerator gen = new CMSSignedDataGenerator();

            gen.addSigner(origKP.getPrivate(), origCert, CMSSignedDataGenerator.DIGEST_SHA1);

            gen.addCertificatesAndCRLs(certs);

            CMSSignedData s = gen.generate(msg, true, "BC");

            ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded());
            ASN1InputStream      aIn = new ASN1InputStream(bIn);
            
            s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));

            certs = s.getCertificatesAndCRLs("Collection", "BC");

            SignerInformationStore  signers = s.getSignerInfos();
            Collection              c = signers.getSigners();
            Iterator                it = c.iterator();

            while (it.hasNext())
            {
                SignerInformation   signer = (SignerInformation)it.next();
                Collection          certCollection = certs.getCertificates(signer.getSID());

                Iterator        certIt = certCollection.iterator();

                X509Certificate cert = (X509Certificate)certIt.next();

                assertEquals(true, signer.verify(cert, "BC"));
            }
        }
        catch(Exception ex)
        {
            log(ex);
            fail();
        }
    }
}
