1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.generators; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.CipherParameters; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.Digest; 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.PBEParametersGenerator; 6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.KeyParameter; 7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.ParametersWithIV; 8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 1. 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Note this generator is limited to the size of the hash produced by the 12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * digest used to drive it. 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p> 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * The document this implementation is based on can be found at 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html> 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * RSA's PKCS5 Page</a> 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class PKCS5S1ParametersGenerator 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam extends PBEParametersGenerator 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private Digest digest; 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Construct a PKCS 5 Scheme 1 Parameters generator. 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param digest the digest to be used as the source of derived keys. 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public PKCS5S1ParametersGenerator( 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam Digest digest) 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.digest = digest; 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * the derived key function, the ith hash of the password and the salt. 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private byte[] generateDerivedKey() 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] digestBytes = new byte[digest.getDigestSize()]; 40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(password, 0, password.length); 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(salt, 0, salt.length); 43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.doFinal(digestBytes, 0); 45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = 1; i < iterationCount; i++) 46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(digestBytes, 0, digestBytes.length); 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.doFinal(digestBytes, 0); 49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return digestBytes; 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Generate a key parameter derived from the password, salt, and iteration 56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * count we are currently initialised with. 57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param keySize the size of the key we want (in bits) 59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return a KeyParameter object. 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalArgumentException if the key length larger than the base hash size. 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public CipherParameters generateDerivedParameters( 63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int keySize) 64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam keySize = keySize / 8; 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (keySize > digest.getDigestSize()) 68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalArgumentException( 70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam "Can't generate a derived key " + keySize + " bytes long."); 71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] dKey = generateDerivedKey(); 74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return new KeyParameter(dKey, 0, keySize); 76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Generate a key with initialisation vector parameter derived from 80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * the password, salt, and iteration count we are currently initialised 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * with. 82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param keySize the size of the key we want (in bits) 84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param ivSize the size of the iv we want (in bits) 85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return a ParametersWithIV object. 86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size. 87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public CipherParameters generateDerivedParameters( 89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int keySize, 90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int ivSize) 91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam keySize = keySize / 8; 93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam ivSize = ivSize / 8; 94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if ((keySize + ivSize) > digest.getDigestSize()) 96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalArgumentException( 98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam "Can't generate a derived key " + (keySize + ivSize) + " bytes long."); 99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] dKey = generateDerivedKey(); 102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); 104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Generate a key parameter for use with a MAC derived from the password, 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * salt, and iteration count we are currently initialised with. 109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param keySize the size of the key we want (in bits) 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return a KeyParameter object. 112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalArgumentException if the key length larger than the base hash size. 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public CipherParameters generateDerivedMacParameters( 115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int keySize) 116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return generateDerivedParameters(keySize); 118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 120