1package org.bouncycastle.crypto.util; 2 3import java.io.IOException; 4import java.io.InputStream; 5import java.math.BigInteger; 6 7import org.bouncycastle.asn1.ASN1Encodable; 8import org.bouncycastle.asn1.ASN1InputStream; 9import org.bouncycastle.asn1.ASN1Integer; 10import org.bouncycastle.asn1.ASN1ObjectIdentifier; 11import org.bouncycastle.asn1.ASN1Primitive; 12import org.bouncycastle.asn1.ASN1Sequence; 13// BEGIN android-removed 14// import org.bouncycastle.asn1.oiw.ElGamalParameter; 15// END android-removed 16import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 17import org.bouncycastle.asn1.pkcs.DHParameter; 18import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 19import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; 20import org.bouncycastle.asn1.pkcs.RSAPrivateKey; 21import org.bouncycastle.asn1.sec.ECPrivateKey; 22import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 23import org.bouncycastle.asn1.x509.DSAParameter; 24import org.bouncycastle.asn1.x9.ECNamedCurveTable; 25import org.bouncycastle.asn1.x9.X962Parameters; 26import org.bouncycastle.asn1.x9.X9ECParameters; 27import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 28import org.bouncycastle.crypto.params.AsymmetricKeyParameter; 29import org.bouncycastle.crypto.params.DHParameters; 30import org.bouncycastle.crypto.params.DHPrivateKeyParameters; 31import org.bouncycastle.crypto.params.DSAParameters; 32import org.bouncycastle.crypto.params.DSAPrivateKeyParameters; 33import org.bouncycastle.crypto.params.ECDomainParameters; 34import org.bouncycastle.crypto.params.ECPrivateKeyParameters; 35// BEGIN android-removed 36// import org.bouncycastle.crypto.params.ElGamalParameters; 37// import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters; 38// END android-removed 39import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; 40 41/** 42 * Factory for creating private key objects from PKCS8 PrivateKeyInfo objects. 43 */ 44public class PrivateKeyFactory 45{ 46 /** 47 * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding. 48 * 49 * @param privateKeyInfoData the PrivateKeyInfo encoding 50 * @return a suitable private key parameter 51 * @throws IOException on an error decoding the key 52 */ 53 public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) throws IOException 54 { 55 return createKey(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(privateKeyInfoData))); 56 } 57 58 /** 59 * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding read from a 60 * stream. 61 * 62 * @param inStr the stream to read the PrivateKeyInfo encoding from 63 * @return a suitable private key parameter 64 * @throws IOException on an error decoding the key 65 */ 66 public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException 67 { 68 return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); 69 } 70 71 /** 72 * Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object. 73 * 74 * @param keyInfo the PrivateKeyInfo object containing the key material 75 * @return a suitable private key parameter 76 * @throws IOException on an error decoding the key 77 */ 78 public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) throws IOException 79 { 80 AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm(); 81 82 if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)) 83 { 84 RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey()); 85 86 return new RSAPrivateCrtKeyParameters(keyStructure.getModulus(), 87 keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(), 88 keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(), 89 keyStructure.getExponent2(), keyStructure.getCoefficient()); 90 } 91 // TODO? 92// else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber)) 93 else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement)) 94 { 95 DHParameter params = DHParameter.getInstance(algId.getParameters()); 96 ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); 97 98 BigInteger lVal = params.getL(); 99 int l = lVal == null ? 0 : lVal.intValue(); 100 DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l); 101 102 return new DHPrivateKeyParameters(derX.getValue(), dhParams); 103 } 104 // BEGIN android-removed 105 // else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm)) 106 // { 107 // ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters()); 108 // ASN1Integer = (ASN1Integer)keyInfo.parsePrivateKey(); 109 // 110 // return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters( 111 // params.getP(), params.getG())); 112 // } 113 // END android-removed 114 else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)) 115 { 116 ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); 117 ASN1Encodable de = algId.getParameters(); 118 119 DSAParameters parameters = null; 120 if (de != null) 121 { 122 DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive()); 123 parameters = new DSAParameters(params.getP(), params.getQ(), params.getG()); 124 } 125 126 return new DSAPrivateKeyParameters(derX.getValue(), parameters); 127 } 128 else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey)) 129 { 130 X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters()); 131 132 X9ECParameters x9; 133 if (params.isNamedCurve()) 134 { 135 ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters()); 136 x9 = ECNamedCurveTable.getByOID(oid); 137 } 138 else 139 { 140 x9 = X9ECParameters.getInstance(params.getParameters()); 141 } 142 143 ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey()); 144 BigInteger d = ec.getKey(); 145 146 // TODO We lose any named parameters here 147 148 ECDomainParameters dParams = new ECDomainParameters( 149 x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); 150 151 return new ECPrivateKeyParameters(d, dParams); 152 } 153 else 154 { 155 throw new RuntimeException("algorithm identifier in key not recognised"); 156 } 157 } 158} 159