/**
   * Generates a PBE key/IV pair from command line options.
   *
   * @param alg Symmetric algorithm for which a compatible key should be generated.
   * @param line Parsed command line arguments container.
   * @return Secret key from password.
   * @throws Exception On key generation errors.
   */
  protected KeyWithIV genPbeKeyWithIV(final SymmetricAlgorithm alg, final CommandLine line)
      throws Exception {
    if (!line.hasOption(OPT_SALT)) {
      throw new IllegalArgumentException("Salt is required for PBE key generation.");
    }
    if (!line.hasOption(OPT_KEYSIZE)) {
      throw new IllegalArgumentException("Key size is required for PBE key generation.");
    }

    KeyWithIV keyWithIV = null;
    DigestAlgorithm digest = null;
    if (line.hasOption(OPT_DIGEST)) {
      digest = DigestAlgorithm.newInstance(line.getOptionValue(OPT_DIGEST));
    }

    String pbeMode = null;
    if (line.hasOption(OPT_PBEMODE)) {
      pbeMode = line.getOptionValue(OPT_PBEMODE).toLowerCase();
    }

    final int keySize = Integer.parseInt(line.getOptionValue(OPT_KEYSIZE));
    int ivSize = 0;
    if (!line.hasOption(OPT_IV)) {
      // Generate an IV from the password if none specified
      ivSize = alg.getBlockSize() * BITS_IN_BYTE;
    }

    final PbeKeyGenerator keyGen = new PbeKeyGenerator(alg);
    final char[] pass = line.getOptionValue(OPT_PBE).toCharArray();
    final byte[] salt = hexConv.toBytes(line.getOptionValue(OPT_SALT));
    if ("pkcs12".equals(pbeMode)) {
      if (digest == null) {
        throw new IllegalArgumentException("pkcs12 requires a digest algorithm");
      }
      System.err.println("Generating PKCS#12 PBE key.");
      keyWithIV = keyGen.generatePkcs12(pass, keySize, ivSize, digest, salt);
    } else if ("pkcs5s1".equals(pbeMode)) {
      if (digest == null) {
        throw new IllegalArgumentException("pkcs5s1 requires a digest algorithm");
      }
      System.err.println("Generating PKCS#5 v1 PBE key.");
      keyWithIV = keyGen.generatePkcs5v1(pass, keySize, ivSize, digest, salt);
    } else if ("openssl".equals(pbeMode)) {
      System.err.println("Generating OpenSSL PBE key.");
      keyWithIV = keyGen.generateOpenssl(pass, keySize, ivSize, salt);
    } else {
      // Default is pkcs5s2
      System.err.println("Generating PKCS#5 v2 PBE key.");
      keyWithIV = keyGen.generatePkcs5v2(pass, keySize, ivSize, salt);
    }
    System.err.println("Key: " + hexConv.fromBytes(keyWithIV.getKey().getEncoded()));
    if (keyWithIV.getIV().length > 0) {
      System.err.println("IV: " + hexConv.fromBytes(keyWithIV.getIV()));
    }
    return keyWithIV;
  }
 /**
  * Creates a new instance with the given parameters.
  *
  * @param alg Symmetric algorithm used for encryption/decryption.
  * @param digest Key generation function digest.
  * @param params Key generation function salt and iteration count.
  */
 public PBES1EncryptionScheme(
     final SymmetricAlgorithm alg, final DigestAlgorithm digest, final PBEParameter params) {
   boolean valid = false;
   for (PBES1Algorithm a : PBES1Algorithm.values()) {
     if (a.getDigest().getAlgorithm().equals(digest.getAlgorithm())
         && a.getSpec().getName().equals(alg.getAlgorithm())
         && a.getSpec().getMode().equals(alg.getMode())
         && a.getSpec().getPadding().equals(alg.getPadding())) {
       valid = true;
       break;
     }
   }
   if (!valid) {
     throw new IllegalArgumentException("Invalid digest/cipher combination.");
   }
   setCipher(alg);
   generator = new PBKDF1KeyGenerator(digest, params.getSalt(), params.getIterationCount());
 }