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