1 package org.bouncycastle.crypto.generators; 2 3 import org.bouncycastle.crypto.CipherParameters; 4 import org.bouncycastle.crypto.Mac; 5 import org.bouncycastle.crypto.PBEParametersGenerator; 6 import org.bouncycastle.crypto.digests.SHA1Digest; 7 import org.bouncycastle.crypto.macs.HMac; 8 import org.bouncycastle.crypto.params.KeyParameter; 9 import org.bouncycastle.crypto.params.ParametersWithIV; 10 11 /** 12 * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2. 13 * This generator uses a SHA-1 HMac as the calculation function. 14 * <p> 15 * The document this implementation is based on can be found at 16 * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html> 17 * RSA's PKCS5 Page</a> 18 */ 19 public class PKCS5S2ParametersGenerator 20 extends PBEParametersGenerator 21 { 22 private Mac hMac = new HMac(new SHA1Digest()); 23 24 /** 25 * construct a PKCS5 Scheme 2 Parameters generator. 26 */ 27 public PKCS5S2ParametersGenerator() 28 { 29 } 30 31 private void F( 32 byte[] P, 33 byte[] S, 34 int c, 35 byte[] iBuf, 36 byte[] out, 37 int outOff) 38 { 39 byte[] state = new byte[hMac.getMacSize()]; 40 CipherParameters param = new KeyParameter(P); 41 42 hMac.init(param); 43 44 if (S != null) 45 { 46 hMac.update(S, 0, S.length); 47 } 48 49 hMac.update(iBuf, 0, iBuf.length); 50 51 hMac.doFinal(state, 0); 52 53 System.arraycopy(state, 0, out, outOff, state.length); 54 55 if (c == 0) 56 { 57 throw new IllegalArgumentException("iteration count must be at least 1."); 58 } 59 60 for (int count = 1; count < c; count++) 61 { 62 hMac.init(param); 63 hMac.update(state, 0, state.length); 64 hMac.doFinal(state, 0); 65 66 for (int j = 0; j != state.length; j++) 67 { 68 out[outOff + j] ^= state[j]; 69 } 70 } 71 } 72 73 private void intToOctet( 74 byte[] buf, 75 int i) 76 { 77 buf[0] = (byte)(i >>> 24); 78 buf[1] = (byte)(i >>> 16); 79 buf[2] = (byte)(i >>> 8); 80 buf[3] = (byte)i; 81 } 82 83 private byte[] generateDerivedKey( 84 int dkLen) 85 { 86 int hLen = hMac.getMacSize(); 87 int l = (dkLen + hLen - 1) / hLen; 88 byte[] iBuf = new byte[4]; 89 byte[] out = new byte[l * hLen]; 90 91 for (int i = 1; i <= l; i++) 92 { 93 intToOctet(iBuf, i); 94 95 F(password, salt, iterationCount, iBuf, out, (i - 1) * hLen); 96 } 97 98 return out; 99 } 100 101 /** 102 * Generate a key parameter derived from the password, salt, and iteration 103 * count we are currently initialised with. 104 * 105 * @param keySize the size of the key we want (in bits) 106 * @return a KeyParameter object. 107 */ 108 public CipherParameters generateDerivedParameters( 109 int keySize) 110 { 111 keySize = keySize / 8; 112 113 byte[] dKey = generateDerivedKey(keySize); 114 115 return new KeyParameter(dKey, 0, keySize); 116 } 117 118 /** 119 * Generate a key with initialisation vector parameter derived from 120 * the password, salt, and iteration count we are currently initialised 121 * with. 122 * 123 * @param keySize the size of the key we want (in bits) 124 * @param ivSize the size of the iv we want (in bits) 125 * @return a ParametersWithIV object. 126 */ 127 public CipherParameters generateDerivedParameters( 128 int keySize, 129 int ivSize) 130 { 131 keySize = keySize / 8; 132 ivSize = ivSize / 8; 133 134 byte[] dKey = generateDerivedKey(keySize + ivSize); 135 136 return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); 137 } 138 139 /** 140 * Generate a key parameter for use with a MAC derived from the password, 141 * salt, and iteration count we are currently initialised with. 142 * 143 * @param keySize the size of the key we want (in bits) 144 * @return a KeyParameter object. 145 */ 146 public CipherParameters generateDerivedMacParameters( 147 int keySize) 148 { 149 return generateDerivedParameters(keySize); 150 } 151 } 152