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.digests.MD5Digest; 7 import org.bouncycastle.crypto.params.KeyParameter; 8 import org.bouncycastle.crypto.params.ParametersWithIV; 9 10 /** 11 * Generator for PBE derived keys and ivs as usd by OpenSSL. 12 * <p> 13 * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an 14 * iteration count of 1. 15 * <p> 16 */ 17 public class OpenSSLPBEParametersGenerator 18 extends PBEParametersGenerator 19 { 20 private Digest digest = new MD5Digest(); 21 22 /** 23 * Construct a OpenSSL Parameters generator. 24 */ 25 public OpenSSLPBEParametersGenerator() 26 { 27 } 28 29 /** 30 * Initialise - note the iteration count for this algorithm is fixed at 1. 31 * 32 * @param password password to use. 33 * @param salt salt to use. 34 */ 35 public void init( 36 byte[] password, 37 byte[] salt) 38 { 39 super.init(password, salt, 1); 40 } 41 42 /** 43 * the derived key function, the ith hash of the password and the salt. 44 */ 45 private byte[] generateDerivedKey( 46 int bytesNeeded) 47 { 48 byte[] buf = new byte[digest.getDigestSize()]; 49 byte[] key = new byte[bytesNeeded]; 50 int offset = 0; 51 52 for (;;) 53 { 54 digest.update(password, 0, password.length); 55 digest.update(salt, 0, salt.length); 56 57 digest.doFinal(buf, 0); 58 59 int len = (bytesNeeded > buf.length) ? buf.length : bytesNeeded; 60 System.arraycopy(buf, 0, key, offset, len); 61 offset += len; 62 63 // check if we need any more 64 bytesNeeded -= len; 65 if (bytesNeeded == 0) 66 { 67 break; 68 } 69 70 // do another round 71 digest.reset(); 72 digest.update(buf, 0, buf.length); 73 } 74 75 return key; 76 } 77 78 /** 79 * Generate a key parameter derived from the password, salt, and iteration 80 * count we are currently initialised with. 81 * 82 * @param keySize the size of the key we want (in bits) 83 * @return a KeyParameter object. 84 * @exception IllegalArgumentException if the key length larger than the base hash size. 85 */ 86 public CipherParameters generateDerivedParameters( 87 int keySize) 88 { 89 keySize = keySize / 8; 90 91 byte[] dKey = generateDerivedKey(keySize); 92 93 return new KeyParameter(dKey, 0, keySize); 94 } 95 96 /** 97 * Generate a key with initialisation vector parameter derived from 98 * the password, salt, and iteration count we are currently initialised 99 * with. 100 * 101 * @param keySize the size of the key we want (in bits) 102 * @param ivSize the size of the iv we want (in bits) 103 * @return a ParametersWithIV object. 104 * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size. 105 */ 106 public CipherParameters generateDerivedParameters( 107 int keySize, 108 int ivSize) 109 { 110 keySize = keySize / 8; 111 ivSize = ivSize / 8; 112 113 byte[] dKey = generateDerivedKey(keySize + ivSize); 114 115 return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); 116 } 117 118 /** 119 * Generate a key parameter for use with a MAC derived from the password, 120 * salt, and iteration count we are currently initialised with. 121 * 122 * @param keySize the size of the key we want (in bits) 123 * @return a KeyParameter object. 124 * @exception IllegalArgumentException if the key length larger than the base hash size. 125 */ 126 public CipherParameters generateDerivedMacParameters( 127 int keySize) 128 { 129 return generateDerivedParameters(keySize); 130 } 131 } 132