Java tutorial
/* * Copyright (c) 2014, 2015 Ericsson Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.snbi.southplugin; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import org.bouncycastle.asn1.pkcs.CertificationRequest; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.cert.CertException; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v2CRLBuilder; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.cms.CMSSignedDataGenerator; import org.bouncycastle.cms.SignerInfoGeneratorBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.PEMWriter; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; import org.bouncycastle.x509.extension.*; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.x509.extension.X509ExtensionUtil; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.style.BCStrictStyle; import java.security.Security; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.opendaylight.snbi.southplugin.KeyPairMgmt; // Class to manage certificates public class CertificateMgmt { // a static map to keep default values for certificate management public static HashMap<String, String> defaults = null; static { defaults = new HashMap<String, String>(); // defaults.put("COUNTRY", "USA"); // defaults.put("ORGANIZATION", "ODL Community"); // defaults.put("TITLE", "SNBI Certificate by BC"); // defaults.put("STATE", "CALIFORNIA"); // defaults.put("LOCALITY", "SANJOSE"); // defaults.put("EMAIL", "snbi-dev@lists.opendaylight.org"); } protected static final Logger logger = LoggerFactory.getLogger(CertificateMgmt.class); // create and sign the self signed certificate during startup @SuppressWarnings("deprecation") public static X509Certificate generateSelfSignedCACertificate(String hostname, String provider, KeyPair pair) { logger.info("Creating self signed certificate "); X509Certificate cert = null; try { Security.addProvider(new BouncyCastleProvider()); String subject = hostname; String issuerName = hostname; X500Name subjectFormated = new X500NameBuilder(BCStyle.INSTANCE).addRDN(BCStyle.CN, subject).build(); X500Name issuerFormated = new X500NameBuilder(BCStyle.INSTANCE).addRDN(BCStyle.CN, issuerName).build(); BigInteger serialNumber = BigInteger.ONE; Calendar now = Calendar.getInstance(); now.add(Calendar.YEAR, -1); Date notBefore = now.getTime(); now.add(Calendar.YEAR, 4); Date notAfter = now.getTime(); JcaX509v3CertificateBuilder builder = null; builder = new JcaX509v3CertificateBuilder(issuerFormated, serialNumber, notBefore, notAfter, subjectFormated, pair.getPublic()); // Generate self-signed certificate // X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); // builder.addRDN(BCStyle.CN, hostname); builder.addExtension(X509Extension.basicConstraints, true, new BasicConstraints(true)); SubjectKeyIdentifier subjectKeyIdentifier = new JcaX509ExtensionUtils() .createSubjectKeyIdentifier(pair.getPublic()); builder.addExtension(X509Extension.subjectKeyIdentifier, false, subjectKeyIdentifier); KeyUsage keyUsage = new KeyUsage(KeyUsage.keyCertSign); builder.addExtension(X509Extension.keyUsage, true, keyUsage); ExtendedKeyUsage extendedKeyUsage = new ExtendedKeyUsage(KeyPurposeId.anyExtendedKeyUsage); builder.addExtension(X509Extension.extendedKeyUsage, false, extendedKeyUsage); ContentSigner signer = new JcaContentSignerBuilder( CertManagerConstants.CERT_ALGORITHM.SHA1withRSA.toString()).setProvider(provider) .build(pair.getPrivate()); X509CertificateHolder holder = builder.build(signer); cert = (X509Certificate) java.security.cert.CertificateFactory.getInstance("X.509") .generateCertificate(new ByteArrayInputStream(holder.getEncoded())); } catch (Throwable t) { t.printStackTrace(); } logger.info("Created self signed certificate "); return cert; } // save the certificate locally public static void saveCertificate(X509Certificate cert, KeyPair keyPair, String fileName) { logger.info("Saving certificate " + fileName); if (cert == null) return; PEMWriter pemWriter = null; try { pemWriter = new PEMWriter(new FileWriter(fileName)); pemWriter.writeObject(cert); pemWriter.flush(); pemWriter.writeObject(keyPair.getPrivate()); pemWriter.flush(); } catch (IOException e) { e.printStackTrace(); return; } finally { try { pemWriter.close(); } catch (IOException e) { } } } // retrieve saved certificate from file public static X509Certificate getSavedCertificate(String provider, String fileName) { X509Certificate cert = null; logger.info("Retrieving certificate " + fileName); FileReader fileReader; try { fileReader = new FileReader(fileName); } catch (FileNotFoundException e) { e.printStackTrace(); return null; } PEMParser pemParser = new PEMParser(fileReader); Object privatekey; try { privatekey = pemParser.readObject(); } catch (IOException e) { e.printStackTrace(); return null; } finally { try { pemParser.close(); } catch (IOException e) { e.printStackTrace(); } } if (privatekey == null) return null; X509CertificateHolder certHolder = (X509CertificateHolder) privatekey; try { return new JcaX509CertificateConverter().setProvider(provider).getCertificate(certHolder); } catch (CertificateException e) { e.printStackTrace(); } return cert; } // print the certificate to console and return the certificate String public static String printCertificate(X509Certificate cert) { logger.info("Printing X509Certificate"); if (cert == null) return null; logger.info(" ------------------- START -------------------"); logger.info(cert.toString()); logger.info(" ------------------- END -------------------"); return cert.toString(); } // verify the certificate by date and public key. returns error message . public static String verifyCertificate(X509Certificate cert, Date date, PublicKey pub_key) { logger.info("Verify X509Certificate"); String message = ""; try { if (date != null) cert.checkValidity(date); } catch (CertificateException e) { message = "CERTIFICATE VALIDATION ERROR :: " + e.getMessage() + "\n"; } try { if (pub_key != null) cert.verify(cert.getPublicKey()); } catch (InvalidKeyException | CertificateException | NoSuchAlgorithmException | NoSuchProviderException | SignatureException e) { message += "CERTIFICATE VALIDATION ERROR :: " + e.getMessage(); } if (message.trim().length() == 0) message = "CERTIFICATE VALIDATION SUCESS"; return message; } // generate a certificate signing request public static PKCS10CertificationRequest generateCSRRequest(String name, KeyPair pair) throws Exception { X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); // builder.addRDN(BCStyle.C, defaults.get("COUNTRY")); // builder.addRDN(BCStyle.O, defaults.get("ORGANIZATION")); // builder.addRDN(BCStyle.ST, defaults.get("STATE")); // builder.addRDN(BCStyle.T, defaults.get("TITLE")); builder.addRDN(BCStyle.SN, BigInteger.valueOf(System.currentTimeMillis()).toString()); builder.addRDN(BCStyle.CN, name); PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(builder.build(), pair.getPublic()); JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder( CertManagerConstants.CERT_ALGORITHM.SHA1withRSA.toString()); ContentSigner signer = csBuilder.build(pair.getPrivate()); PKCS10CertificationRequest csr = p10Builder.build(signer); return csr; } // build a certificate chain with root certificate and new x509 certificate. public static X509Certificate[] buildChain(String provider, KeyPair pair) throws Exception { X509Certificate rootCert = CertificateMgmt.getSavedCertificate(CertManagerConstants.BC, CertManagerConstants.SELF_SIGNED_CERT_FILE); KeyPair rootPair = KeyPairMgmt.getKeyPairFromStore(CertManagerConstants.KEY_STORE_ALIAS, CertManagerConstants.KEY_STORE_CERT_ALIAS, CertManagerConstants.STORE_TYPE.JKS); KeyPair keyPair = KeyPairMgmt.generateKeyPair(CertManagerConstants.ALGORITHM.RSA); PKCS10CertificationRequest request = generateCSRRequest("Node", pair); Calendar now = Calendar.getInstance(); Date notBefore = now.getTime(); now.add(Calendar.YEAR, 3); Date notAfter = now.getTime(); BigInteger serial = BigInteger.valueOf(System.currentTimeMillis()); X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(request.getSubject(), serial, notBefore, notAfter, request.getSubject(), rootCert.getPublicKey()); ContentSigner sigGen = new JcaContentSignerBuilder( CertManagerConstants.CERT_ALGORITHM.SHA1withRSA.toString()).setProvider(provider) .build(rootPair.getPrivate()); X509Certificate issuedCert = new JcaX509CertificateConverter().setProvider(provider) .getCertificate(certGen.build(sigGen)); return new X509Certificate[] { issuedCert, rootCert }; } // utility metjhod to sign the csr with local CA public static X509Certificate signCSR(CertificationRequest inputCSR, PrivateKey caPrivate, KeyPair pair) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, IOException, OperatorCreationException, CertException { PKCS10CertificationRequest pk10Holder = new PKCS10CertificationRequest(inputCSR); X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); // builder.addRDN(BCStyle.C, defaults.get("COUNTRY")); // builder.addRDN(BCStyle.O, defaults.get("ORGANIZATION")); //builder.addRDN(BCStyle.ST, defaults.get("STATE")); // builder.addRDN(BCStyle.T, defaults.get("TITLE")); builder.addRDN(BCStyle.CN, inputCSR.getSignature()); Calendar now = Calendar.getInstance(); Date notBefore = now.getTime(); now.add(Calendar.YEAR, 3); Date notAfter = now.getTime(); BigInteger serial = BigInteger.valueOf(System.currentTimeMillis()); X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), serial, notBefore, notAfter, builder.build(), pair.getPublic()); ContentSigner sigGen = new JcaContentSignerBuilder( CertManagerConstants.CERT_ALGORITHM.SHA1withRSA.toString()).setProvider(CertManagerConstants.BC) .build(pair.getPrivate()); X509CertificateHolder holder = certGen.build(sigGen); Certificate eeX509CertificateStructure = holder.toASN1Structure(); CertificateFactory cf = null; try { cf = CertificateFactory.getInstance(CertManagerConstants.CERT_TYPE.X509.toString(), CertManagerConstants.BC); } catch (CertificateException e) { e.printStackTrace(); } // Read Certificate InputStream is1 = new ByteArrayInputStream(eeX509CertificateStructure.getEncoded()); X509Certificate theCert = null; try { theCert = (X509Certificate) cf.generateCertificate(is1); } catch (CertificateException e) { e.printStackTrace(); } is1.close(); return theCert; } // method to revoke a certificate public static void createCRL(String name) { X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); // builder.addRDN(BCStyle.C, defaults.get("COUNTRY")); // builder.addRDN(BCStyle.O, defaults.get("ORGANIZATION")); // builder.addRDN(BCStyle.ST, defaults.get("STATE")); // builder.addRDN(BCStyle.T, defaults.get("TITLE")); builder.addRDN(BCStyle.SN, BigInteger.valueOf(System.currentTimeMillis()).toString()); builder.addRDN(BCStyle.CN, name); Calendar now = Calendar.getInstance(); Date notBefore = now.getTime(); now.add(Calendar.YEAR, 3); Date notAfter = now.getTime(); X509v2CRLBuilder crlGen = new X509v2CRLBuilder(builder.build(), notBefore); crlGen.setNextUpdate(notAfter); } // create signature with the root ca private key public static byte[] generateSignature(byte[] data, Certificate cert, String algorithm) { Signature signer = null; KeyPair rootPair = KeyPairMgmt.getKeyPairFromStore(CertManagerConstants.KEY_STORE_ALIAS, CertManagerConstants.KEY_STORE_CERT_ALIAS, CertManagerConstants.STORE_TYPE.JKS); try { signer = Signature.getInstance(algorithm, CertManagerConstants.BC); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } catch (NoSuchProviderException e) { e.printStackTrace(); return null; } try { signer.initSign(rootPair.getPrivate()); } catch (InvalidKeyException e) { e.printStackTrace(); return null; } try { signer.update(data); } catch (SignatureException e) { e.printStackTrace(); return null; } try { return signer.sign(); } catch (SignatureException e) { e.printStackTrace(); return null; } } //verify the signature . first generate the signature and compare with both hash public static boolean verifySignature(byte[] data, byte[] hash, Certificate cert, String algorithm) { byte[] newhash = generateSignature(data, cert, algorithm); return Arrays.equals(hash, newhash); } /* Misc Methods not used */ // create signature by passing the certificate public static byte[] sign(Certificate cert, KeyPair pair) { ContentSigner signGen = null; X509CertificateHolder certHolder = new X509CertificateHolder(cert); try { signGen = new JcaContentSignerBuilder(CertManagerConstants.CERT_ALGORITHM.SHA1withRSA.toString()) .setProvider(CertManagerConstants.BC).build(pair.getPrivate()); } catch (OperatorCreationException e) { e.printStackTrace(); return null; } CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); try { gen.addSignerInfoGenerator( new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider()).build(signGen, certHolder)); } catch (OperatorCreationException e) { e.printStackTrace(); return null; } return certHolder.getSignature(); } // create signature another api public static byte[] sign(byte[] data, KeyPair pair) { Signature signer = null; try { signer = Signature.getInstance(CertManagerConstants.CERT_ALGORITHM.SHA1withRSA.toString(), CertManagerConstants.BC); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } catch (NoSuchProviderException e) { e.printStackTrace(); return null; } try { signer.initSign(pair.getPrivate()); } catch (InvalidKeyException e) { e.printStackTrace(); return null; } try { signer.update(data); } catch (SignatureException e) { e.printStackTrace(); return null; } try { return signer.sign(); } catch (SignatureException e) { e.printStackTrace(); return null; } } }