PKCS5S2ParametersGenerator.java revision 5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96
14f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.compackage org.bouncycastle.crypto.generators;
292b9cd57673dad9c0ead2956bad0ded4e5ac49f8shannonwoods@chromium.org
34f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport org.bouncycastle.crypto.CipherParameters;
44f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport org.bouncycastle.crypto.Digest;
54f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport org.bouncycastle.crypto.Mac;
64f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport org.bouncycastle.crypto.PBEParametersGenerator;
74f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com// BEGIN android-changed
84f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport org.bouncycastle.crypto.digests.AndroidDigestFactory;
94f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com// END android-changed
104f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport org.bouncycastle.crypto.macs.HMac;
114f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport org.bouncycastle.crypto.params.KeyParameter;
12b35602556fd332fa32620c4ba5e998e781e331a8shannon.woods@transgaming.comimport org.bouncycastle.crypto.params.ParametersWithIV;
1344fa7594bc518b1b004b1deb91d1c2f125df9f68Geoff Lang
14a2ecfcccf1d1a85e6054a7314ce1f9de0648ac7fshannonwoods@chromium.org/**
15b155bbcbacceeee8bed049d26ed0ee62d9bfd208Jamie Madill * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2.
16b155bbcbacceeee8bed049d26ed0ee62d9bfd208Jamie Madill * This generator uses a SHA-1 HMac as the calculation function.
174f26786863c81244acdd5b36738ae25e2c56b312Jamie Madill * <p>
18b155bbcbacceeee8bed049d26ed0ee62d9bfd208Jamie Madill * The document this implementation is based on can be found at
194f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
204f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * RSA's PKCS5 Page</a>
2149ec992d80abe48f86034738e8d14c71de3c0b84shannonwoods@chromium.org */
2249ec992d80abe48f86034738e8d14c71de3c0b84shannonwoods@chromium.orgpublic class PKCS5S2ParametersGenerator
2349ec992d80abe48f86034738e8d14c71de3c0b84shannonwoods@chromium.org    extends PBEParametersGenerator
2449ec992d80abe48f86034738e8d14c71de3c0b84shannonwoods@chromium.org{
2560dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org    private Mac hMac;
2660dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org    private byte[] state;
2760dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org
2860dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org    /**
2960dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org     * construct a PKCS5 Scheme 2 Parameters generator.
3060dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org     */
3160dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org    public PKCS5S2ParametersGenerator()
3260dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org    {
3360dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org        // BEGIN android-changed
3460dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org        this(AndroidDigestFactory.getSHA1());
3560dafe8f061e921a2b22fde9f2eb0e1264048121apatrick@chromium.org        // END android-changed
364f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    }
374f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
384f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    public PKCS5S2ParametersGenerator(Digest digest)
394f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    {
404f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        hMac = new HMac(digest);
414f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        state = new byte[hMac.getMacSize()];
424f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    }
434f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
44e2b2212912010fafc2675485f8ddd67c6b29130ddaniel@transgaming.com    private void F(
454f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        byte[]  S,
464f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        int     c,
474f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        byte[]  iBuf,
4881655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com        byte[]  out,
4981655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com        int     outOff)
5081655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com    {
5181655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com        if (c == 0)
5281655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com        {
5381655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com            throw new IllegalArgumentException("iteration count must be at least 1.");
5481655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com        }
5581655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com
5681655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com        if (S != null)
5781655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com        {
5881655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com            hMac.update(S, 0, S.length);
5981655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com        }
6081655a720e752e0f0107993b6b575c5411f3a01edaniel@transgaming.com
61b155bbcbacceeee8bed049d26ed0ee62d9bfd208Jamie Madill        hMac.update(iBuf, 0, iBuf.length);
62b155bbcbacceeee8bed049d26ed0ee62d9bfd208Jamie Madill        hMac.doFinal(state, 0);
63b155bbcbacceeee8bed049d26ed0ee62d9bfd208Jamie Madill
64b155bbcbacceeee8bed049d26ed0ee62d9bfd208Jamie Madill        System.arraycopy(state, 0, out, outOff, state.length);
65b155bbcbacceeee8bed049d26ed0ee62d9bfd208Jamie Madill
6670656a64851b8014a325dd711297054032e466c1Jamie Madill        for (int count = 1; count < c; count++)
6770656a64851b8014a325dd711297054032e466c1Jamie Madill        {
6870656a64851b8014a325dd711297054032e466c1Jamie Madill            hMac.update(state, 0, state.length);
6970656a64851b8014a325dd711297054032e466c1Jamie Madill            hMac.doFinal(state, 0);
7070656a64851b8014a325dd711297054032e466c1Jamie Madill
7170656a64851b8014a325dd711297054032e466c1Jamie Madill            for (int j = 0; j != state.length; j++)
7270656a64851b8014a325dd711297054032e466c1Jamie Madill            {
7370656a64851b8014a325dd711297054032e466c1Jamie Madill                out[outOff + j] ^= state[j];
7470656a64851b8014a325dd711297054032e466c1Jamie Madill            }
7570656a64851b8014a325dd711297054032e466c1Jamie Madill        }
7670656a64851b8014a325dd711297054032e466c1Jamie Madill    }
7770656a64851b8014a325dd711297054032e466c1Jamie Madill
7870656a64851b8014a325dd711297054032e466c1Jamie Madill    private byte[] generateDerivedKey(
79b31f532d7137039e73d5bbdcc0b54a9883718c58apatrick@chromium.org        int dkLen)
80b31f532d7137039e73d5bbdcc0b54a9883718c58apatrick@chromium.org    {
81b31f532d7137039e73d5bbdcc0b54a9883718c58apatrick@chromium.org        int     hLen = hMac.getMacSize();
8231c4f2354382991a2f199d2584ec17bd3db0ae8dshannon.woods@transgaming.com        int     l = (dkLen + hLen - 1) / hLen;
8331c4f2354382991a2f199d2584ec17bd3db0ae8dshannon.woods@transgaming.com        byte[]  iBuf = new byte[4];
84b31f532d7137039e73d5bbdcc0b54a9883718c58apatrick@chromium.org        byte[]  outBytes = new byte[l * hLen];
85b31f532d7137039e73d5bbdcc0b54a9883718c58apatrick@chromium.org        int     outPos = 0;
864f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
874f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        CipherParameters param = new KeyParameter(password);
88b31f532d7137039e73d5bbdcc0b54a9883718c58apatrick@chromium.org
894f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        hMac.init(param);
904f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
914f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        for (int i = 1; i <= l; i++)
924f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        {
934f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            // Increment the value in 'iBuf'
944f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            int pos = 3;
954f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            while (++iBuf[pos] == 0)
96e2b2212912010fafc2675485f8ddd67c6b29130ddaniel@transgaming.com            {
974f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com                --pos;
984f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            }
994f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
100e2b2212912010fafc2675485f8ddd67c6b29130ddaniel@transgaming.com            F(salt, iterationCount, iBuf, outBytes, outPos);
1014f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            outPos += hLen;
1024f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        }
1034f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
1044f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        return outBytes;
1054f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    }
1064f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
1074f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    /**
1084f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com     * Generate a key parameter derived from the password, salt, and iteration
109b31f532d7137039e73d5bbdcc0b54a9883718c58apatrick@chromium.org     * count we are currently initialised with.
110f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     *
111f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     * @param keySize the size of the key we want (in bits)
112fb8394756ea5940cf41e8276a81d54bacdceb5a6Shannon Woods     * @return a KeyParameter object.
113f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     */
114f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org    public CipherParameters generateDerivedParameters(
115f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org        int keySize)
116f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org    {
117f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org        keySize = keySize / 8;
118f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org
119f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org        byte[]  dKey = generateDerivedKey(keySize);
120f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org
121f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org        return new KeyParameter(dKey, 0, keySize);
122f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org    }
123a2ecfcccf1d1a85e6054a7314ce1f9de0648ac7fshannonwoods@chromium.org
124f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org    /**
125f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     * Generate a key with initialisation vector parameter derived from
126f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     * the password, salt, and iteration count we are currently initialised
127f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     * with.
128f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     *
129f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     * @param keySize the size of the key we want (in bits)
130f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     * @param ivSize the size of the iv we want (in bits)
131f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     * @return a ParametersWithIV object.
132f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org     */
133f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org    public CipherParameters generateDerivedParameters(
13483217796ed57efe8954fc3b53d743aae1a6cfe6bGeoff Lang        int     keySize,
13583217796ed57efe8954fc3b53d743aae1a6cfe6bGeoff Lang        int     ivSize)
13683217796ed57efe8954fc3b53d743aae1a6cfe6bGeoff Lang    {
13783217796ed57efe8954fc3b53d743aae1a6cfe6bGeoff Lang        keySize = keySize / 8;
138f1f28c80b0486e2b1d7dc7d976efb16a467fc5dajbauman@chromium.org        ivSize = ivSize / 8;
139aa48067ac8125da0a96b10be3ea6e9df0fbaab43apatrick@chromium.org
140a43d829fabc8a251d6695922966ad25320e4c99fshannonwoods@chromium.org        byte[]  dKey = generateDerivedKey(keySize + ivSize);
141a43d829fabc8a251d6695922966ad25320e4c99fshannonwoods@chromium.org
142a43d829fabc8a251d6695922966ad25320e4c99fshannonwoods@chromium.org        return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
1437ab02fafb5de8cabadaa5eff10e473e79f9b027eJamie Madill    }
144a43d829fabc8a251d6695922966ad25320e4c99fshannonwoods@chromium.org
1457ab02fafb5de8cabadaa5eff10e473e79f9b027eJamie Madill    /**
146a43d829fabc8a251d6695922966ad25320e4c99fshannonwoods@chromium.org     * Generate a key parameter for use with a MAC derived from the password,
147a43d829fabc8a251d6695922966ad25320e4c99fshannonwoods@chromium.org     * salt, and iteration count we are currently initialised with.
148a43d829fabc8a251d6695922966ad25320e4c99fshannonwoods@chromium.org     *
1492e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com     * @param keySize the size of the key we want (in bits)
1502e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com     * @return a KeyParameter object.
1512e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com     */
1522e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com    public CipherParameters generateDerivedMacParameters(
1532e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com        int keySize)
1542e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com    {
1552e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com        return generateDerivedParameters(keySize);
1562e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com    }
1572e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com}
1582e38b800b3f448dd1a2e96a31db25d3bd5b6a3f4daniel@transgaming.com