// Copyright (C) 1997 by DI Wolfgang Platzer, IAIK // email: wplatzer@iaik.tu-graz.ac.at // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. // import java.io.*; import java.security.*; import java.util.*; import java.net.*; import java.math.BigInteger; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.crypto.EncryptedPrivateKeyInfo; //import iaik.security.rsa.*; //import iaik.x509.*; //import iaik.asn1.structures.*; //import iaik.asn1.*; //import iaik.x509.extensions.*; //import iaik.security.provider.IAIK; //import iaik.pkcs.pkcs8.*; //import iaik.utils.KeyAndCertificate; public class CreateCertificates { public static void saveKeyAndCert(KeyPair keyPair, X509Certificate[] chain, String fileName) throws IOException { System.out.println("encrypt private key..."); EncryptedPrivateKeyInfo epki = new EncryptedPrivateKeyInfo((PrivateKeyInfo)keyPair.getPrivate()); try { epki.encrypt("ecom", AlgorithmID.pbeWithMD5AndDES_CBC, null); } catch (NoSuchAlgorithmException ex) { throw new RuntimeException("No implementation for pbeWithMD5AndDES_CBC!"); } System.out.println("save private key and certificate chain to file "+fileName+"..."); new KeyAndCertificate(epki, chain).saveTo(fileName, ASN1.DER); } /** * Generate a RSA KeyPair. * * @param bits the length of the key (modulus) in bits * @return the KeyPair */ public static KeyPair generateKeyPair(String algorithm, int bits) { KeyPairGenerator generator = null; try { generator = KeyPairGenerator.getInstance(algorithm); } catch (NoSuchAlgorithmException ex) { System.out.println("generateKey: Algorithm "+algorithm+" not implemented!"); return null; // } catch (NoSuchProviderException ex) { // System.out.println("generateKey: Provider IAIK not found!"); // return null; } generator.initialize(bits); KeyPair kp = generator.generateKeyPair(); return kp; } /** * certChain[0] = user certificate. * certChain[x] = self signed CA certificate */ public static void verifyCertificateChain(X509Certificate[] certs) { int anz = certs.length; if (!verifyCertificate(certs[anz-1], null)) { System.out.println("Self signed TOPLEVEL certificate error!"); return; } else System.out.println("Self signed TOPLEVEL certificate OK!"); for (int i=anz-1; i>0; i--) System.out.println(verifyCertificate(certs[i-1], certs[i])); } /** * Verify a certificate. */ public static boolean verifyCertificate(X509Certificate userCert, X509Certificate caCert) { try { if (caCert == null) userCert.verify(); // self signed else userCert.verify(caCert.getPublicKey()); } catch (Exception ex) { return false; } return true; } /** * Create a certificate. */ public static X509Certificate createCertificate(Name subject, PublicKey pk, Name issuer, PrivateKey sk, AlgorithmID algorithm) { boolean extensions = false; X509Certificate cert = new X509Certificate(); try { cert.setSerialNumber(BigInteger.valueOf(0x1234L)); cert.setSubjectDN(subject); cert.setPublicKey(pk); cert.setIssuerDN(issuer); GregorianCalendar date = new GregorianCalendar(); date.add(Calendar.DATE, -1); cert.setValidNotBefore(date.getTime()); // not before yesterday date.add(Calendar.MONTH, 6); cert.setValidNotAfter(date.getTime()); if (extensions) { // add some v3 extensions byte[] id = {1,2,3,23,3,4,3,23,3}; SubjectKeyIdentifier ski = new SubjectKeyIdentifier(id); cert.addExtension(ski); BasicConstraints bc = new BasicConstraints(true, 1); bc.setCritical(true); cert.addExtension(bc); KeyUsage ku = new KeyUsage( KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign); cert.addExtension(ku); } cert.sign(algorithm ,sk); } catch (CertificateException ex) { System.out.println("CertificateException: "+ex.getMessage()); return null; } catch (InvalidKeyException ex) { System.out.println("InvalidKeyException: "+ex.getMessage()); return null; } catch (NoSuchAlgorithmException ex) { System.out.println("NoSuchAlgorithmException: "+ex.getMessage()); return null; } return cert; } public static void main(String arg[]) throws IOException { try { DataInputStream dis = new DataInputStream(System.in); String line; System.out.println("add Provider IAIK...\n"); IAIK provider = new IAIK(); Security.addProvider(provider); String localhost = null; try { localhost = InetAddress.getLocalHost().getHostName(); } catch(UnknownHostException ex) { System.out.print("UnknownHostException: "+ex.getMessage()); } System.out.print("Server host name ["+localhost+"]:"); // First create the private keys System.out.println("Creating server test certificates for "+localhost+"\n"); System.out.println("generate RSA KeyPair for CA certificate [1024 bits]..."); KeyPair caKeyPair = generateKeyPair("RSA", 1024); System.out.println("generate RSA KeyPair for server certificate [1024 bits]..."); KeyPair siteRSA = generateKeyPair("RSA", 1024); // Now create the certificates // Certificate Authority Name issuer = new Name(); issuer.addRDN(ObjectID.country, "FR"); issuer.addRDN(ObjectID.stateOrProvince, "Isere"); issuer.addRDN(ObjectID.locality, "Montbonnot"); issuer.addRDN(ObjectID.organization ,"INRIA"); issuer.addRDN(ObjectID.organizationalUnit ,"SIRAC"); issuer.addRDN(ObjectID.commonName ,"FELIOT"); // Transaction Server Name site = new Name(); site.addRDN(ObjectID.country, "FR"); site.addRDN(ObjectID.stateOrProvince, "Isere"); site.addRDN(ObjectID.locality, "Montbonnot"); site.addRDN(ObjectID.organization ,"INRIA"); site.addRDN(ObjectID.organizationalUnit ,"SIRAC"); site.addRDN(ObjectID.commonName , "Shopping Server"); site.addRDN(ObjectID.emailAddress , "David.Feliot@imag.fr"); // create self signed CA cert System.out.println("create self signed CA certificate..."); X509Certificate caRSACert = createCertificate(issuer, caKeyPair.getPublic(), issuer, caKeyPair.getPrivate(), AlgorithmID.md5WithRSAEncryption); // create site certificates site.addRDN(ObjectID.organizationalUnit ,"RSA Shopping Server Certificate"); System.out.println("create RSA server certificate..."); X509Certificate siteRSACert = createCertificate(site, siteRSA.getPublic(), issuer, caKeyPair.getPrivate(), AlgorithmID.md5WithRSAEncryption); X509Certificate[] chain = new X509Certificate[1]; chain[0] = caRSACert; saveKeyAndCert(caKeyPair, chain, "caRSA1024.der"); chain = new X509Certificate[2]; chain[1] = caRSACert; chain[0] = siteRSACert; verifyCertificateChain(chain); saveKeyAndCert(siteRSA, chain, "siteRSA1024.der"); System.out.println("\n site and CA certificates created."); } catch (Exception ex) { System.out.println("Exception: "+ex); } } }