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