public JCEECPrivateKey(
      String algorithm,
      ECPrivateKeyParameters params,
      JCEECPublicKey pubKey,
      org.sandrob.bouncycastle.jce.spec.ECParameterSpec spec) {
    ECDomainParameters dp = params.getParameters();

    this.algorithm = algorithm;
    this.d = params.getD();

    if (spec == null) {
      EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());

      this.ecSpec =
          new ECParameterSpec(
              ellipticCurve,
              new ECPoint(dp.getG().getX().toBigInteger(), dp.getG().getY().toBigInteger()),
              dp.getN(),
              dp.getH().intValue());
    } else {
      EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed());

      this.ecSpec =
          new ECParameterSpec(
              ellipticCurve,
              new ECPoint(spec.getG().getX().toBigInteger(), spec.getG().getY().toBigInteger()),
              spec.getN(),
              spec.getH().intValue());
    }

    publicKey = getPublicKeyDetails(pubKey);
  }
  private void populateFromPrivKeyInfo(PrivateKeyInfo info) {
    X962Parameters params = new X962Parameters((DERObject) info.getAlgorithmId().getParameters());

    if (params.isNamedCurve()) {
      DERObjectIdentifier oid = (DERObjectIdentifier) params.getParameters();
      X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);

      if (ecP == null) // GOST Curve
      {
        ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid);
        EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed());

        ecSpec =
            new ECNamedCurveSpec(
                ECGOST3410NamedCurves.getName(oid),
                ellipticCurve,
                new ECPoint(
                    gParam.getG().getX().toBigInteger(), gParam.getG().getY().toBigInteger()),
                gParam.getN(),
                gParam.getH());
      } else {
        EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());

        ecSpec =
            new ECNamedCurveSpec(
                ECUtil.getCurveName(oid),
                ellipticCurve,
                new ECPoint(ecP.getG().getX().toBigInteger(), ecP.getG().getY().toBigInteger()),
                ecP.getN(),
                ecP.getH());
      }
    } else if (params.isImplicitlyCA()) {
      ecSpec = null;
    } else {
      X9ECParameters ecP = new X9ECParameters((ASN1Sequence) params.getParameters());
      EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());

      this.ecSpec =
          new ECParameterSpec(
              ellipticCurve,
              new ECPoint(ecP.getG().getX().toBigInteger(), ecP.getG().getY().toBigInteger()),
              ecP.getN(),
              ecP.getH().intValue());
    }

    if (info.getPrivateKey() instanceof DERInteger) {
      DERInteger derD = (DERInteger) info.getPrivateKey();

      this.d = derD.getValue();
    } else {
      ECPrivateKeyStructure ec = new ECPrivateKeyStructure((ASN1Sequence) info.getPrivateKey());

      this.d = ec.getKey();
      this.publicKey = ec.getPublicKey();
    }
  }
  /**
   * 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();
  }
  org.sandrob.bouncycastle.jce.spec.ECParameterSpec engineGetSpec() {
    if (ecSpec != null) {
      return EC5Util.convertSpec(ecSpec, withCompression);
    }

    return ProviderUtil.getEcImplicitlyCa();
  }
  public org.sandrob.bouncycastle.jce.spec.ECParameterSpec getParameters() {
    if (ecSpec == null) {
      return null;
    }

    return EC5Util.convertSpec(ecSpec, withCompression);
  }
  public JCEECPrivateKey(
      String algorithm, org.sandrob.bouncycastle.jce.spec.ECPrivateKeySpec spec) {
    this.algorithm = algorithm;
    this.d = spec.getD();

    if (spec.getParams() != null) // can be null if implicitlyCA
    {
      ECCurve curve = spec.getParams().getCurve();
      EllipticCurve ellipticCurve;

      ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed());

      this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams());
    } else {
      this.ecSpec = null;
    }
  }