116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropackage org.bouncycastle.jcajce.provider.symmetric.util;
216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
364fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giroimport java.lang.reflect.Method;
4bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giroimport java.security.InvalidAlgorithmParameterException;
516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.spec.AlgorithmParameterSpec;
616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
7bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giroimport javax.crypto.SecretKey;
864fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro// BEGIN android-added
964fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giroimport javax.crypto.spec.IvParameterSpec;
1064fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro// END android-added
1116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.spec.PBEKeySpec;
1216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.spec.PBEParameterSpec;
1316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
1416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.CipherParameters;
1516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.PBEParametersGenerator;
167dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro// BEGIN android-added
177dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giroimport org.bouncycastle.crypto.digests.AndroidDigestFactory;
187dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro// END android-added
19c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// BEGIN android-removed
20c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.digests.GOST3411Digest;
21c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.digests.MD2Digest;
22c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.digests.RIPEMD160Digest;
23c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.digests.TigerDigest;
24c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// END android-removed
2516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
2616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
2716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
2816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
2916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DESParameters;
3016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.KeyParameter;
3116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.ParametersWithIV;
327dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro// BEGIN android-removed
337dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro// import org.bouncycastle.crypto.util.DigestFactory;
347dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro// END android-removed
3516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropublic interface PBE
3716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro{
3816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    //
3916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    // PBE Based encryption constants - by default we do PKCS12 with SHA-1
4016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    //
4116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        MD5          = 0;
4216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        SHA1         = 1;
43c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // BEGIN android-removed
44c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // static final int        RIPEMD160    = 2;
45c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // static final int        TIGER        = 3;
46c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // END android-removed
4716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        SHA256       = 4;
48c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // BEGIN android-removed
49c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // static final int        MD2          = 5;
50c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // static final int        GOST3411     = 6;
51c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // END android-removed
524caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    static final int        SHA224       = 7;
534caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    static final int        SHA384       = 8;
544caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    static final int        SHA512       = 9;
5516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
5616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        PKCS5S1      = 0;
5716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        PKCS5S2      = 1;
5816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        PKCS12       = 2;
5916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        OPENSSL      = 3;
6016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        PKCS5S1_UTF8 = 4;
6116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int        PKCS5S2_UTF8 = 5;
625c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro
6316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
6516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * uses the appropriate mixer to generate the key and IV if necessary.
6616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
6716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static class Util
6816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
6916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        static private PBEParametersGenerator makePBEGenerator(
7016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int                     type,
7116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int                     hash)
7216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
7316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            PBEParametersGenerator  generator;
7416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
7516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (type == PKCS5S1 || type == PKCS5S1_UTF8)
7616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
7716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                switch (hash)
7816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
79c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // BEGIN android-removed
80c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // case MD2:
81c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     generator = new PKCS5S1ParametersGenerator(new MD2Digest());
82c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     break;
83c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // END android-removed
8416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                case MD5:
85c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // BEGIN android-changed
86c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    generator = new PKCS5S1ParametersGenerator(AndroidDigestFactory.getMD5());
87c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // END android-changed
8816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    break;
8916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                case SHA1:
90c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // BEGIN android-changed
91c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    generator = new PKCS5S1ParametersGenerator(AndroidDigestFactory.getSHA1());
92c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // END android-changed
9316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    break;
9416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                default:
9516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    throw new IllegalStateException("PKCS5 scheme 1 only supports MD2, MD5 and SHA1.");
9616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
9716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
9816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (type == PKCS5S2 || type == PKCS5S2_UTF8)
9916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
10080261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                switch (hash)
10180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                {
102c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // BEGIN android-removed
103c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // case MD2:
104c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     generator = new PKCS5S2ParametersGenerator(new MD2Digest());
105c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     break;
106c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // END android-removed
10780261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                case MD5:
108c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // BEGIN android-changed
109c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getMD5());
110c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // END android-changed
11180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                    break;
1127dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro
11380261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                case SHA1:
114c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // BEGIN android-changed
115c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA1());
116c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // END android-changed
117c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    break;
118c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // BEGIN android-removed
119c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // case RIPEMD160:
120c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     generator = new PKCS5S2ParametersGenerator(new RIPEMD160Digest());
121c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     break;
122c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // case TIGER:
123c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     generator = new PKCS5S2ParametersGenerator(new TigerDigest());
124c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     break;
125c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // END android-removed
1265c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                // BEGIN android-added
1275c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                case SHA224:
1285c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA224());
1295c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    break;
1305c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                // END android-added
13180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                case SHA256:
132c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // BEGIN android-changed
133c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA256());
134c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // END android-changed
135c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    break;
1365c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                // BEGIN android-added
1375c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                case SHA384:
1385c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA384());
1395c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    break;
1405c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                case SHA512:
1415c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA512());
1425c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    break;
1435c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                // END android-added
14480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                default:
14580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                    throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption.");
14680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                }
14716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
14816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (type == PKCS12)
14916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
15016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                switch (hash)
15116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
152c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // BEGIN android-removed
153c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // case MD2:
154c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     generator = new PKCS12ParametersGenerator(new MD2Digest());
155c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     break;
156c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // END android-removed
15716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                case MD5:
158c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // BEGIN android-changed
159c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getMD5());
160c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // END android-changed
16116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    break;
16216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                case SHA1:
163c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // BEGIN android-changed
164c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA1());
165c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // END android-changed
166c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    break;
167c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // BEGIN android-removed
168c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // case RIPEMD160:
169c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     generator = new PKCS12ParametersGenerator(new RIPEMD160Digest());
170c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     break;
171c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // case TIGER:
172c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     generator = new PKCS12ParametersGenerator(new TigerDigest());
173c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                //     break;
174c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                // END android-removed
1755c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                // BEGIN android-added
1765c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                case SHA224:
1775c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA224());
1785c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    break;
1795c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                // END android-added
18016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                case SHA256:
181c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // BEGIN android-changed
182c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA256());
183c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    // END android-changed
184c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                    break;
1855c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                // BEGIN android-added
1865c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                case SHA384:
1875c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA384());
1885c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    break;
1895c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                case SHA512:
1905c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA512());
1915c39dfb0425106172f6ee6d5f38083d3ec2f266dSergio Giro                    break;
19216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                default:
19316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    throw new IllegalStateException("unknown digest scheme for PBE encryption.");
19416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
19516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
19616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
19716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
19816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                generator = new OpenSSLPBEParametersGenerator();
19916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
20016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
20116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return generator;
20216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
20316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
20416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        /**
205bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro         * construct a key and iv (if necessary) suitable for use with a
206bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro         * Cipher.
207bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro         */
208bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro        public static CipherParameters makePBEParameters(
209bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            byte[] pbeKey,
210bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            int scheme,
211bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            int digest,
212bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            int keySize,
213bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            int ivSize,
214bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            AlgorithmParameterSpec spec,
215bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            String targetAlgorithm)
216bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            throws InvalidAlgorithmParameterException
217bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro        {
218bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            if ((spec == null) || !(spec instanceof PBEParameterSpec))
219bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            {
220bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                throw new InvalidAlgorithmParameterException("Need a PBEParameter spec with a PBE key.");
221bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            }
222bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
223bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            PBEParameterSpec        pbeParam = (PBEParameterSpec)spec;
224bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            PBEParametersGenerator  generator = makePBEGenerator(scheme, digest);
225bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            byte[]                  key = pbeKey;
226bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            CipherParameters        param;
227bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
228bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro//            if (pbeKey.shouldTryWrongPKCS12())
229bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro//            {
230bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro//                key = new byte[2];
231bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro//            }
232bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
233bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
234bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
235bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            if (ivSize != 0)
236bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            {
237bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                param = generator.generateDerivedParameters(keySize, ivSize);
23864fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                // BEGIN ANDROID-ADDED
23964fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                // PKCS5S2 doesn't specify that the IV must be generated from the password. If the
24064fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                // IV is passed as a parameter, use it.
24164fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                AlgorithmParameterSpec parameterSpecFromPBEParameterSpec =
24264fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                        getParameterSpecFromPBEParameterSpec(pbeParam);
24364fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                if ((scheme == PKCS5S2 || scheme == PKCS5S2_UTF8)
24464fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                        && parameterSpecFromPBEParameterSpec instanceof IvParameterSpec) {
24564fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                    ParametersWithIV parametersWithIV = (ParametersWithIV) param;
24664fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                    IvParameterSpec ivParameterSpec =
24764fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                            (IvParameterSpec) parameterSpecFromPBEParameterSpec;
24864fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                    param = new ParametersWithIV(
24964fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                            (KeyParameter) parametersWithIV.getParameters(),
25064fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                            ivParameterSpec.getIV());
25164fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                }
25264fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                // END ANDROID-ADDED
253bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            }
254bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            else
255bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            {
256bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                param = generator.generateDerivedParameters(keySize);
257bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            }
258bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
259bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            if (targetAlgorithm.startsWith("DES"))
260bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            {
261bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                if (param instanceof ParametersWithIV)
262bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                {
263bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                    KeyParameter    kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
264bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
265bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                    DESParameters.setOddParity(kParam.getKey());
266bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                }
267bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                else
268bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                {
269bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                    KeyParameter    kParam = (KeyParameter)param;
270bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
271bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                    DESParameters.setOddParity(kParam.getKey());
272bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                }
273bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            }
274bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
275bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            return param;
276bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro        }
277bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
278bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro        /**
27916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * construct a key and iv (if necessary) suitable for use with a
28016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * Cipher.
28116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         */
28216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public static CipherParameters makePBEParameters(
28316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            BCPBEKey pbeKey,
28416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            AlgorithmParameterSpec spec,
28516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            String targetAlgorithm)
28616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
28716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if ((spec == null) || !(spec instanceof PBEParameterSpec))
28816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
28916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
29016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
29116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
29216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            PBEParameterSpec        pbeParam = (PBEParameterSpec)spec;
29316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            PBEParametersGenerator  generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
29416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            byte[]                  key = pbeKey.getEncoded();
29516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            CipherParameters        param;
29616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
29716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (pbeKey.shouldTryWrongPKCS12())
29816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
29916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                key = new byte[2];
30016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
30116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
30216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
30316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
30416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (pbeKey.getIvSize() != 0)
30516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
30616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                param = generator.generateDerivedParameters(pbeKey.getKeySize(), pbeKey.getIvSize());
30764fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                // BEGIN ANDROID-ADDED
30864fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                // PKCS5S2 doesn't specify that the IV must be generated from the password. If the
30964fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                // IV is passed as a parameter, use it.
31064fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                AlgorithmParameterSpec parameterSpecFromPBEParameterSpec =
31164fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                        getParameterSpecFromPBEParameterSpec(pbeParam);
31264fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                if ((pbeKey.getType() == PKCS5S2 || pbeKey.getType() == PKCS5S2_UTF8)
31364fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                        && parameterSpecFromPBEParameterSpec instanceof IvParameterSpec) {
31464fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                    ParametersWithIV parametersWithIV = (ParametersWithIV) param;
31564fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                    IvParameterSpec ivParameterSpec =
31664fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                            (IvParameterSpec) parameterSpecFromPBEParameterSpec;
31764fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                    param = new ParametersWithIV(
31864fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                            (KeyParameter) parametersWithIV.getParameters(),
31964fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                            ivParameterSpec.getIV());
32064fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                }
32164fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                // END ANDROID-ADDED
32216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
32316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
32416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
32516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                param = generator.generateDerivedParameters(pbeKey.getKeySize());
32616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
32716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
32816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (targetAlgorithm.startsWith("DES"))
32916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
33016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                if (param instanceof ParametersWithIV)
33116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
33216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    KeyParameter    kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
33316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
33416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    DESParameters.setOddParity(kParam.getKey());
33516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
33616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                else
33716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
33816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    KeyParameter    kParam = (KeyParameter)param;
33916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
34016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    DESParameters.setOddParity(kParam.getKey());
34116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
34216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
34316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
34416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return param;
34516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
34616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
34716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        /**
34816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * generate a PBE based key suitable for a MAC algorithm, the
34916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * key size is chosen according the MAC size, or the hashing algorithm,
35016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * whichever is greater.
35116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         */
35216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public static CipherParameters makePBEMacParameters(
35316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            BCPBEKey pbeKey,
35416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            AlgorithmParameterSpec spec)
35516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
35616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if ((spec == null) || !(spec instanceof PBEParameterSpec))
35716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
35816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
35916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
36016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
36116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            PBEParameterSpec        pbeParam = (PBEParameterSpec)spec;
36216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            PBEParametersGenerator  generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
36316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            byte[]                  key = pbeKey.getEncoded();
36416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            CipherParameters        param;
36516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
36616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
36716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
36816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            param = generator.generateDerivedMacParameters(pbeKey.getKeySize());
36916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
37016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return param;
37116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
372bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
373bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro        /**
374bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro         * generate a PBE based key suitable for a MAC algorithm, the
375bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro         * key size is chosen according the MAC size, or the hashing algorithm,
376bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro         * whichever is greater.
377bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro         */
378bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro        public static CipherParameters makePBEMacParameters(
379bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            PBEKeySpec keySpec,
380bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            int type,
381bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            int hash,
382bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            int keySize)
383bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro        {
384bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            PBEParametersGenerator  generator = makePBEGenerator(type, hash);
385bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            byte[]                  key;
386bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            CipherParameters        param;
387bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
388bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            key = convertPassword(type, keySpec);
389bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
390bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
391bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
392bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            param = generator.generateDerivedMacParameters(keySize);
393bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
394bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            for (int i = 0; i != key.length; i++)
395bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            {
396bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                key[i] = 0;
397bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            }
398bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
399bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            return param;
400bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro        }
401bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
40216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        /**
40316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * construct a key and iv (if necessary) suitable for use with a
40416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * Cipher.
40516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         */
40616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public static CipherParameters makePBEParameters(
40716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            PBEKeySpec keySpec,
40816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int type,
40916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int hash,
41016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int keySize,
41116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int ivSize)
41216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
41316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            PBEParametersGenerator  generator = makePBEGenerator(type, hash);
41416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            byte[]                  key;
41516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            CipherParameters        param;
41616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
41716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            key = convertPassword(type, keySpec);
41816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
41916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
42016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
42116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (ivSize != 0)
42216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
42316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                param = generator.generateDerivedParameters(keySize, ivSize);
42416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
42516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
42616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
42716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                param = generator.generateDerivedParameters(keySize);
42816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
42916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
43016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            for (int i = 0; i != key.length; i++)
43116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
43216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                key[i] = 0;
43316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
43416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
43516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return param;
43616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
43716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
43816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        /**
43916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * generate a PBE based key suitable for a MAC algorithm, the
44016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * key size is chosen according the MAC size, or the hashing algorithm,
44116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         * whichever is greater.
44216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         */
44316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public static CipherParameters makePBEMacParameters(
444bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            SecretKey key,
44516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int type,
44616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int hash,
447bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            int keySize,
448bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            PBEParameterSpec pbeSpec)
44916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
45016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            PBEParametersGenerator  generator = makePBEGenerator(type, hash);
45116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            CipherParameters        param;
45216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
453bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            byte[] keyBytes = key.getEncoded();
45416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
455bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            generator.init(key.getEncoded(), pbeSpec.getSalt(), pbeSpec.getIterationCount());
45680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
45716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            param = generator.generateDerivedMacParameters(keySize);
45880261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
459bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            for (int i = 0; i != keyBytes.length; i++)
46016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
461bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro                keyBytes[i] = 0;
46216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
46316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
46416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return param;
46516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
46616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
46764fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro        // BEGIN android-added
46864fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro        /**
46964fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro         * Invokes the method {@link PBEParameterSpec#getParameterSpec()} via reflection.
47064fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro         *
47164fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro         * Needed as the method was introduced in Java 1.8 and Bouncycastle level is 1.5.
47264fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro         *
47364fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro         * @return the parameter spec, or null if the method is not available.
47464fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro         */
47564fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro        public static AlgorithmParameterSpec getParameterSpecFromPBEParameterSpec(
47664fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                PBEParameterSpec pbeParameterSpec) {
47764fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro            try {
47864fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                Method getParameterSpecMethod = PBE.class.getClassLoader()
47964fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                        .loadClass("javax.crypto.spec.PBEParameterSpec")
48064fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                        .getMethod("getParameterSpec");
48164fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                return (AlgorithmParameterSpec) getParameterSpecMethod.invoke(pbeParameterSpec);
48264fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro            } catch (Exception e) {
48364fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro                return null;
48464fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro            }
48564fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro        }
48664fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro        // END android-added
48764fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro
48864fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giro
48916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        private static byte[] convertPassword(int type, PBEKeySpec keySpec)
49016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
49116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            byte[] key;
49216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
49316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (type == PKCS12)
49416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
49516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword());
49616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
49716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (type == PKCS5S2_UTF8 || type == PKCS5S1_UTF8)
49816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
49916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                key = PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(keySpec.getPassword());
50016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
50116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
50216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
50316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword());
50416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
50516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return key;
50616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
50716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
50816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro}
509