1 package org.bouncycastle.crypto.generators; 2 3 import org.bouncycastle.crypto.CipherParameters; 4 import org.bouncycastle.crypto.Digest; 5 import org.bouncycastle.crypto.PBEParametersGenerator; 6 import org.bouncycastle.crypto.params.KeyParameter; 7 import org.bouncycastle.crypto.params.ParametersWithIV; 8 9 /** 10 * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 1. 11 * Note this generator is limited to the size of the hash produced by the 12 * digest used to drive it. 13 * <p> 14 * The document this implementation is based on can be found at 15 * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html> 16 * RSA's PKCS5 Page</a> 17 */ 18 public class PKCS5S1ParametersGenerator 19 extends PBEParametersGenerator 20 { 21 private Digest digest; 22 23 /** 24 * Construct a PKCS 5 Scheme 1 Parameters generator. 25 * 26 * @param digest the digest to be used as the source of derived keys. 27 */ PKCS5S1ParametersGenerator( Digest digest)28 public PKCS5S1ParametersGenerator( 29 Digest digest) 30 { 31 this.digest = digest; 32 } 33 34 /** 35 * the derived key function, the ith hash of the password and the salt. 36 */ generateDerivedKey()37 private byte[] generateDerivedKey() 38 { 39 byte[] digestBytes = new byte[digest.getDigestSize()]; 40 41 digest.update(password, 0, password.length); 42 digest.update(salt, 0, salt.length); 43 44 digest.doFinal(digestBytes, 0); 45 for (int i = 1; i < iterationCount; i++) 46 { 47 digest.update(digestBytes, 0, digestBytes.length); 48 digest.doFinal(digestBytes, 0); 49 } 50 51 return digestBytes; 52 } 53 54 /** 55 * Generate a key parameter derived from the password, salt, and iteration 56 * count we are currently initialised with. 57 * 58 * @param keySize the size of the key we want (in bits) 59 * @return a KeyParameter object. 60 * @exception IllegalArgumentException if the key length larger than the base hash size. 61 */ generateDerivedParameters( int keySize)62 public CipherParameters generateDerivedParameters( 63 int keySize) 64 { 65 keySize = keySize / 8; 66 67 if (keySize > digest.getDigestSize()) 68 { 69 throw new IllegalArgumentException( 70 "Can't generate a derived key " + keySize + " bytes long."); 71 } 72 73 byte[] dKey = generateDerivedKey(); 74 75 return new KeyParameter(dKey, 0, keySize); 76 } 77 78 /** 79 * Generate a key with initialisation vector parameter derived from 80 * the password, salt, and iteration count we are currently initialised 81 * with. 82 * 83 * @param keySize the size of the key we want (in bits) 84 * @param ivSize the size of the iv we want (in bits) 85 * @return a ParametersWithIV object. 86 * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size. 87 */ generateDerivedParameters( int keySize, int ivSize)88 public CipherParameters generateDerivedParameters( 89 int keySize, 90 int ivSize) 91 { 92 keySize = keySize / 8; 93 ivSize = ivSize / 8; 94 95 if ((keySize + ivSize) > digest.getDigestSize()) 96 { 97 throw new IllegalArgumentException( 98 "Can't generate a derived key " + (keySize + ivSize) + " bytes long."); 99 } 100 101 byte[] dKey = generateDerivedKey(); 102 103 return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); 104 } 105 106 /** 107 * Generate a key parameter for use with a MAC derived from the password, 108 * salt, and iteration count we are currently initialised with. 109 * 110 * @param keySize the size of the key we want (in bits) 111 * @return a KeyParameter object. 112 * @exception IllegalArgumentException if the key length larger than the base hash size. 113 */ generateDerivedMacParameters( int keySize)114 public CipherParameters generateDerivedMacParameters( 115 int keySize) 116 { 117 return generateDerivedParameters(keySize); 118 } 119 } 120