public AlgorithmIdentifier getAlgorithmIdentifier(
      ASN1ObjectIdentifier macOID, AlgorithmParameterSpec paramSpec) {
    if (paramSpec instanceof IvParameterSpec) {
      return new AlgorithmIdentifier(
          macOID, new DEROctetString(((IvParameterSpec) paramSpec).getIV()));
    }

    if (paramSpec instanceof RC2ParameterSpec) {
      RC2ParameterSpec rc2Spec = (RC2ParameterSpec) paramSpec;

      int effKeyBits = ((RC2ParameterSpec) paramSpec).getEffectiveKeyBits();

      if (effKeyBits != -1) {
        int parameterVersion;

        if (effKeyBits < 256) {
          parameterVersion = rc2Table[effKeyBits];
        } else {
          parameterVersion = effKeyBits;
        }

        return new AlgorithmIdentifier(
            macOID, new RC2CBCParameter(parameterVersion, rc2Spec.getIV()));
      }

      return new AlgorithmIdentifier(macOID, new RC2CBCParameter(rc2Spec.getIV()));
    }

    throw new IllegalStateException("unknown parameter spec: " + paramSpec);
  }
  private static byte[] testParams(AlgorithmParameters rc2Params, RC2ParameterSpec rc2Spec)
      throws Exception {

    // test getParameterSpec returns object equal to input
    rc2Params.init(rc2Spec);
    RC2ParameterSpec rc2OtherSpec =
        (RC2ParameterSpec) rc2Params.getParameterSpec(RC2ParameterSpec.class);
    if (!rc2Spec.equals(rc2OtherSpec)) {
      throw new Exception("AlgorithmParameterSpecs should be equal");
    }

    // test RC2ParameterSpec with RC2 Cipher
    Cipher rc2Cipher = Cipher.getInstance("RC2/CBC/PKCS5PADDING", "SunJCE");
    rc2Cipher.init(
        Cipher.ENCRYPT_MODE, new SecretKeySpec("secret".getBytes("ASCII"), "RC2"), rc2Spec);

    // get IV
    byte[] iv = rc2Cipher.getIV();
    if (!Arrays.equals(iv, rc2Spec.getIV())) {
      throw new Exception("ivs should be equal");
    }

    // test encoding and decoding
    byte[] encoded = rc2Params.getEncoded();
    AlgorithmParameters params = AlgorithmParameters.getInstance("RC2");
    params.init(encoded);

    // test RC2 AlgorithmParameters with RC2 Cipher
    rc2Cipher.init(
        Cipher.ENCRYPT_MODE, new SecretKeySpec("secret".getBytes("ASCII"), "RC2"), params);

    // get IV
    iv = rc2Cipher.getIV();
    if (!Arrays.equals(iv, rc2Spec.getIV())) {
      throw new Exception("ivs should be equal");
    }
    return encoded;
  }
  protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)
      throws InvalidKeyException, InvalidAlgorithmParameterException {
    CipherParameters param;

    //
    // a note on iv's - if ivLength is zero the IV gets ignored (we don't use it).
    //
    if (key instanceof JCEPBEKey) {
      param =
          Util.makePBEParameters(
              (JCEPBEKey) key,
              params,
              pbeType,
              pbeHash,
              cipher.getUnderlyingCipher().getAlgorithmName(),
              pbeKeySize,
              pbeIvSize);

      if (pbeIvSize != 0) {
        ivParam = (ParametersWithIV) param;
      }
    } else if (params == null) {
      param = new KeyParameter(key.getEncoded());
    } else if (params instanceof IvParameterSpec) {
      if (ivLength != 0) {
        param =
            new ParametersWithIV(
                new KeyParameter(key.getEncoded()), ((IvParameterSpec) params).getIV());
        ivParam = (ParametersWithIV) param;
      } else {
        param = new KeyParameter(key.getEncoded());
      }
    } else if (params instanceof RC2ParameterSpec) {
      RC2ParameterSpec rc2Param = (RC2ParameterSpec) params;

      param =
          new RC2Parameters(key.getEncoded(), ((RC2ParameterSpec) params).getEffectiveKeyBits());

      if (rc2Param.getIV() != null && ivLength != 0) {
        param = new ParametersWithIV(param, rc2Param.getIV());
        ivParam = (ParametersWithIV) param;
      }
    } else if (params instanceof RC5ParameterSpec) {
      RC5ParameterSpec rc5Param = (RC5ParameterSpec) params;

      param = new RC5Parameters(key.getEncoded(), ((RC5ParameterSpec) params).getRounds());
      if (rc5Param.getWordSize() != 32) {
        throw new IllegalArgumentException("can only accept RC5 word size 32 (at the moment...)");
      }
      if ((rc5Param.getIV() != null) && (ivLength != 0)) {
        param = new ParametersWithIV(param, rc5Param.getIV());
        ivParam = (ParametersWithIV) param;
      }
    } else {
      throw new InvalidAlgorithmParameterException("unknown parameter type.");
    }

    if ((ivLength != 0) && !(param instanceof ParametersWithIV)) {
      if (random == null) {
        random = new SecureRandom();
      }

      if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE)) {
        byte[] iv = new byte[ivLength];

        random.nextBytes(iv);
        param = new ParametersWithIV(param, iv);
        ivParam = (ParametersWithIV) param;
      } else {
        throw new InvalidAlgorithmParameterException("no IV set when one expected");
      }
    }

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