import java.security.*;
import java.io.*;
import java.math.BigInteger;
import java.util.*;

//import java.security.cert.*;


import iaik.asn1.structures.*;
import iaik.security.rsa.*;
import iaik.x509.*;
import iaik.asn1.structures.*;
import iaik.asn1.*;
import iaik.security.provider.IAIK;
import iaik.pkcs.pkcs8.*;
import iaik.utils.KeyAndCertificate;

public class CertMaker
{
   public CertMaker(String filename, String password) throws Exception
     {
	    if (password==null) throw new Exception("passa consegñia");

	     _ks = KeyStore.getInstance("JKS");
	     _password = password;
	     FileInputStream fis = null ;

	     if (filename != null ) {
	        _file = filename;

		fis = new FileInputStream(filename);
	     }

	     _ks.load(fis,password.toCharArray());

	     if (filename != null) fis.close();
     }
	       
   public void save(String filename) throws Exception
     {
	FileOutputStream fos = new FileOutputStream(filename);
	_ks.store(fos,_password.toCharArray());
	fos.close();
     }
   
   public X509Certificate makeSelfSigned(String alias, String password) throws Exception
     {
	KeyPair kp = generateKeyPair("RSA",512);
	X509Certificate cert = null;
	X509Certificate[] chain = new X509Certificate[1] ;

	Name issuer = new Name();
	issuer.addRDN(ObjectID.country, "ES");
	issuer.addRDN(ObjectID.organization ,"UAB Barcelona");
	issuer.addRDN(ObjectID.organizationalUnit ,"CCD");
	issuer.addRDN(ObjectID.commonName ,"Group 8");
	
	Name userSubject = new Name();
	userSubject.addRDN(ObjectID.country, "ES");
	userSubject.addRDN(ObjectID.organization ,"UAB Barcelona");
	userSubject.addRDN(ObjectID.organizationalUnit ,"CCD");

	cert = createCertificate(
			issuer, kp.getPublic(),
              		issuer, kp.getPrivate(),
			AlgorithmID.sha1WithRSAEncryption, 1);

	chain[0] = cert;

	_ks.setCertificateEntry(alias,cert);
	_ks.setKeyEntry(alias,kp.getPrivate(),password.toCharArray(),chain);

	//System.out.println(cert.getIssuerDN());
	//System.out.println(cert.getSubjectDN());


	return cert;
     }

   public X509Certificate makeSigned(String alias, String password, String aliassigner, String passwordsigner) throws Exception
     {
	// XXX
	// implementaction not optimal. missing increasement of serial numer in adequate way.
	// only based on numer of aliases in keystore 
	
	KeyPair kp = generateKeyPair("RSA",512);
	X509Certificate cert = null;
	X509Certificate[] chain = new X509Certificate[2] ;

	Name userSubject = new Name();

	userSubject.addRDN(ObjectID.country, "ES");
	userSubject.addRDN(ObjectID.organization ,"UAB Barcelona");
	userSubject.addRDN(ObjectID.organizationalUnit ,"CCD");
        userSubject.addRDN(ObjectID.commonName , "TestCertificate - "+alias);

	// load sign certificate
	
	X509Certificate signer = (X509Certificate)_ks.getCertificate(aliassigner);
	PrivateKey signkey = (PrivateKey)_ks.getKey(aliassigner,passwordsigner.toCharArray());

        cert = createCertificate(userSubject, kp.getPublic(),
              signer.getIssuerDN(), signkey, 
	      AlgorithmID.sha1WithRSAEncryption, _ks.size()+1 ); 


	chain[0] = signer;
	chain[1] = cert;

	_ks.setCertificateEntry(alias,cert);
	_ks.setKeyEntry(alias,kp.getPrivate(),password.toCharArray(),chain);

	//System.out.println(cert.toString(true));
	      
	return cert;
     }
     
   public void importTrusted(String alias, String file) throws Exception
     {
	     X509Certificate cert = new X509Certificate(new FileInputStream(new File(file)));
	     _ks.setCertificateEntry(alias,cert);
     }

   public void exportCertificate(String alias, String file) throws Exception
   {
	X509Certificate cert = (X509Certificate)_ks.getCertificate(alias);
	FileOutputStream fos = new FileOutputStream(new File(file));
	fos.write(cert.toByteArray());
	fos.close();
   }

   private X509Certificate createCertificate(Name subject, PublicKey pk, 
	Principal issuer, PrivateKey sk, AlgorithmID algorithm, int serialNumber)
	throws Exception {

    X509Certificate cert = new X509Certificate();

    cert.setSerialNumber(BigInteger.valueOf(serialNumber));
    cert.setSubjectDN(subject);
    cert.setPublicKey(pk);
    cert.setIssuerDN(issuer);

    GregorianCalendar date = new GregorianCalendar();

    date.add(Calendar.DATE, -1);
    cert.setValidNotBefore(date.getTime());      
    date.add(Calendar.MONTH, 6);
    cert.setValidNotAfter(date.getTime());

    cert.sign(algorithm,sk);

    return cert;
  }

  private KeyPair generateKeyPair(String algorithm, int bits) throws Exception {

	KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm);
	generator.initialize(bits);
	return generator.generateKeyPair();
   }

  public String toString() {
	  String ret = "";
	  String elem ;

	  try {

	  ret += "number elem: "+ _ks.size()+"\n";

	  for (Enumeration e = _ks.aliases() ; e.hasMoreElements() ;) {
		elem = (String)e.nextElement();
		ret += elem+"\n" ;
		 ;
		ret += (_ks.getCertificate(elem)).toString()+"\n";

	  }
	  
	  }
	  catch (Exception ex) { ex.printStackTrace() ; }

	  return ret;
  }
	
   
   private KeyStore _ks;
   private String _file;
   private String _password;
}

