/**
   * 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;
  }
 /**
  * Initialize the given symmetric algorithm in preparation for an encryption or decryption
  * operation.
  *
  * @param alg Algorith to initialize.
  * @param line Parsed command line arguments container.
  * @throws Exception On errors.
  */
 protected void initAlgorithm(final SymmetricAlgorithm alg, final CommandLine line)
     throws Exception {
   if (line.hasOption(OPT_KEY)) {
     alg.setKey(readKey(line));
     if (line.hasOption(OPT_IV)) {
       alg.setIV(hexConv.toBytes(line.getOptionValue(OPT_IV)));
     }
   } else if (line.hasOption(OPT_PBE)) {
     final KeyWithIV keyWithIV = genPbeKeyWithIV(alg, line);
     alg.setKey(keyWithIV.getKey());
     if (line.hasOption(OPT_IV)) {
       alg.setIV(hexConv.toBytes(line.getOptionValue(OPT_IV)));
     } else if (keyWithIV.getIV().length > 0) {
       alg.setIV(keyWithIV.getIV());
     }
   } else {
     throw new IllegalArgumentException(
         "Either -key or -pbe is required for encryption or decryption.");
   }
 }