protected int engineGetKeySize(Key key) {
    if (!(key instanceof IESKey)) {
      throw new IllegalArgumentException("must be passed IE key");
    }

    IESKey ieKey = (IESKey) key;

    if (ieKey.getPrivate() instanceof DHPrivateKey) {
      DHPrivateKey k = (DHPrivateKey) ieKey.getPrivate();

      return k.getX().bitLength();
    } else if (ieKey.getPrivate() instanceof ECPrivateKey) {
      ECPrivateKey k = (ECPrivateKey) ieKey.getPrivate();

      return k.getD().bitLength();
    }

    throw new IllegalArgumentException("not an IE key!");
  }
  protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)
      throws InvalidKeyException, InvalidAlgorithmParameterException {
    if (!(key instanceof IESKey)) {
      throw new InvalidKeyException("must be passed IES key");
    }

    if (params == null && (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE)) {
      //
      // if nothing is specified we set up for a 128 bit mac, with
      // 128 bit derivation vectors.
      //
      byte[] d = new byte[16];
      byte[] e = new byte[16];

      if (random == null) {
        random = new SecureRandom();
      }

      random.nextBytes(d);
      random.nextBytes(e);

      params = new IESParameterSpec(d, e, 128);
    } else if (!(params instanceof IESParameterSpec)) {
      throw new InvalidAlgorithmParameterException("must be passed IES parameters");
    }

    IESKey ieKey = (IESKey) key;

    CipherParameters pubKey;
    CipherParameters privKey;

    if (ieKey.getPublic() instanceof ECPublicKey) {
      pubKey = ECUtil.generatePublicKeyParameter(ieKey.getPublic());
      privKey = ECUtil.generatePrivateKeyParameter(ieKey.getPrivate());
    } else {
      pubKey = DHUtil.generatePublicKeyParameter(ieKey.getPublic());
      privKey = DHUtil.generatePrivateKeyParameter(ieKey.getPrivate());
    }

    this.engineParams = (IESParameterSpec) params;

    IESParameters p =
        new IESParameters(
            engineParams.getDerivationV(),
            engineParams.getEncodingV(),
            engineParams.getMacKeySize());

    this.state = opmode;

    buffer.reset();

    switch (opmode) {
      case Cipher.ENCRYPT_MODE:
      case Cipher.WRAP_MODE:
        cipher.init(true, privKey, pubKey, p);
        break;
      case Cipher.DECRYPT_MODE:
      case Cipher.UNWRAP_MODE:
        cipher.init(false, privKey, pubKey, p);
        break;
      default:
        System.out.println("eeek!");
    }
  }