@Override
  public boolean equals(Object o) {
    if (o == this) {
      return true;
    }

    if (o instanceof OpenSSLECPublicKey) {
      OpenSSLECPublicKey other = (OpenSSLECPublicKey) o;
      return key.equals(other.key);
    }

    if (!(o instanceof ECPublicKey)) {
      return false;
    }

    final ECPublicKey other = (ECPublicKey) o;
    if (!getPublicKey().equals(other.getW())) {
      return false;
    }

    final ECParameterSpec spec = getParams();
    final ECParameterSpec otherSpec = other.getParams();

    return spec.getCurve().equals(otherSpec.getCurve())
        && spec.getGenerator().equals(otherSpec.getGenerator())
        && spec.getOrder().equals(otherSpec.getOrder())
        && spec.getCofactor() == otherSpec.getCofactor();
  }
  /**
   * Return a PKCS8 representation of the key. The sequence returned represents a full
   * PrivateKeyInfo object.
   *
   * @return a PKCS8 representation of the key.
   */
  public byte[] getEncoded() {
    X962Parameters params;

    if (ecSpec instanceof ECNamedCurveSpec) {
      DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec) ecSpec).getName());
      if (curveOid == null) // guess it's the OID
      {
        curveOid = new DERObjectIdentifier(((ECNamedCurveSpec) ecSpec).getName());
      }
      params = new X962Parameters(curveOid);
    } else if (ecSpec == null) {
      params = new X962Parameters(DERNull.INSTANCE);
    } else {
      ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());

      X9ECParameters ecP =
          new X9ECParameters(
              curve,
              EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
              ecSpec.getOrder(),
              BigInteger.valueOf(ecSpec.getCofactor()),
              ecSpec.getCurve().getSeed());

      params = new X962Parameters(ecP);
    }

    PrivateKeyInfo info;
    ECPrivateKeyStructure keyStructure;

    if (publicKey != null) {
      keyStructure = new ECPrivateKeyStructure(this.getS(), publicKey, params);
    } else {
      keyStructure = new ECPrivateKeyStructure(this.getS(), params);
    }

    if (algorithm.equals("ECGOST3410")) {
      info =
          new PrivateKeyInfo(
              new AlgorithmIdentifier(
                  CryptoProObjectIdentifiers.gostR3410_2001, params.getDERObject()),
              keyStructure.getDERObject());
    } else {

      info =
          new PrivateKeyInfo(
              new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.getDERObject()),
              keyStructure.getDERObject());
    }

    return info.getDEREncoded();
  }
  public PublicKeyDataObject getPublicKeyDataObject(
      ASN1ObjectIdentifier usage, PublicKey publicKey) {
    if (publicKey instanceof java.security.interfaces.RSAPublicKey) {
      java.security.interfaces.RSAPublicKey pubKey =
          (java.security.interfaces.RSAPublicKey) publicKey;

      return new RSAPublicKey(usage, pubKey.getModulus(), pubKey.getPublicExponent());
    } else {
      ECPublicKey pubKey = (ECPublicKey) publicKey;
      java.security.spec.ECParameterSpec params = pubKey.getParams();

      return new ECDSAPublicKey(
          usage,
          ((ECFieldFp) params.getCurve().getField()).getP(),
          params.getCurve().getA(),
          params.getCurve().getB(),
          convertPoint(convertCurve(params.getCurve()), params.getGenerator()).getEncoded(),
          params.getOrder(),
          convertPoint(convertCurve(params.getCurve()), pubKey.getW()).getEncoded(),
          params.getCofactor());
    }
  }
  public void initialize(AlgorithmParameterSpec params, SecureRandom random)
      throws InvalidAlgorithmParameterException {
    if (params instanceof ECParameterSpec) {
      ECParameterSpec p = (ECParameterSpec) params;
      this.ecParams = params;

      param =
          new ECKeyGenerationParameters(
              new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random);

      engine.init(param);
      initialised = true;
    } else if (params instanceof java.security.spec.ECParameterSpec) {
      java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec) params;
      this.ecParams = params;

      ECCurve curve = EC5Util.convertCurve(p.getCurve());
      ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false);

      param =
          new ECKeyGenerationParameters(
              new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())),
              random);

      engine.init(param);
      initialised = true;
    } else if (params instanceof ECGenParameterSpec
        || params instanceof ECNamedCurveGenParameterSpec) {
      String curveName;

      if (params instanceof ECGenParameterSpec) {
        curveName = ((ECGenParameterSpec) params).getName();
      } else {
        curveName = ((ECNamedCurveGenParameterSpec) params).getName();
      }

      ECDomainParameters ecP = ECGOST3410NamedCurves.getByName(curveName);
      if (ecP == null) {
        throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
      }

      this.ecParams =
          new ECNamedCurveSpec(
              curveName, ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());

      java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec) ecParams;

      ECCurve curve = EC5Util.convertCurve(p.getCurve());
      ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false);

      param =
          new ECKeyGenerationParameters(
              new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())),
              random);

      engine.init(param);
      initialised = true;
    } else if (params == null && BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa() != null) {
      ECParameterSpec p = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
      this.ecParams = params;

      param =
          new ECKeyGenerationParameters(
              new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random);

      engine.init(param);
      initialised = true;
    } else if (params == null && BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa() == null) {
      throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set");
    } else {
      throw new InvalidAlgorithmParameterException(
          "parameter object not a ECParameterSpec: " + params.getClass().getName());
    }
  }