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.ASN1OctetString; 12import org.bouncycastle.asn1.ASN1Primitive; 13import org.bouncycastle.asn1.DEROctetString; 14// BEGIN android-removed 15// import org.bouncycastle.asn1.oiw.ElGamalParameter; 16// END android-removed 17import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 18import org.bouncycastle.asn1.pkcs.DHParameter; 19import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 20import org.bouncycastle.asn1.pkcs.RSAPublicKey; 21import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 22import org.bouncycastle.asn1.x509.DSAParameter; 23import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 24import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; 25import org.bouncycastle.asn1.x9.DHPublicKey; 26import org.bouncycastle.asn1.x9.DomainParameters; 27import org.bouncycastle.asn1.x9.ECNamedCurveTable; 28import org.bouncycastle.asn1.x9.ValidationParams; 29import org.bouncycastle.asn1.x9.X962Parameters; 30import org.bouncycastle.asn1.x9.X9ECParameters; 31import org.bouncycastle.asn1.x9.X9ECPoint; 32import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 33import org.bouncycastle.crypto.ec.CustomNamedCurves; 34import org.bouncycastle.crypto.params.AsymmetricKeyParameter; 35import org.bouncycastle.crypto.params.DHParameters; 36import org.bouncycastle.crypto.params.DHPublicKeyParameters; 37import org.bouncycastle.crypto.params.DHValidationParameters; 38import org.bouncycastle.crypto.params.DSAParameters; 39import org.bouncycastle.crypto.params.DSAPublicKeyParameters; 40import org.bouncycastle.crypto.params.ECDomainParameters; 41import org.bouncycastle.crypto.params.ECNamedDomainParameters; 42import org.bouncycastle.crypto.params.ECPublicKeyParameters; 43// BEGIN android-removed 44// import org.bouncycastle.crypto.params.ElGamalParameters; 45// import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters; 46// END android-removed 47import org.bouncycastle.crypto.params.RSAKeyParameters; 48 49/** 50 * Factory to create asymmetric public key parameters for asymmetric ciphers from range of 51 * ASN.1 encoded SubjectPublicKeyInfo objects. 52 */ 53public class PublicKeyFactory 54{ 55 /** 56 * Create a public key from a SubjectPublicKeyInfo encoding 57 * 58 * @param keyInfoData the SubjectPublicKeyInfo encoding 59 * @return the appropriate key parameter 60 * @throws IOException on an error decoding the key 61 */ 62 public static AsymmetricKeyParameter createKey(byte[] keyInfoData) throws IOException 63 { 64 return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData))); 65 } 66 67 /** 68 * Create a public key from a SubjectPublicKeyInfo encoding read from a stream 69 * 70 * @param inStr the stream to read the SubjectPublicKeyInfo encoding from 71 * @return the appropriate key parameter 72 * @throws IOException on an error decoding the key 73 */ 74 public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException 75 { 76 return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); 77 } 78 79 /** 80 * Create a public key from the passed in SubjectPublicKeyInfo 81 * 82 * @param keyInfo the SubjectPublicKeyInfo containing the key data 83 * @return the appropriate key parameter 84 * @throws IOException on an error decoding the key 85 */ 86 public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException 87 { 88 AlgorithmIdentifier algId = keyInfo.getAlgorithm(); 89 90 if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption) 91 || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa)) 92 { 93 RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey()); 94 95 return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent()); 96 } 97 else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber)) 98 { 99 DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey()); 100 101 BigInteger y = dhPublicKey.getY(); 102 103 DomainParameters dhParams = DomainParameters.getInstance(algId.getParameters()); 104 105 BigInteger p = dhParams.getP(); 106 BigInteger g = dhParams.getG(); 107 BigInteger q = dhParams.getQ(); 108 109 BigInteger j = null; 110 if (dhParams.getJ() != null) 111 { 112 j = dhParams.getJ(); 113 } 114 115 DHValidationParameters validation = null; 116 ValidationParams dhValidationParms = dhParams.getValidationParams(); 117 if (dhValidationParms != null) 118 { 119 byte[] seed = dhValidationParms.getSeed(); 120 BigInteger pgenCounter = dhValidationParms.getPgenCounter(); 121 122 // TODO Check pgenCounter size? 123 124 validation = new DHValidationParameters(seed, pgenCounter.intValue()); 125 } 126 127 return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation)); 128 } 129 else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement)) 130 { 131 DHParameter params = DHParameter.getInstance(algId.getParameters()); 132 ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); 133 134 BigInteger lVal = params.getL(); 135 int l = lVal == null ? 0 : lVal.intValue(); 136 DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l); 137 138 return new DHPublicKeyParameters(derY.getValue(), dhParams); 139 } 140 // BEGIN android-removed 141 // else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm)) 142 // { 143 // ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters()); 144 // ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); 145 // 146 // return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters( 147 // params.getP(), params.getG())); 148 // } 149 // END android-removed 150 else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa) 151 || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1)) 152 { 153 ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); 154 ASN1Encodable de = algId.getParameters(); 155 156 DSAParameters parameters = null; 157 if (de != null) 158 { 159 DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive()); 160 parameters = new DSAParameters(params.getP(), params.getQ(), params.getG()); 161 } 162 163 return new DSAPublicKeyParameters(derY.getValue(), parameters); 164 } 165 else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey)) 166 { 167 X962Parameters params = X962Parameters.getInstance(algId.getParameters()); 168 169 X9ECParameters x9; 170 ECDomainParameters dParams; 171 172 if (params.isNamedCurve()) 173 { 174 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); 175 176 x9 = CustomNamedCurves.getByOID(oid); 177 if (x9 == null) 178 { 179 x9 = ECNamedCurveTable.getByOID(oid); 180 } 181 dParams = new ECNamedDomainParameters( 182 oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); 183 } 184 else 185 { 186 x9 = X9ECParameters.getInstance(params.getParameters()); 187 dParams = new ECDomainParameters( 188 x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); 189 } 190 191 ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes()); 192 X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key); 193 194 return new ECPublicKeyParameters(derQ.getPoint(), dParams); 195 } 196 else 197 { 198 throw new RuntimeException("algorithm identifier in key not recognised"); 199 } 200 } 201} 202