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