Home | History | Annotate | Download | only in util
      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