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