PKCS5S2ParametersGenerator.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)package org.bouncycastle.crypto.generators; 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.crypto.CipherParameters; 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.crypto.Digest; 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.crypto.Mac; 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.crypto.PBEParametersGenerator; 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// BEGIN android-changed 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.crypto.digests.AndroidDigestFactory; 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// END android-changed 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.crypto.macs.HMac; 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.crypto.params.KeyParameter; 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.crypto.params.ParametersWithIV; 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/** 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2. 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This generator uses a SHA-1 HMac as the calculation function. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * <p> 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * The document this implementation is based on can be found at 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html> 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * RSA's PKCS5 Page</a> 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public class PKCS5S2ParametersGenerator 2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) extends PBEParametersGenerator 2409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) private Mac hMac; 26a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /** 28c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * construct a PKCS5 Scheme 2 Parameters generator. 2902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch */ 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) public PKCS5S2ParametersGenerator() 317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // BEGIN android-changed 335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) this(AndroidDigestFactory.getSHA1()); 3402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // END android-changed 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) public PKCS5S2ParametersGenerator(Digest digest) 3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 3909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) hMac = new HMac(digest); 4009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) private void F( 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) byte[] P, 4451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) byte[] S, 4502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch int c, 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) byte[] iBuf, 47926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) byte[] out, 4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int outOff) 4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 5002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch byte[] state = new byte[hMac.getMacSize()]; 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CipherParameters param = new KeyParameter(P); 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch hMac.init(param); 5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (S != null) 5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) hMac.update(S, 0, S.length); 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 60c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) hMac.update(iBuf, 0, iBuf.length); 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci hMac.doFinal(state, 0); 63 64 System.arraycopy(state, 0, out, outOff, state.length); 65 66 if (c == 0) 67 { 68 throw new IllegalArgumentException("iteration count must be at least 1."); 69 } 70 71 for (int count = 1; count < c; count++) 72 { 73 hMac.init(param); 74 hMac.update(state, 0, state.length); 75 hMac.doFinal(state, 0); 76 77 for (int j = 0; j != state.length; j++) 78 { 79 out[outOff + j] ^= state[j]; 80 } 81 } 82 } 83 84 private void intToOctet( 85 byte[] buf, 86 int i) 87 { 88 buf[0] = (byte)(i >>> 24); 89 buf[1] = (byte)(i >>> 16); 90 buf[2] = (byte)(i >>> 8); 91 buf[3] = (byte)i; 92 } 93 94 private byte[] generateDerivedKey( 95 int dkLen) 96 { 97 int hLen = hMac.getMacSize(); 98 int l = (dkLen + hLen - 1) / hLen; 99 byte[] iBuf = new byte[4]; 100 byte[] out = new byte[l * hLen]; 101 102 for (int i = 1; i <= l; i++) 103 { 104 intToOctet(iBuf, i); 105 106 F(password, salt, iterationCount, iBuf, out, (i - 1) * hLen); 107 } 108 109 return out; 110 } 111 112 /** 113 * Generate a key parameter derived from the password, salt, and iteration 114 * count we are currently initialised with. 115 * 116 * @param keySize the size of the key we want (in bits) 117 * @return a KeyParameter object. 118 */ 119 public CipherParameters generateDerivedParameters( 120 int keySize) 121 { 122 keySize = keySize / 8; 123 124 byte[] dKey = generateDerivedKey(keySize); 125 126 return new KeyParameter(dKey, 0, keySize); 127 } 128 129 /** 130 * Generate a key with initialisation vector parameter derived from 131 * the password, salt, and iteration count we are currently initialised 132 * with. 133 * 134 * @param keySize the size of the key we want (in bits) 135 * @param ivSize the size of the iv we want (in bits) 136 * @return a ParametersWithIV object. 137 */ 138 public CipherParameters generateDerivedParameters( 139 int keySize, 140 int ivSize) 141 { 142 keySize = keySize / 8; 143 ivSize = ivSize / 8; 144 145 byte[] dKey = generateDerivedKey(keySize + ivSize); 146 147 return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); 148 } 149 150 /** 151 * Generate a key parameter for use with a MAC derived from the password, 152 * salt, and iteration count we are currently initialised with. 153 * 154 * @param keySize the size of the key we want (in bits) 155 * @return a KeyParameter object. 156 */ 157 public CipherParameters generateDerivedMacParameters( 158 int keySize) 159 { 160 return generateDerivedParameters(keySize); 161 } 162} 163