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