Ejemplo n.º 1
0
  /**
   * create from an issuer certificate and the serial number of the certificate it signed.
   *
   * @exception OCSPException if any problems occur creating the id fields.
   */
  public CertificateID(
      String hashAlgorithm, X509Certificate issuerCert, BigInteger number, String provider)
      throws OCSPException {
    try {
      MessageDigest digest = MessageDigest.getInstance(hashAlgorithm, provider);
      AlgorithmIdentifier hashAlg =
          new AlgorithmIdentifier(new DERObjectIdentifier(hashAlgorithm), new DERNull());

      X509Principal issuerName = PrincipalUtil.getSubjectX509Principal(issuerCert);

      digest.update(issuerName.getEncoded());

      ASN1OctetString issuerNameHash = new DEROctetString(digest.digest());
      PublicKey issuerKey = issuerCert.getPublicKey();

      ASN1InputStream aIn = new ASN1InputStream(issuerKey.getEncoded());
      SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject());

      digest.update(info.getPublicKeyData().getBytes());

      ASN1OctetString issuerKeyHash = new DEROctetString(digest.digest());

      DERInteger serialNumber = new DERInteger(number);

      this.id = new CertID(hashAlg, issuerNameHash, issuerKeyHash, serialNumber);
    } catch (Exception e) {
      throw new OCSPException("problem creating ID: " + e, e);
    }
  }
Ejemplo n.º 2
0
  public CryptEngineImpl(Context ctx) throws Exception {

    // Получаем действующее хранилище
    IKeyStorage storage = KeyStorageFactory.getKeyStorage(ctx);

    Log.v("TFORWARD.CryptEngineImpl", "Decoding public key...");
    byte[] publicKey = Base64.decode(storage.getKey(IKeyStorage.PUBLIC_KEY_TYPE), Base64.DEFAULT);

    Log.v("TFORWARD.CryptEngineImpl", "Decoding ASN1 Structure");
    ASN1InputStream asnStream = new ASN1InputStream(publicKey);

    ASN1Sequence sequence = null;
    try {
      Log.v("TFORWARD.CryptEngineImpl", "Reading ASN1 Sequence");
      sequence = (ASN1Sequence) asnStream.readObject();
    } finally {
      asnStream.close();
    }

    Log.v("TFORWARD.CryptEngineImpl", "Creating certificate. " + sequence.size());
    Certificate certificate = Certificate.getInstance(sequence);
    SubjectPublicKeyInfo publicKeyInfo = certificate.getSubjectPublicKeyInfo();

    RSAPublicKey publicKeyStructure = RSAPublicKey.getInstance(publicKeyInfo.parsePublicKey());
    BigInteger mod = publicKeyStructure.getModulus();
    BigInteger pubExp = publicKeyStructure.getPublicExponent();

    publicRsaKey = new RSAKeyParameters(false, mod, pubExp);

    // ------------------------ PRIVATE KEY --------------------------------
    byte[] privateKeyData =
        Base64.decode(storage.getKey(IKeyStorage.SECRET_KEY_TYPE), Base64.DEFAULT);
    asnStream = new ASN1InputStream(privateKeyData);

    ASN1Sequence asnSequence = null;
    try {
      asnSequence = (ASN1Sequence) asnStream.readObject();
    } finally {
      asnStream.close();
    }

    RSAPrivateKey privateKey = RSAPrivateKey.getInstance(asnSequence);
    privateRsaKey =
        new RSAPrivateCrtKeyParameters(
            privateKey.getModulus(),
            privateKey.getPublicExponent(),
            privateKey.getPrivateExponent(),
            privateKey.getPrime1(),
            privateKey.getPrime2(),
            privateKey.getExponent1(),
            privateKey.getExponent2(),
            privateKey.getCoefficient());

    RSAEngine engine = new RSAEngine();
    digest = new MD5Digest();
    cipher = new PKCS1Encoding(engine);
  }
  protected static AlgorithmIdentifier getAlgorithmIdentifier(PublicKey key)
      throws CertPathValidatorException {
    try {
      ASN1InputStream aIn = new ASN1InputStream(key.getEncoded());

      SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject());

      return info.getAlgorithmId();
    } catch (Exception e) {
      throw new ExtCertPathValidatorException("Subject public key cannot be decoded.", e);
    }
  }
  protected static AlgorithmIdentifier getAlgorithmIdentifier(PublicKey key)
      throws CertPathValidatorException {
    try {
      ASN1InputStream aIn = new ASN1InputStream(key.getEncoded());

      SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject());

      return info.getAlgorithmId();
    } catch (IOException e) {
      throw new CertPathValidatorException("exception processing public key");
    }
  }
  public void testSubKeyId() throws Exception {
    MimeBodyPart msg = SMIMETestUtil.makeMimeBodyPart("WallaWallaWashington");

    SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();

    //
    // create a subject key id - this has to be done the same way as
    // it is done in the certificate associated with the private key
    //
    MessageDigest dig = MessageDigest.getInstance("SHA1", BC);
    dig.update(
        SubjectPublicKeyInfo.getInstance(_reciCert.getPublicKey().getEncoded())
            .getPublicKeyData()
            .getBytes());

    gen.addRecipientInfoGenerator(
        new JceKeyTransRecipientInfoGenerator(dig.digest(), _reciCert.getPublicKey())
            .setProvider(BC));

    //
    // generate a MimeBodyPart object which encapsulates the content
    // we want encrypted.
    //

    MimeBodyPart mp =
        gen.generate(
            msg,
            new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build());

    SMIMEEnveloped m = new SMIMEEnveloped(mp);

    dig.update(
        SubjectPublicKeyInfo.getInstance(_reciCert.getPublicKey().getEncoded())
            .getPublicKeyData()
            .getBytes());

    RecipientId recId = new KeyTransRecipientId(dig.digest());

    RecipientInformationStore recipients = m.getRecipientInfos();
    RecipientInformation recipient = recipients.get(recId);

    MimeBodyPart res =
        SMIMEUtil.toMimeBodyPart(
            recipient.getContent(
                new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)));

    verifyMessageBytes(msg, res);
  }
Ejemplo n.º 6
0
  /**
   * Create a self-signed X.509 Certificate. From
   * http://bfo.com/blog/2011/03/08/odds_and_ends_creating_a_new_x_509_certificate.html.
   *
   * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
   * @param pair the KeyPair
   * @param days how many days from now the Certificate is valid for
   * @param algorithm the signing algorithm, eg "SHA1withRSA"
   * @return the self-signed certificate
   * @throws CertificateException thrown if a security error or an IO error ocurred.
   */
  public static X509Certificate generateCertificate(
      String dn, KeyPair pair, int days, String algorithm) throws CertificateException {

    try {
      Security.addProvider(new BouncyCastleProvider());
      AlgorithmIdentifier sigAlgId =
          new DefaultSignatureAlgorithmIdentifierFinder().find(algorithm);
      AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
      AsymmetricKeyParameter privateKeyAsymKeyParam =
          PrivateKeyFactory.createKey(pair.getPrivate().getEncoded());
      SubjectPublicKeyInfo subPubKeyInfo =
          SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded());
      ContentSigner sigGen =
          new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(privateKeyAsymKeyParam);
      X500Name name = new X500Name(dn);
      Date from = new Date();
      Date to = new Date(from.getTime() + days * 86400000L);
      BigInteger sn = new BigInteger(64, new SecureRandom());

      X509v1CertificateBuilder v1CertGen =
          new X509v1CertificateBuilder(name, sn, from, to, name, subPubKeyInfo);
      X509CertificateHolder certificateHolder = v1CertGen.build(sigGen);
      return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certificateHolder);
    } catch (CertificateException ce) {
      throw ce;
    } catch (Exception e) {
      throw new CertificateException(e);
    }
  }
Ejemplo n.º 7
0
  protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
    CipherParameters param;

    if (publicKey instanceof ECPublicKey) {
      param = ECUtil.generatePublicKeyParameter(publicKey);
    } else if (publicKey instanceof GOST3410Key) {
      param = GOST3410Util.generatePublicKeyParameter(publicKey);
    } else {
      try {
        byte[] bytes = publicKey.getEncoded();

        publicKey = BouncyCastleProvider.getPublicKey(SubjectPublicKeyInfo.getInstance(bytes));

        if (publicKey instanceof ECPublicKey) {
          param = ECUtil.generatePublicKeyParameter(publicKey);
        } else {
          throw new InvalidKeyException("can't recognise key type in DSA based signer");
        }
      } catch (Exception e) {
        throw new InvalidKeyException("can't recognise key type in DSA based signer");
      }
    }

    digest.reset();
    signer.init(false, param);
  }
Ejemplo n.º 8
0
  /**
   * Generate version 1 self signed {@link java.security.cert.X509Certificate}..
   *
   * @param caKeyPair the CA key pair
   * @param subject the subject name
   * @return the x509 certificate
   * @throws Exception the exception
   */
  public static X509Certificate generateV1SelfSignedCertificate(KeyPair caKeyPair, String subject)
      throws Exception {

    try {
      X500Name subjectDN = new X500Name("CN=" + subject);
      BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
      Date validityStartDate = new Date(System.currentTimeMillis() - 100000);
      Calendar calendar = Calendar.getInstance();
      calendar.add(Calendar.YEAR, 10);
      Date validityEndDate = new Date(calendar.getTime().getTime());
      SubjectPublicKeyInfo subPubKeyInfo =
          SubjectPublicKeyInfo.getInstance(caKeyPair.getPublic().getEncoded());

      X509v1CertificateBuilder builder =
          new X509v1CertificateBuilder(
              subjectDN,
              serialNumber,
              validityStartDate,
              validityEndDate,
              subjectDN,
              subPubKeyInfo);
      X509CertificateHolder holder = builder.build(createSigner(caKeyPair.getPrivate()));

      return new JcaX509CertificateConverter().getCertificate(holder);
    } catch (Exception e) {
      throw new RuntimeException("Error creating X509v1Certificate.", e);
    }
  }
  private static ASN1OctetString fromPublicKey(PublicKey pubKey) throws InvalidKeyException {
    try {
      SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded());

      return (ASN1OctetString) (new SubjectKeyIdentifier(info).toASN1Object());
    } catch (Exception e) {
      throw new InvalidKeyException("Exception extracting key details: " + e.toString());
    }
  }
  /**
   * Converts, if possible, a key specification into a {@link BCMcElieceCCA2PublicKey}. Currently,
   * the following key specifications are supported: {@link McElieceCCA2PublicKeySpec}, {@link
   * X509EncodedKeySpec}.
   *
   * @param keySpec the key specification
   * @return the McEliece CCA2 public key
   * @throws InvalidKeySpecException if the key specification is not supported.
   */
  public PublicKey generatePublic(KeySpec keySpec) throws InvalidKeySpecException {
    if (keySpec instanceof McElieceCCA2PublicKeySpec) {
      return new BCMcElieceCCA2PublicKey((McElieceCCA2PublicKeySpec) keySpec);
    } else if (keySpec instanceof X509EncodedKeySpec) {
      // get the DER-encoded Key according to X.509 from the spec
      byte[] encKey = ((X509EncodedKeySpec) keySpec).getEncoded();

      // decode the SubjectPublicKeyInfo data structure to the pki object
      SubjectPublicKeyInfo pki;
      try {
        pki = SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(encKey));
      } catch (IOException e) {
        throw new InvalidKeySpecException(e.toString());
      }

      try {
        // --- Build and return the actual key.
        ASN1Primitive innerType = pki.parsePublicKey();
        ASN1Sequence publicKey = (ASN1Sequence) innerType;

        // decode oidString (but we don't need it right now)
        String oidString = ((ASN1ObjectIdentifier) publicKey.getObjectAt(0)).toString();

        // decode <n>
        BigInteger bigN = ((ASN1Integer) publicKey.getObjectAt(1)).getValue();
        int n = bigN.intValue();

        // decode <t>
        BigInteger bigT = ((ASN1Integer) publicKey.getObjectAt(2)).getValue();
        int t = bigT.intValue();

        // decode <matrixG>
        byte[] matrixG = ((ASN1OctetString) publicKey.getObjectAt(3)).getOctets();

        return new BCMcElieceCCA2PublicKey(new McElieceCCA2PublicKeySpec(OID, n, t, matrixG));
      } catch (IOException cce) {
        throw new InvalidKeySpecException(
            "Unable to decode X509EncodedKeySpec: " + cce.getMessage());
      }
    }

    throw new InvalidKeySpecException("Unsupported key specification: " + keySpec.getClass() + ".");
  }
 public PublicKey generatePublic(SubjectPublicKeyInfo pki) throws InvalidKeySpecException {
   // get the inner type inside the BIT STRING
   try {
     ASN1Primitive innerType = pki.parsePublicKey();
     McElieceCCA2PublicKey key = McElieceCCA2PublicKey.getInstance((ASN1Sequence) innerType);
     return new BCMcElieceCCA2PublicKey(key.getOID().getId(), key.getN(), key.getT(), key.getG());
   } catch (IOException cce) {
     throw new InvalidKeySpecException("Unable to decode X509EncodedKeySpec");
   }
 }
Ejemplo n.º 12
0
  BCGOST3410PublicKey(SubjectPublicKeyInfo info) {
    GOST3410PublicKeyAlgParameters params =
        new GOST3410PublicKeyAlgParameters((ASN1Sequence) info.getAlgorithmId().getParameters());
    DEROctetString derY;

    try {
      derY = (DEROctetString) info.parsePublicKey();

      byte[] keyEnc = derY.getOctets();
      byte[] keyBytes = new byte[keyEnc.length];

      for (int i = 0; i != keyEnc.length; i++) {
        keyBytes[i] = keyEnc[keyEnc.length - 1 - i]; // was little endian
      }

      this.y = new BigInteger(1, keyBytes);
    } catch (IOException e) {
      throw new IllegalArgumentException("invalid info structure in GOST3410 public key");
    }

    this.gost3410Spec = GOST3410ParameterSpec.fromPublicKeyAlg(params);
  }
Ejemplo n.º 13
0
 public static void checkOrCreateKeyStore(
     final String file, final String password, final String domainName)
     throws IllegalArgumentException, OperatorCreationException {
   final String hostname;
   if ("0.0.0.0".equals(domainName)) {
     hostname = "localhost";
   } else {
     hostname = domainName;
   }
   try {
     KeyStore ks = KeyStore.getInstance("JKS");
     File keyStoreFile = new File(file);
     if (!keyStoreFile.exists()) {
       keyStoreFile.createNewFile();
       ks.load(null, null);
       KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
       keyPairGenerator.initialize(1024);
       KeyPair KPair = keyPairGenerator.generateKeyPair();
       X509v3CertificateBuilder v3CertGen =
           new X509v3CertificateBuilder(
               new X500Name("CN=" + hostname + ", OU=None, O=None L=None, C=None"),
               BigInteger.valueOf(System.currentTimeMillis()),
               new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30),
               new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 365 * 10)),
               new X500Name("CN=" + hostname + ", OU=None, O=None L=None, C=None"),
               SubjectPublicKeyInfo.getInstance(KPair.getPublic().getEncoded()));
       AlgorithmIdentifier sigAlgId =
           new DefaultSignatureAlgorithmIdentifierFinder().find("SHA512withRSA");
       AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
       AsymmetricKeyParameter foo = PrivateKeyFactory.createKey(KPair.getPrivate().getEncoded());
       ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(foo);
       X509CertificateHolder PKCertificateHolder = v3CertGen.build(sigGen);
       X509CertificateStructure eeX509CertificateStructure = PKCertificateHolder.toASN1Structure();
       CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
       X509Certificate cert;
       try (InputStream is1 = new ByteArrayInputStream(eeX509CertificateStructure.getEncoded())) {
         cert = (X509Certificate) cf.generateCertificate(is1);
       }
       ks.setKeyEntry(
           "siesta",
           KPair.getPrivate(),
           password.toCharArray(),
           new java.security.cert.Certificate[] {cert});
       ks.store(new FileOutputStream(file), password.toCharArray());
     }
   } catch (GeneralSecurityException | IOException | IllegalStateException ex) {
     throw new IllegalArgumentException("Error creating keystore, please manually create one", ex);
   }
 }
Ejemplo n.º 14
0
  public CertificationRequestInfo(ASN1Sequence seq) {
    version = (DERInteger) seq.getObjectAt(0);

    subject = X509Name.getInstance(seq.getObjectAt(1));
    subjectPKInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(2));

    //
    // some CertificationRequestInfo objects seem to treat this field
    // as optional.
    //
    if (seq.size() > 3) {
      DERTaggedObject tagobj = (DERTaggedObject) seq.getObjectAt(3);
      attributes = ASN1Set.getInstance(tagobj, false);
    }

    if ((subject == null) || (version == null) || (subjectPKInfo == null)) {
      throw new IllegalArgumentException(
          "Not all mandatory fields set in CertificationRequestInfo generator.");
    }
  }
Ejemplo n.º 15
0
  /** create a public key from the given public key info object. */
  static PublicKey createPublicKeyFromPublicKeyInfo(SubjectPublicKeyInfo info) {
    DERObjectIdentifier algOid = info.getAlgorithmId().getObjectId();

    if (RSAUtil.isRsaOid(algOid)) {
      return new JCERSAPublicKey(info);
    } else if (algOid.equals(PKCSObjectIdentifiers.dhKeyAgreement)) {
      return new JCEDHPublicKey(info);
    } else if (algOid.equals(X9ObjectIdentifiers.dhpublicnumber)) {
      return new JCEDHPublicKey(info);
    }
    // BEGIN android-removed
    // else if (algOid.equals(OIWObjectIdentifiers.elGamalAlgorithm))
    // {
    //     return new JCEElGamalPublicKey(info);
    // }
    // END android-removed
    else if (algOid.equals(X9ObjectIdentifiers.id_dsa)) {
      return new JDKDSAPublicKey(info);
    } else if (algOid.equals(OIWObjectIdentifiers.dsaWithSHA1)) {
      return new JDKDSAPublicKey(info);
    }
    // BEGIN android-removed
    // else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey))
    // {
    //     return new JCEECPublicKey(info);
    // }
    // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94))
    // {
    //     return new JDKGOST3410PublicKey(info);
    // }
    // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_2001))
    // {
    //     return new JCEECPublicKey(info);
    // }
    else {
      throw new RuntimeException("algorithm identifier " + algOid + " in key not recognised");
    }
  }
 /**
  * Create a public key from a SubjectPublicKeyInfo encoding
  *
  * @param keyInfoData the SubjectPublicKeyInfo encoding
  * @return the appropriate key parameter
  * @throws IOException on an error decoding the key
  */
 public static AsymmetricKeyParameter createKey(byte[] keyInfoData) throws IOException {
   return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData)));
 }
 /**
  * Create a public key from a SubjectPublicKeyInfo encoding read from a stream
  *
  * @param inStr the stream to read the SubjectPublicKeyInfo encoding from
  * @return the appropriate key parameter
  * @throws IOException on an error decoding the key
  */
 public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException {
   return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
 }
  /**
   * Create a public key from the passed in SubjectPublicKeyInfo
   *
   * @param keyInfo the SubjectPublicKeyInfo containing the key data
   * @return the appropriate key parameter
   * @throws IOException on an error decoding the key
   */
  public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException {
    AlgorithmIdentifier algId = keyInfo.getAlgorithm();

    if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)
        || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa)) {
      RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey());

      return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());
    } else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber)) {
      DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey());

      BigInteger y = dhPublicKey.getY().getValue();

      DHDomainParameters dhParams = DHDomainParameters.getInstance(algId.getParameters());

      BigInteger p = dhParams.getP().getValue();
      BigInteger g = dhParams.getG().getValue();
      BigInteger q = dhParams.getQ().getValue();

      BigInteger j = null;
      if (dhParams.getJ() != null) {
        j = dhParams.getJ().getValue();
      }

      DHValidationParameters validation = null;
      DHValidationParms dhValidationParms = dhParams.getValidationParms();
      if (dhValidationParms != null) {
        byte[] seed = dhValidationParms.getSeed().getBytes();
        BigInteger pgenCounter = dhValidationParms.getPgenCounter().getValue();

        // TODO Check pgenCounter size?

        validation = new DHValidationParameters(seed, pgenCounter.intValue());
      }

      return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
    } else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement)) {
      DHParameter params = DHParameter.getInstance(algId.getParameters());
      ASN1Integer derY = (ASN1Integer) keyInfo.parsePublicKey();

      BigInteger lVal = params.getL();
      int l = lVal == null ? 0 : lVal.intValue();
      DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);

      return new DHPublicKeyParameters(derY.getValue(), dhParams);
    }
    // BEGIN android-removed
    // else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
    // {
    //     ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
    //     ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
    //
    //     return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
    //         params.getP(), params.getG()));
    // }
    // END android-removed
    else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
        || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1)) {
      ASN1Integer derY = (ASN1Integer) keyInfo.parsePublicKey();
      ASN1Encodable de = algId.getParameters();

      DSAParameters parameters = null;
      if (de != null) {
        DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
        parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
      }

      return new DSAPublicKeyParameters(derY.getValue(), parameters);
    } else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey)) {
      X962Parameters params = X962Parameters.getInstance(algId.getParameters());

      X9ECParameters x9;
      if (params.isNamedCurve()) {
        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) params.getParameters();
        x9 = ECNamedCurveTable.getByOID(oid);
      } else {
        x9 = X9ECParameters.getInstance(params.getParameters());
      }

      ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes());
      X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key);

      // TODO We lose any named parameters here

      ECDomainParameters dParams =
          new ECDomainParameters(x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());

      return new ECPublicKeyParameters(derQ.getPoint(), dParams);
    } else {
      throw new RuntimeException("algorithm identifier in key not recognised");
    }
  }