package org.openstack.atlas.util.ca; import java.io.IOException; import java.security.NoSuchProviderException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.math.BigInteger; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.security.spec.PKCS8EncodedKeySpec; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.jce.provider.JCERSAPrivateCrtKey; import org.bouncycastle.jce.provider.JCERSAPublicKey; import org.bouncycastle.openssl.PKCS8Generator; import org.bouncycastle.util.io.pem.PemObject; import org.openstack.atlas.util.ca.exceptions.ConversionException; import org.openstack.atlas.util.ca.exceptions.NotAnRSAKeyException; import org.openstack.atlas.util.ca.exceptions.PemException; import org.openstack.atlas.util.ca.exceptions.NoSuchAlgorithmException; import org.openstack.atlas.util.ca.primitives.Debug; import org.openstack.atlas.util.ca.exceptions.RsaException; import org.openstack.atlas.util.ca.primitives.RsaConst; import org.openstack.atlas.util.ca.primitives.bcextenders.HackedProviderAccessor; public class RSAKeyUtils { public static final int DEFAULT_KEY_SIZE = 2048; static { RsaConst.init(); } private static final BigInteger m16bit = new BigInteger("10001", 16); public static List<String> verifyKeyAndCert(KeyPair kp, X509Certificate cert) { List<String> errorList = new ArrayList<String>(); JCERSAPublicKey certPub = null; JCERSAPublicKey keyPub = null; try { Object obj = kp.getPublic(); String objInfo = Debug.classLoaderInfo(obj.getClass()); String jpkInfo = Debug.classLoaderInfo(JCERSAPublicKey.class); keyPub = (JCERSAPublicKey) obj; } catch (ClassCastException ex) { errorList.add("privateKey pair did not decode correctly"); } try { certPub = (JCERSAPublicKey) cert.getPublicKey(); } catch (ClassCastException ex) { errorList.add("Error could not retrieve public key from Cert"); return errorList; } if (!certPub.getModulus().equals(keyPub.getModulus())) { errorList.add("Error cert and key Modulus mismatch"); } if (!certPub.getPublicExponent().equals(keyPub.getPublicExponent())) { errorList.add("Error cert and key public exponents mismatch"); } try { cert.checkValidity(); } catch (CertificateExpiredException ex) { errorList.add("Error cert Expired"); } catch (CertificateNotYetValidException ex) { errorList.add("Error cert not yet valid"); } catch (RuntimeException ex) { errorList.add("Unable to check date validity of Cert"); } return errorList; } @Deprecated public static List<String> verifyKeyAndCert(byte[] keyPem, byte[] certPem) { List<String> errorList = new ArrayList<String>(); KeyPair kp = null; JCERSAPublicKey certPub = null; JCERSAPublicKey keyPub = null; X509Certificate cert = null; try { Object obj = PemUtils.fromPem(keyPem); if (obj instanceof JCERSAPrivateCrtKey) { try { kp = HackedProviderAccessor.newKeyPair((JCERSAPrivateCrtKey) obj); } catch (InvalidKeySpecException ex) { errorList.add("InvalidKeySpec when trying to decode key"); return errorList; } } else { kp = (KeyPair) PemUtils.fromPem(keyPem); } keyPub = (JCERSAPublicKey) kp.getPublic(); } catch (PemException ex) { errorList.add("Error decoding Key from Pem Data"); } catch (ClassCastException ex) { errorList.add("Error key Pem Data did not decode to an RSA Private Key"); } try { cert = (X509Certificate) PemUtils.fromPem(certPem); } catch (PemException ex) { errorList.add("Error decoding Cert from Pem Data"); } catch (ClassCastException ex) { errorList.add("Error cert Pem data did not decode to an RSA Private Key"); } if (kp == null || cert == null) { return errorList; } return verifyKeyAndCert(kp, cert); } public static String shortPub(Object obj) { String out = null; BigInteger n; BigInteger e; if (obj instanceof JCERSAPublicKey) { JCERSAPublicKey jk = (JCERSAPublicKey) obj; n = jk.getModulus().mod(m16bit); e = jk.getPublicExponent(); return String.format("(%s,%s)", e, n); } else if (obj instanceof RSAKeyParameters) { RSAKeyParameters rp = (RSAKeyParameters) obj; n = rp.getModulus().mod(m16bit); e = rp.getExponent(); return String.format("(%s,%s)", e, n); } else if (obj instanceof RSAPublicKeyStructure) { RSAPublicKeyStructure rs = (RSAPublicKeyStructure) obj; n = rs.getModulus().mod(m16bit); e = rs.getPublicExponent(); return String.format("(%s,%s)", e, n); } else { return String.format("(%s,%s)", "None", "None"); } } public static KeyPair genKeyPair(int keySize) throws RsaException { SecureRandom sr; KeyPairGenerator kpGen; try { sr = SecureRandom.getInstance("SHA1PRNG"); } catch (java.security.NoSuchAlgorithmException ex) { throw new RsaException("Could not generate RSA Key", ex); } try { kpGen = KeyPairGenerator.getInstance("RSA", "BC"); } catch (java.security.NoSuchAlgorithmException ex) { throw new RsaException("No such Algo RSA"); } catch (NoSuchProviderException ex) { throw new RsaException("No such Provider BC"); } kpGen.initialize(keySize); KeyPair kp = kpGen.generateKeyPair(); return kp; } public static String shortKey(Object obj) { if (obj == null) { return "null"; } else if (obj instanceof JCERSAPublicKey) { JCERSAPublicKey pubKey; pubKey = (JCERSAPublicKey) obj; String shortMod = pubKey.getModulus().mod(m16bit).toString(16); String shortE = pubKey.getPublicExponent().mod(m16bit).toString(16); return String.format("(%s,%s)", shortMod, shortE); } else if (obj instanceof JCERSAPrivateCrtKey) { JCERSAPrivateCrtKey privKey = (JCERSAPrivateCrtKey) obj; JCERSAPublicKey pubKey; try { pubKey = HackedProviderAccessor.newJCERSAPublicKey(privKey); } catch (InvalidKeySpecException ex) { return "Nak"; } return shortKey(pubKey); } else if (obj instanceof KeyPair) { KeyPair kp = (KeyPair) obj; return shortKey(kp.getPrivate()); } return "NaK"; } public static JCERSAPublicKey newJCERSAPublicKey(Object obj) throws NotAnRSAKeyException { if (obj == null) { throw new NotAnRSAKeyException("Key was null"); } else if (obj instanceof JCERSAPublicKey) { // already a JCERSAPublicKey return (JCERSAPublicKey) obj; } else if (obj instanceof JCERSAPrivateCrtKey) { try { return newJCERSAPublicKey(HackedProviderAccessor.newJCERSAPublicKey((JCERSAPrivateCrtKey) obj)); } catch (InvalidKeySpecException ex) { throw new NotAnRSAKeyException("Could not retrieve Public Key from incomming object", ex); } } else if (obj instanceof KeyPair) { return newJCERSAPublicKey(((KeyPair) obj).getPublic()); } else { throw new NotAnRSAKeyException(String.format("Object was of class %s", obj.getClass().getName())); } } public static BigInteger getModulus(Object obj) throws NotAnRSAKeyException { return newJCERSAPublicKey(obj).getModulus(); } public static int modSize(Object obj) { JCERSAPublicKey pubKey; try { pubKey = newJCERSAPublicKey(obj); } catch (NotAnRSAKeyException ex) { return -1; } return pubKey.getModulus().bitLength(); } public static String objToString(Object obj) { if (obj instanceof JCERSAPublicKey) { JCERSAPublicKey jPubKey = (JCERSAPublicKey) obj; String exp = jPubKey.getPublicExponent().toString(16); String mod = jPubKey.getModulus().toString(16); } return ""; } public static String KeyPairToString(KeyPair kp) { return "Implement Me"; } public static PemObject toPKCS8(KeyPair kp) throws java.security.NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException { PKCS8Generator gen = new PKCS8Generator(kp.getPrivate()); PemObject out = gen.generate(); Debug.nop(); return out; } }