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