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