• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.jce.provider;
2 
3 import java.security.spec.AlgorithmParameterSpec;
4 
5 import javax.crypto.spec.PBEKeySpec;
6 import javax.crypto.spec.PBEParameterSpec;
7 
8 import org.bouncycastle.crypto.CipherParameters;
9 import org.bouncycastle.crypto.PBEParametersGenerator;
10 // BEGIN android-removed
11 // import org.bouncycastle.crypto.digests.MD2Digest;
12 // END android-removed
13 import org.bouncycastle.crypto.digests.MD5Digest;
14 // BEGIN android-removed
15 // import org.bouncycastle.crypto.digests.RIPEMD160Digest;
16 // END android-removed
17 import org.bouncycastle.crypto.digests.SHA1Digest;
18 import org.bouncycastle.crypto.digests.SHA256Digest;
19 // BEGIN android-removed
20 // import org.bouncycastle.crypto.digests.TigerDigest;
21 // END android-removed
22 import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
23 import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
24 import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
25 import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
26 import org.bouncycastle.crypto.params.DESParameters;
27 import org.bouncycastle.crypto.params.KeyParameter;
28 import org.bouncycastle.crypto.params.ParametersWithIV;
29 
30 public interface PBE
31 {
32     //
33     // PBE Based encryption constants - by default we do PKCS12 with SHA-1
34     //
35     static final int        MD5         = 0;
36     static final int        SHA1        = 1;
37     static final int        RIPEMD160   = 2;
38     static final int        TIGER       = 3;
39     static final int        SHA256      = 4;
40     static final int        MD2         = 5;
41 
42     static final int        PKCS5S1     = 0;
43     static final int        PKCS5S2     = 1;
44     static final int        PKCS12      = 2;
45     static final int        OPENSSL     = 3;
46 
47     /**
48      * uses the appropriate mixer to generate the key and IV if necessary.
49      */
50     static class Util
51     {
makePBEGenerator( int type, int hash)52         static private PBEParametersGenerator makePBEGenerator(
53             int                     type,
54             int                     hash)
55         {
56             PBEParametersGenerator  generator;
57 
58             if (type == PKCS5S1)
59             {
60                 switch (hash)
61                 {
62                 // BEGIN android-removed
63                 // case MD2:
64                 //     generator = new PKCS5S1ParametersGenerator(new MD2Digest());
65                 //     break;
66                 // END android-removed
67                 case MD5:
68                     generator = new PKCS5S1ParametersGenerator(new MD5Digest());
69                     break;
70                 case SHA1:
71                     generator = new PKCS5S1ParametersGenerator(new SHA1Digest());
72                     break;
73                 default:
74                     throw new IllegalStateException("PKCS5 scheme 1 only supports MD2, MD5 and SHA1.");
75                 }
76             }
77             else if (type == PKCS5S2)
78             {
79                 generator = new PKCS5S2ParametersGenerator();
80             }
81             else if (type == PKCS12)
82             {
83                 switch (hash)
84                 {
85                 // BEGIN android-removed
86                 // case MD2:
87                 //     generator = new PKCS12ParametersGenerator(new MD2Digest());
88                 //     break;
89                 // END android-removed
90                 case MD5:
91                     generator = new PKCS12ParametersGenerator(new MD5Digest());
92                     break;
93                 case SHA1:
94                     generator = new PKCS12ParametersGenerator(new SHA1Digest());
95                     break;
96                 // BEGIN android-removed
97                 // case RIPEMD160:
98                 //     generator = new PKCS12ParametersGenerator(new RIPEMD160Digest());
99                 //     break;
100                 // case TIGER:
101                 //     generator = new PKCS12ParametersGenerator(new TigerDigest());
102                 //     break;
103                 // END android-removed
104                 case SHA256:
105                     generator = new PKCS12ParametersGenerator(new SHA256Digest());
106                     break;
107                 default:
108                     throw new IllegalStateException("unknown digest scheme for PBE encryption.");
109                 }
110             }
111             else
112             {
113                 generator = new OpenSSLPBEParametersGenerator();
114             }
115 
116             return generator;
117         }
118 
119         /**
120          * construct a key and iv (if necessary) suitable for use with a
121          * Cipher.
122          */
makePBEParameters( JCEPBEKey pbeKey, AlgorithmParameterSpec spec, String targetAlgorithm)123         static CipherParameters makePBEParameters(
124             JCEPBEKey               pbeKey,
125             AlgorithmParameterSpec  spec,
126             String                  targetAlgorithm)
127         {
128             if ((spec == null) || !(spec instanceof PBEParameterSpec))
129             {
130                 throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
131             }
132 
133             PBEParameterSpec        pbeParam = (PBEParameterSpec)spec;
134             PBEParametersGenerator  generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
135             byte[]                  key = pbeKey.getEncoded();
136             CipherParameters        param;
137 
138             if (pbeKey.shouldTryWrongPKCS12())
139             {
140                 key = new byte[2];
141             }
142 
143             generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
144 
145             if (pbeKey.getIvSize() != 0)
146             {
147                 param = generator.generateDerivedParameters(pbeKey.getKeySize(), pbeKey.getIvSize());
148             }
149             else
150             {
151                 param = generator.generateDerivedParameters(pbeKey.getKeySize());
152             }
153 
154             if (targetAlgorithm.startsWith("DES"))
155             {
156                 if (param instanceof ParametersWithIV)
157                 {
158                     KeyParameter    kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
159 
160                     DESParameters.setOddParity(kParam.getKey());
161                 }
162                 else
163                 {
164                     KeyParameter    kParam = (KeyParameter)param;
165 
166                     DESParameters.setOddParity(kParam.getKey());
167                 }
168             }
169 
170             for (int i = 0; i != key.length; i++)
171             {
172                 key[i] = 0;
173             }
174 
175             return param;
176         }
177 
178         /**
179          * generate a PBE based key suitable for a MAC algorithm, the
180          * key size is chosen according the MAC size, or the hashing algorithm,
181          * whichever is greater.
182          */
makePBEMacParameters( JCEPBEKey pbeKey, AlgorithmParameterSpec spec)183         static CipherParameters makePBEMacParameters(
184             JCEPBEKey               pbeKey,
185             AlgorithmParameterSpec  spec)
186         {
187             if ((spec == null) || !(spec instanceof PBEParameterSpec))
188             {
189                 throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
190             }
191 
192             PBEParameterSpec        pbeParam = (PBEParameterSpec)spec;
193             PBEParametersGenerator  generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
194             byte[]                  key = pbeKey.getEncoded();
195             CipherParameters        param;
196 
197             if (pbeKey.shouldTryWrongPKCS12())
198             {
199                 key = new byte[2];
200             }
201 
202             generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
203 
204             param = generator.generateDerivedMacParameters(pbeKey.getKeySize());
205 
206             for (int i = 0; i != key.length; i++)
207             {
208                 key[i] = 0;
209             }
210 
211             return param;
212         }
213 
214         /**
215          * construct a key and iv (if necessary) suitable for use with a
216          * Cipher.
217          */
makePBEParameters( PBEKeySpec keySpec, int type, int hash, int keySize, int ivSize)218         static CipherParameters makePBEParameters(
219             PBEKeySpec              keySpec,
220             int                     type,
221             int                     hash,
222             int                     keySize,
223             int                     ivSize)
224         {
225             PBEParametersGenerator  generator = makePBEGenerator(type, hash);
226             byte[]                  key;
227             CipherParameters        param;
228 
229             if (type == PKCS12)
230             {
231                 key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword());
232             }
233             else
234             {
235                 key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword());
236             }
237 
238             generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
239 
240             if (ivSize != 0)
241             {
242                 param = generator.generateDerivedParameters(keySize, ivSize);
243             }
244             else
245             {
246                 param = generator.generateDerivedParameters(keySize);
247             }
248 
249             for (int i = 0; i != key.length; i++)
250             {
251                 key[i] = 0;
252             }
253 
254             return param;
255         }
256 
257         /**
258          * generate a PBE based key suitable for a MAC algorithm, the
259          * key size is chosen according the MAC size, or the hashing algorithm,
260          * whichever is greater.
261          */
makePBEMacParameters( PBEKeySpec keySpec, int type, int hash, int keySize)262         static CipherParameters makePBEMacParameters(
263             PBEKeySpec              keySpec,
264             int                     type,
265             int                     hash,
266             int                     keySize)
267         {
268             PBEParametersGenerator  generator = makePBEGenerator(type, hash);
269             byte[]                  key;
270             CipherParameters        param;
271 
272             if (type == PKCS12)
273             {
274                 key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword());
275             }
276             else
277             {
278                 key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword());
279             }
280 
281             generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
282 
283             param = generator.generateDerivedMacParameters(keySize);
284 
285             for (int i = 0; i != key.length; i++)
286             {
287                 key[i] = 0;
288             }
289 
290             return param;
291         }
292     }
293 }
294