1 package org.bouncycastle.crypto.util; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.math.BigInteger; 6 7 import org.bouncycastle.asn1.ASN1Encodable; 8 import org.bouncycastle.asn1.ASN1InputStream; 9 import org.bouncycastle.asn1.ASN1Integer; 10 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 11 import org.bouncycastle.asn1.ASN1OctetString; 12 import org.bouncycastle.asn1.ASN1Primitive; 13 import org.bouncycastle.asn1.DEROctetString; 14 // Android-removed: Unsupported algorithm 15 // import org.bouncycastle.asn1.oiw.ElGamalParameter; 16 import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 17 import org.bouncycastle.asn1.pkcs.DHParameter; 18 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 19 import org.bouncycastle.asn1.pkcs.RSAPublicKey; 20 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 21 import org.bouncycastle.asn1.x509.DSAParameter; 22 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 23 import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; 24 import org.bouncycastle.asn1.x9.DHPublicKey; 25 import org.bouncycastle.asn1.x9.DomainParameters; 26 import org.bouncycastle.asn1.x9.ECNamedCurveTable; 27 import org.bouncycastle.asn1.x9.ValidationParams; 28 import org.bouncycastle.asn1.x9.X962Parameters; 29 import org.bouncycastle.asn1.x9.X9ECParameters; 30 import org.bouncycastle.asn1.x9.X9ECPoint; 31 import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 32 import org.bouncycastle.crypto.ec.CustomNamedCurves; 33 import org.bouncycastle.crypto.params.AsymmetricKeyParameter; 34 import org.bouncycastle.crypto.params.DHParameters; 35 import org.bouncycastle.crypto.params.DHPublicKeyParameters; 36 import org.bouncycastle.crypto.params.DHValidationParameters; 37 import org.bouncycastle.crypto.params.DSAParameters; 38 import org.bouncycastle.crypto.params.DSAPublicKeyParameters; 39 import org.bouncycastle.crypto.params.ECDomainParameters; 40 import org.bouncycastle.crypto.params.ECNamedDomainParameters; 41 import org.bouncycastle.crypto.params.ECPublicKeyParameters; 42 // Android-removed: Unsupported algorithm 43 // import org.bouncycastle.crypto.params.ElGamalParameters; 44 // import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters; 45 import org.bouncycastle.crypto.params.RSAKeyParameters; 46 47 /** 48 * Factory to create asymmetric public key parameters for asymmetric ciphers from range of 49 * ASN.1 encoded SubjectPublicKeyInfo objects. 50 */ 51 public class PublicKeyFactory 52 { 53 /** 54 * Create a public key from a SubjectPublicKeyInfo encoding 55 * 56 * @param keyInfoData the SubjectPublicKeyInfo encoding 57 * @return the appropriate key parameter 58 * @throws IOException on an error decoding the key 59 */ 60 public static AsymmetricKeyParameter createKey(byte[] keyInfoData) throws IOException 61 { 62 return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData))); 63 } 64 65 /** 66 * Create a public key from a SubjectPublicKeyInfo encoding read from a stream 67 * 68 * @param inStr the stream to read the SubjectPublicKeyInfo encoding from 69 * @return the appropriate key parameter 70 * @throws IOException on an error decoding the key 71 */ 72 public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException 73 { 74 return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); 75 } 76 77 /** 78 * Create a public key from the passed in SubjectPublicKeyInfo 79 * 80 * @param keyInfo the SubjectPublicKeyInfo containing the key data 81 * @return the appropriate key parameter 82 * @throws IOException on an error decoding the key 83 */ 84 public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException 85 { 86 AlgorithmIdentifier algId = keyInfo.getAlgorithm(); 87 88 if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption) 89 || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa)) 90 { 91 RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey()); 92 93 return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent()); 94 } 95 else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber)) 96 { 97 DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey()); 98 99 BigInteger y = dhPublicKey.getY(); 100 101 DomainParameters dhParams = DomainParameters.getInstance(algId.getParameters()); 102 103 BigInteger p = dhParams.getP(); 104 BigInteger g = dhParams.getG(); 105 BigInteger q = dhParams.getQ(); 106 107 BigInteger j = null; 108 if (dhParams.getJ() != null) 109 { 110 j = dhParams.getJ(); 111 } 112 113 DHValidationParameters validation = null; 114 ValidationParams dhValidationParms = dhParams.getValidationParams(); 115 if (dhValidationParms != null) 116 { 117 byte[] seed = dhValidationParms.getSeed(); 118 BigInteger pgenCounter = dhValidationParms.getPgenCounter(); 119 120 // TODO Check pgenCounter size? 121 122 validation = new DHValidationParameters(seed, pgenCounter.intValue()); 123 } 124 125 return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation)); 126 } 127 else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement)) 128 { 129 DHParameter params = DHParameter.getInstance(algId.getParameters()); 130 ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); 131 132 BigInteger lVal = params.getL(); 133 int l = lVal == null ? 0 : lVal.intValue(); 134 DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l); 135 136 return new DHPublicKeyParameters(derY.getValue(), dhParams); 137 } 138 // BEGIN Android-removed: Unsupported algorithm 139 /* 140 else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm)) 141 { 142 ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters()); 143 ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); 144 145 return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters( 146 params.getP(), params.getG())); 147 } 148 */ 149 // END Android-removed: Unsupported algorithm 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