All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.vt.middleware.crypt.PbeKeyGenerator Maven / Gradle / Ivy

/*
  $Id$

  Copyright (C) 2007-2010 Virginia Tech.
  All rights reserved.

  SEE LICENSE FOR MORE INFORMATION

  Author:  Middleware Services
  Email:   [email protected]
  Version: $Revision$
  Updated: $Date$
*/
package edu.vt.middleware.crypt;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import edu.vt.middleware.crypt.digest.DigestAlgorithm;
import edu.vt.middleware.crypt.symmetric.SymmetricAlgorithm;
import org.bouncycastle.crypto.PBEParametersGenerator;
import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

/**
 * Generates secret keys from passwords/phrases in support of password-based
 * encryption (PBE).
 *
 * @author  Middleware Services
 * @version  $Revision: 3 $
 */
public class PbeKeyGenerator
{

  /**
   * Default number of applications of mixing function during key generation.
   */
  private static final int DEFAULT_ITERATIONS = 1024;

  /** Number of bits in byte. */
  private static final int BITS_IN_BYTE = 8;

  /** Symmetric cipher algorithm for which this generator can generate keys. */
  private SymmetricAlgorithm symmetricAlg;

  /** Number of iterations "mixing" function is to be applied. */
  private int iterations = DEFAULT_ITERATIONS;


  /**
   * Creates a key generator that can generate PBE keys for use with the given
   * symmetric cipher algorithm.
   *
   * @param  algorithm  Symmetric cipher algorithm.
   */
  public PbeKeyGenerator(final SymmetricAlgorithm algorithm)
  {
    symmetricAlg = algorithm;
  }


  /**
   * Sets the number of iterations the mixing function is applied during key
   * generations.
   *
   * @param  n  Number of applications of mixing function.
   */
  public void setIterations(final int n)
  {
    iterations = n;
  }


  /**
   * Generate a key from a text password using the PKCS#12 method described at
   * http://www.rsa.com/rsalabs/node.asp?id=2138.
   *
   * @param  password  Raw material used for key generation.
   * @param  keyBitLength  Size of generated key in bits.
   * @param  digest  Digest algorithm to use during key generation.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key based on password.
   */
  public SecretKey generatePkcs12(
    final char[] password,
    final int keyBitLength,
    final DigestAlgorithm digest,
    final byte[] salt)
  {
    return
      generate(
        new PKCS12ParametersGenerator(digest.getDigest()),
        PBEParametersGenerator.PKCS12PasswordToBytes(password),
        keyBitLength,
        salt);
  }


  /**
   * Generate a key/IV pair from a text password using the PKCS#12 method
   * described at http://www.rsa.com/rsalabs/node.asp?id=2138.
   *
   * @param  password  Raw material used for key generation.
   * @param  keyBitLength  Size of generated key in bits.
   * @param  ivBitLength  Size of generated IV in bits.
   * @param  digest  Digest algorithm to use during key generation.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key based on password.
   */
  public KeyWithIV generatePkcs12(
    final char[] password,
    final int keyBitLength,
    final int ivBitLength,
    final DigestAlgorithm digest,
    final byte[] salt)
  {
    return
      generate(
        new PKCS12ParametersGenerator(digest.getDigest()),
        PBEParametersGenerator.PKCS12PasswordToBytes(password),
        keyBitLength,
        ivBitLength,
        salt);
  }


  /**
   * Generate a key from a text password using the PKCS#5 version 1 method
   * described at http://www.rsa.com/rsalabs/node.asp?id=2127.
   *
   * @param  password  Raw material used for key generation.
   * @param  keyBitLength  Size of generated key in bits.
   * @param  digest  Digest algorithm to use during key generation.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key based on password.
   */
  public SecretKey generatePkcs5v1(
    final char[] password,
    final int keyBitLength,
    final DigestAlgorithm digest,
    final byte[] salt)
  {
    final int minSize = keyBitLength / BITS_IN_BYTE;
    if (digest.getDigest().getDigestSize() < minSize) {
      throw new IllegalArgumentException(
        "Digest is too small for chosen key size. " +
        "Use a digest whose size is at least " + minSize + " bytes.");
    }
    return
      generate(
        new PKCS5S1ParametersGenerator(digest.getDigest()),
        PBEParametersGenerator.PKCS5PasswordToBytes(password),
        keyBitLength,
        salt);
  }


  /**
   * Generate a key/IV pair from a text password using the PKCS#5 version 1
   * method described at http://www.rsa.com/rsalabs/node.asp?id=2127.
   *
   * @param  password  Raw material used for key generation.
   * @param  keyBitLength  Size of generated key in bits.
   * @param  ivBitLength  Size of generated IV in bits.
   * @param  digest  Digest algorithm to use during key generation.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key based on password.
   */
  public KeyWithIV generatePkcs5v1(
    final char[] password,
    final int keyBitLength,
    final int ivBitLength,
    final DigestAlgorithm digest,
    final byte[] salt)
  {
    final int minSize = (keyBitLength + ivBitLength) / BITS_IN_BYTE;
    if (digest.getDigest().getDigestSize() < minSize) {
      throw new IllegalArgumentException(
        "Digest is too small for chosen key + IV size. " +
        "Use a digest whose size is at least " + minSize + " bytes.");
    }
    return
      generate(
        new PKCS5S1ParametersGenerator(digest.getDigest()),
        PBEParametersGenerator.PKCS5PasswordToBytes(password),
        keyBitLength,
        ivBitLength,
        salt);
  }


  /**
   * Generate a key from a text password using the PKCS#5 version 2.0 method
   * described at http://www.rsa.com/rsalabs/node.asp?id=2127. A SHA-1 digest is
   * used as the calculation function.
   *
   * @param  password  Raw material used for key generation.
   * @param  keyBitLength  Size of generated key in bits.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key based on password.
   */
  public SecretKey generatePkcs5v2(
    final char[] password,
    final int keyBitLength,
    final byte[] salt)
  {
    return
      generate(
        new PKCS5S2ParametersGenerator(),
        PBEParametersGenerator.PKCS5PasswordToBytes(password),
        keyBitLength,
        salt);
  }


  /**
   * Generate a key/IV pair from a text password using the PKCS#5 version 2.0
   * method described at http://www.rsa.com/rsalabs/node.asp?id=2127. A SHA-1
   * digest is used as the calculation function.
   *
   * @param  password  Raw material used for key generation.
   * @param  keyBitLength  Size of generated key in bits.
   * @param  ivBitLength  Size of generated IV in bits.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key based on password.
   */
  public KeyWithIV generatePkcs5v2(
    final char[] password,
    final int keyBitLength,
    final int ivBitLength,
    final byte[] salt)
  {
    return
      generate(
        new PKCS5S2ParametersGenerator(),
        PBEParametersGenerator.PKCS5PasswordToBytes(password),
        keyBitLength,
        ivBitLength,
        salt);
  }


  /**
   * Generate a key from a text password using a method based ok PKCS#5 version
   * 2 that is consistent with that performed by the openssl enc operation.
   *
   * @param  password  Raw material used for key generation.
   * @param  keyBitLength  Size of generated key in bits.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key based on password.
   */
  public SecretKey generateOpenssl(
    final char[] password,
    final int keyBitLength,
    final byte[] salt)
  {
    return
      generate(
        new OpenSSLPBEParametersGenerator(),
        PBEParametersGenerator.PKCS5PasswordToBytes(password),
        keyBitLength,
        salt);
  }


  /**
   * Generate a key/IV pair from a text password using a strategy compatible
   * with the OpenSSL enc operation. The strategy is based on PKCS#5 version 2,
   * but uses a MD5 hash instead of SHA1 and an iteration count of 1. For
   * compatibility with OpenSSL, the IV size should be equal to key size.
   *
   * @param  password  Raw material used for key generation.
   * @param  keyBitLength  Size of generated key in bits.
   * @param  ivBitLength  Size of generated IV in bits.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key based on password.
   */
  public KeyWithIV generateOpenssl(
    final char[] password,
    final int keyBitLength,
    final int ivBitLength,
    final byte[] salt)
  {
    return
      generate(
        new OpenSSLPBEParametersGenerator(),
        PBEParametersGenerator.PKCS5PasswordToBytes(password),
        keyBitLength,
        ivBitLength,
        salt);
  }


  /**
   * Generate an encryption key from a password using the given parameter
   * generator.
   *
   * @param  generator  Key generator for specific PBE method.
   * @param  password  Password as byte array (depends on PBE method).
   * @param  keyBitLength  Size of generated key in bits.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key derived from password using PBE key generation method.
   */
  private SecretKey generate(
    final PBEParametersGenerator generator,
    final byte[] password,
    final int keyBitLength,
    final byte[] salt)
  {
    generator.init(password, salt, iterations);

    final KeyParameter keyParam = (KeyParameter)
      generator.generateDerivedParameters(keyBitLength);
    final SecretKeySpec spec = new SecretKeySpec(
      keyParam.getKey(),
      symmetricAlg.getAlgorithm());
    return spec;
  }


  /**
   * Generate an encryption key/IV pair from a password using the given
   * parameter generator.
   *
   * @param  generator  Key generator for specific PBE method.
   * @param  password  Password as byte array (depends on PBE method).
   * @param  keyBitLength  Size of generated key in bits.
   * @param  ivBitLength  Size of generated IV in bits.
   * @param  salt  Key initialization data.
   *
   * @return  Secret key derived from password using PBE key generation method.
   */
  private KeyWithIV generate(
    final PBEParametersGenerator generator,
    final byte[] password,
    final int keyBitLength,
    final int ivBitLength,
    final byte[] salt)
  {
    generator.init(password, salt, iterations);

    final ParametersWithIV params = (ParametersWithIV)
      generator.generateDerivedParameters(keyBitLength, ivBitLength);
    final KeyParameter keyParam = (KeyParameter) params.getParameters();
    return
      new KeyWithIV(
        new SecretKeySpec(keyParam.getKey(), symmetricAlg.getAlgorithm()),
        params.getIV());
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy