18212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompackage org.bouncycastle.jce.provider;
28212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
38212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.io.IOException;
48212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.io.ObjectInputStream;
58212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.io.ObjectOutputStream;
68212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.math.BigInteger;
78212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.interfaces.ECPublicKey;
88212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.ECParameterSpec;
98212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.ECPoint;
108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.ECPublicKeySpec;
118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.EllipticCurve;
128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable;
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier;
158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.ASN1OctetString;
164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Primitive;
178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.ASN1Sequence;
188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.DERBitString;
198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.DERNull;
208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.DEROctetString;
218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// BEGIN android-removed
22e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// END android-removed
268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x509.AlgorithmIdentifier;
278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x9.X962Parameters;
298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x9.X9ECParameters;
308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x9.X9ECPoint;
318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x9.X9IntegerConverter;
328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.crypto.params.ECDomainParameters;
348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.crypto.params.ECPublicKeyParameters;
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jcajce.provider.asymmetric.ec.EC5Util;
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jcajce.provider.asymmetric.ec.ECUtil;
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// BEGIN android-removed
398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// import org.bouncycastle.jce.ECGOST3410NamedCurveTable;
408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// END android-removed
418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.jce.interfaces.ECPointEncoder;
428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// BEGIN android-removed
438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// END android-removed
458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.jce.spec.ECNamedCurveSpec;
468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.math.ec.ECCurve;
478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompublic class JCEECPublicKey
498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    implements ECPublicKey, org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder
508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom{
518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private String                  algorithm = "EC";
528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private org.bouncycastle.math.ec.ECPoint q;
538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private ECParameterSpec         ecSpec;
548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private boolean                 withCompression;
558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    // BEGIN android-removed
568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    // private GOST3410PublicKeyAlgParameters       gostParams;
578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    // END android-removed
588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public JCEECPublicKey(
608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        String              algorithm,
618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        JCEECPublicKey      key)
628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.algorithm = algorithm;
648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.q = key.q;
658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.ecSpec = key.ecSpec;
668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.withCompression = key.withCompression;
678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // BEGIN android-removed
688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // this.gostParams = key.gostParams;
698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // END android-removed
708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public JCEECPublicKey(
738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        String              algorithm,
748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPublicKeySpec     spec)
758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.algorithm = algorithm;
778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.ecSpec = spec.getParams();
788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.q = EC5Util.convertPoint(ecSpec, spec.getW(), false);
798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public JCEECPublicKey(
828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        String              algorithm,
838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        org.bouncycastle.jce.spec.ECPublicKeySpec     spec)
848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.algorithm = algorithm;
868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.q = spec.getQ();
878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (spec.getParams() != null) // can be null if implictlyCa
898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECCurve curve = spec.getParams().getCurve();
918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed());
928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams());
948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (q.getCurve() == null)
988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                org.bouncycastle.jce.spec.ECParameterSpec s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
1008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false);
1028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
1038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.ecSpec = null;
1048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public JCEECPublicKey(
1088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        String                  algorithm,
1098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPublicKeyParameters   params,
1108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECParameterSpec         spec)
1118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECDomainParameters      dp = params.getParameters();
1138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.algorithm = algorithm;
1158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.q = params.getQ();
1168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (spec == null)
1188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
1208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.ecSpec = createSpec(ellipticCurve, dp);
1228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
1248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.ecSpec = spec;
1268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public JCEECPublicKey(
1308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        String                  algorithm,
1318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPublicKeyParameters   params,
1328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        org.bouncycastle.jce.spec.ECParameterSpec         spec)
1338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECDomainParameters      dp = params.getParameters();
1358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.algorithm = algorithm;
1378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.q = params.getQ();
1388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (spec == null)
1408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
1428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.ecSpec = createSpec(ellipticCurve, dp);
1448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
1468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed());
1488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec);
1508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /*
1548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * called for implicitCA
1558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
1568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public JCEECPublicKey(
1578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        String                  algorithm,
1588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPublicKeyParameters   params)
1598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.algorithm = algorithm;
1618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.q = params.getQ();
1628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.ecSpec = null;
1638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private ECParameterSpec createSpec(EllipticCurve ellipticCurve, ECDomainParameters dp)
1668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return new ECParameterSpec(
1688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ellipticCurve,
1698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                new ECPoint(
1708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        dp.getG().getX().toBigInteger(),
1718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        dp.getG().getY().toBigInteger()),
1728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        dp.getN(),
1738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        dp.getH().intValue());
1748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public JCEECPublicKey(
1778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPublicKey     key)
1788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.algorithm = key.getAlgorithm();
1808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.ecSpec = key.getParams();
1818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.q = EC5Util.convertPoint(this.ecSpec, key.getW(), false);
1828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    JCEECPublicKey(
1858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SubjectPublicKeyInfo    info)
1868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        populateFromPubKeyInfo(info);
1888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private void populateFromPubKeyInfo(SubjectPublicKeyInfo info)
1918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // BEGIN android-removed
1938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // if (info.getAlgorithmId().getObjectId().equals(CryptoProObjectIdentifiers.gostR3410_2001))
1948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // {
1958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     DERBitString bits = info.getPublicKeyData();
1968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     ASN1OctetString key;
1978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     this.algorithm = "ECGOST3410";
1988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
1998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     try
2008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     {
2014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         key = (ASN1OctetString) ASN1Primitive.fromByteArray(bits.getBytes());
2028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     }
2038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     catch (IOException ex)
2048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     {
2058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         throw new IllegalArgumentException("error recovering public key");
2068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     }
2078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     byte[]          keyEnc = key.getOctets();
2098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     byte[]          x = new byte[32];
2108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     byte[]          y = new byte[32];
2118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     for (int i = 0; i != x.length; i++)
2138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     {
2148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         x[i] = keyEnc[32 - 1 - i];
2158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     }
2168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     for (int i = 0; i != y.length; i++)
2188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     {
2198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         y[i] = keyEnc[64 - 1 - i];
2208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     }
2218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     gostParams = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithmId().getParameters());
2238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()));
2258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     ECCurve curve = spec.getCurve();
2278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
2288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false);
2308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     ecSpec = new ECNamedCurveSpec(
2328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //             ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
2338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //             ellipticCurve,
2348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //             new ECPoint(
2358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                     spec.getG().getX().toBigInteger(),
2368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                     spec.getG().getY().toBigInteger()),
2378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                     spec.getN(), spec.getH());
2388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
2398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // }
2408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // else
2418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // END android-removed
2428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            X962Parameters params = new X962Parameters((ASN1Primitive)info.getAlgorithmId().getParameters());
2448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECCurve                 curve;
2458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            EllipticCurve           ellipticCurve;
2468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (params.isNamedCurve())
2488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
2508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
2518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                curve = ecP.getCurve();
2538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
2548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ecSpec = new ECNamedCurveSpec(
2568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        ECUtil.getCurveName(oid),
2578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        ellipticCurve,
2588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        new ECPoint(
2598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                                ecP.getG().getX().toBigInteger(),
2608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                                ecP.getG().getY().toBigInteger()),
2618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        ecP.getN(),
2628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        ecP.getH());
2638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else if (params.isImplicitlyCA())
2658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ecSpec = null;
2674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                curve = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa().getCurve();
2688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
2708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                X9ECParameters          ecP = X9ECParameters.getInstance(params.getParameters());
2728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                curve = ecP.getCurve();
2748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
2758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                this.ecSpec = new ECParameterSpec(
2778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        ellipticCurve,
2788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        new ECPoint(
2798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                                ecP.getG().getX().toBigInteger(),
2808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                                ecP.getG().getY().toBigInteger()),
2818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        ecP.getN(),
2828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        ecP.getH().intValue());
2838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            DERBitString    bits = info.getPublicKeyData();
2868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            byte[]          data = bits.getBytes();
2878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ASN1OctetString key = new DEROctetString(data);
2888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            //
2908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // extra octet string - one of our old certs...
2918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            //
2928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (data[0] == 0x04 && data[1] == data.length - 2
2938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                && (data[2] == 0x02 || data[2] == 0x03))
2948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                int qLength = new X9IntegerConverter().getByteLength(curve);
2968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (qLength >= data.length - 3)
2988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
2998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    try
3008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    {
3014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        key = (ASN1OctetString) ASN1Primitive.fromByteArray(data);
3028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    }
3038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    catch (IOException ex)
3048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    {
3058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        throw new IllegalArgumentException("error recovering public key");
3068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    }
3078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
3088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            X9ECPoint derQ = new X9ECPoint(curve, key);
3108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.q = derQ.getPoint();
3128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
3148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public String getAlgorithm()
3168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
3178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return algorithm;
3188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
3198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public String getFormat()
3218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
3228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return "X.509";
3238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
3248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public byte[] getEncoded()
3268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
3278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ASN1Encodable        params;
3288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SubjectPublicKeyInfo info;
3298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // BEGIN android-removed
3318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // if (algorithm.equals("ECGOST3410"))
3328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // {
3338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     if (gostParams != null)
3348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     {
3358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         params = gostParams;
3368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     }
3378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     else
3388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     {
3398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         if (ecSpec instanceof ECNamedCurveSpec)
3408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         {
3418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //             params = new GOST3410PublicKeyAlgParameters(
3428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                            ECGOST3410NamedCurves.getOID(((ECNamedCurveSpec)ecSpec).getName()),
3438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                            CryptoProObjectIdentifiers.gostR3411_94_CryptoProParamSet);
3448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         }
3458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         else
3468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         {   // strictly speaking this may not be applicable...
3478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //             ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
3488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
3498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //             X9ECParameters ecP = new X9ECParameters(
3508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                 curve,
3518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                 EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
3528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                 ecSpec.getOrder(),
3538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                 BigInteger.valueOf(ecSpec.getCofactor()),
3548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //                 ecSpec.getCurve().getSeed());
3558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
3568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //             params = new X962Parameters(ecP);
3578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //         }
3588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     }
3598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
3608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     BigInteger      bX = this.q.getX().toBigInteger();
3618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     BigInteger      bY = this.q.getY().toBigInteger();
3628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     byte[]          encKey = new byte[64];
3638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
3648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     extractBytes(encKey, 0, bX);
3658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //     extractBytes(encKey, 32, bY);
3668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        //
3674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params), new DEROctetString(encKey));
3688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // }
3698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // else
3708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // END android-removed
3718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (ecSpec instanceof ECNamedCurveSpec)
3738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
3756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (curveOid == null)
3766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
3774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
3786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
3798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                params = new X962Parameters(curveOid);
3808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else if (ecSpec == null)
3828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                params = new X962Parameters(DERNull.INSTANCE);
3848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
3868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
3888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                X9ECParameters ecP = new X9ECParameters(
3908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    curve,
3918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
3928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    ecSpec.getOrder(),
3938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    BigInteger.valueOf(ecSpec.getCofactor()),
3948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    ecSpec.getCurve().getSeed());
3958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                params = new X962Parameters(ecP);
3978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECCurve curve = this.engineGetQ().getCurve();
4008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ASN1OctetString p = (ASN1OctetString)
4014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                new X9ECPoint(curve.createPoint(this.getQ().getX().toBigInteger(), this.getQ().getY().toBigInteger(), withCompression)).toASN1Primitive();
4028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
4048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return KeyUtil.getEncodedSubjectPublicKeyInfo(info);
4078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private void extractBytes(byte[] encKey, int offSet, BigInteger bI)
4108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte[] val = bI.toByteArray();
4128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (val.length < 32)
4138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            byte[] tmp = new byte[32];
4158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            System.arraycopy(val, 0, tmp, tmp.length - val.length, val.length);
4166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            val = tmp;
4178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        for (int i = 0; i != 32; i++)
4208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            encKey[offSet + i] = val[val.length - 1 - i];
4228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public ECParameterSpec getParams()
4268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return ecSpec;
4288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public org.bouncycastle.jce.spec.ECParameterSpec getParameters()
4318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (ecSpec == null)     // implictlyCA
4338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return null;
4358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return EC5Util.convertSpec(ecSpec, withCompression);
4388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public ECPoint getW()
4418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return new ECPoint(q.getX().toBigInteger(), q.getY().toBigInteger());
4438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public org.bouncycastle.math.ec.ECPoint getQ()
4468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (ecSpec == null)
4488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
4508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getX(), q.getY());
4528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
4548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getX(), q.getY());
4568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return q;
4608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public org.bouncycastle.math.ec.ECPoint engineGetQ()
4638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return q;
4658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    org.bouncycastle.jce.spec.ECParameterSpec engineGetSpec()
4688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (ecSpec != null)
4708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return EC5Util.convertSpec(ecSpec, withCompression);
4728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
4758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public String toString()
4788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        StringBuffer    buf = new StringBuffer();
4808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        String          nl = System.getProperty("line.separator");
4818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        buf.append("EC Public Key").append(nl);
4838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        buf.append("            X: ").append(this.q.getX().toBigInteger().toString(16)).append(nl);
4848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        buf.append("            Y: ").append(this.q.getY().toBigInteger().toString(16)).append(nl);
4858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return buf.toString();
4878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public void setPointFormat(String style)
4918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom       withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
4938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public boolean equals(Object o)
4968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (!(o instanceof JCEECPublicKey))
4988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return false;
5008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        JCEECPublicKey other = (JCEECPublicKey)o;
5038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return engineGetQ().equals(other.engineGetQ()) && (engineGetSpec().equals(other.engineGetSpec()));
5058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
5068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public int hashCode()
5088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
5098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return engineGetQ().hashCode() ^ engineGetSpec().hashCode();
5108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
5118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private void readObject(
5138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ObjectInputStream in)
5148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        throws IOException, ClassNotFoundException
5158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
5168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte[] enc = (byte[])in.readObject();
5178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        populateFromPubKeyInfo(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(enc)));
5198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.algorithm = (String)in.readObject();
5218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.withCompression = in.readBoolean();
5228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
5238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private void writeObject(
5258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ObjectOutputStream out)
5268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        throws IOException
5278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
5288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        out.writeObject(this.getEncoded());
5298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        out.writeObject(algorithm);
5308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        out.writeBoolean(withCompression);
5318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
5328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom}
533