DES.java revision a198e1ecc615e26a167d0f2dca9fa7e5fc62de10
1package org.bouncycastle.jcajce.provider.symmetric;
2
3import java.security.AlgorithmParameters;
4import java.security.InvalidAlgorithmParameterException;
5import java.security.SecureRandom;
6import java.security.spec.AlgorithmParameterSpec;
7import java.security.spec.InvalidKeySpecException;
8import java.security.spec.KeySpec;
9
10import javax.crypto.SecretKey;
11import javax.crypto.spec.DESKeySpec;
12import javax.crypto.spec.IvParameterSpec;
13import javax.crypto.spec.PBEKeySpec;
14import javax.crypto.spec.SecretKeySpec;
15
16import org.bouncycastle.asn1.ASN1ObjectIdentifier;
17import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
18import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
19import org.bouncycastle.crypto.CipherParameters;
20import org.bouncycastle.crypto.KeyGenerationParameters;
21import org.bouncycastle.crypto.engines.DESEngine;
22// BEGIN android-removed
23// import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
24// END android-removed
25import org.bouncycastle.crypto.generators.DESKeyGenerator;
26import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
27// BEGIN android-removed
28// import org.bouncycastle.crypto.macs.CFBBlockCipherMac;
29// import org.bouncycastle.crypto.macs.CMac;
30// import org.bouncycastle.crypto.macs.ISO9797Alg3Mac;
31// END android-removed
32import org.bouncycastle.crypto.modes.CBCBlockCipher;
33import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
34import org.bouncycastle.crypto.params.DESParameters;
35import org.bouncycastle.crypto.params.KeyParameter;
36import org.bouncycastle.crypto.params.ParametersWithIV;
37import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
38import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
39import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
40import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
41import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
42import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
43import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory;
44import org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher;
45import org.bouncycastle.jcajce.provider.symmetric.util.PBE;
46import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
47import org.bouncycastle.jce.provider.BouncyCastleProvider;
48
49public final class DES
50{
51    private DES()
52    {
53    }
54
55    static public class ECB
56        extends BaseBlockCipher
57    {
58        public ECB()
59        {
60            super(new DESEngine());
61        }
62    }
63
64    static public class CBC
65        extends BaseBlockCipher
66    {
67        public CBC()
68        {
69            super(new CBCBlockCipher(new DESEngine()), 64);
70        }
71    }
72
73    // BEGIN android-removed
74    // /**
75    //  * DES   CFB8
76    //  */
77    // public static class DESCFB8
78    //     extends BaseMac
79    // {
80    //     public DESCFB8()
81    //     {
82    //         super(new CFBBlockCipherMac(new DESEngine()));
83    //     }
84    // }
85    // END android-removed
86
87    /**
88     * DES64
89     */
90    public static class DES64
91        extends BaseMac
92    {
93        public DES64()
94        {
95            super(new CBCBlockCipherMac(new DESEngine(), 64));
96        }
97    }
98
99    /**
100     * DES64with7816-4Padding
101     */
102    public static class DES64with7816d4
103        extends BaseMac
104    {
105        public DES64with7816d4()
106        {
107            super(new CBCBlockCipherMac(new DESEngine(), 64, new ISO7816d4Padding()));
108        }
109    }
110
111    public static class CBCMAC
112        extends BaseMac
113    {
114        public CBCMAC()
115        {
116            super(new CBCBlockCipherMac(new DESEngine()));
117        }
118    }
119
120    // BEGIN android-removed
121    // static public class CMAC
122    //     extends BaseMac
123    // {
124    //     public CMAC()
125    //     {
126    //         super(new CMac(new DESEngine()));
127    //     }
128    // }
129    //
130    // /**
131    //  * DES9797Alg3with7816-4Padding
132    //  */
133    // public static class DES9797Alg3with7816d4
134    //     extends BaseMac
135    // {
136    //     public DES9797Alg3with7816d4()
137    //     {
138    //         super(new ISO9797Alg3Mac(new DESEngine(), new ISO7816d4Padding()));
139    //     }
140    // }
141    //
142    // /**
143    //  * DES9797Alg3
144    //  */
145    // public static class DES9797Alg3
146    //     extends BaseMac
147    // {
148    //     public DES9797Alg3()
149    //     {
150    //         super(new ISO9797Alg3Mac(new DESEngine()));
151    //     }
152    // }
153    //
154    // public static class RFC3211
155    //     extends BaseWrapCipher
156    // {
157    //     public RFC3211()
158    //     {
159    //         super(new RFC3211WrapEngine(new DESEngine()), 8);
160    //     }
161    // }
162    // END android-removed
163
164    public static class AlgParamGen
165        extends BaseAlgorithmParameterGenerator
166    {
167        protected void engineInit(
168            AlgorithmParameterSpec genParamSpec,
169            SecureRandom            random)
170            throws InvalidAlgorithmParameterException
171        {
172            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DES parameter generation.");
173        }
174
175        protected AlgorithmParameters engineGenerateParameters()
176        {
177            byte[]  iv = new byte[8];
178
179            if (random == null)
180            {
181                random = new SecureRandom();
182            }
183
184            random.nextBytes(iv);
185
186            AlgorithmParameters params;
187
188            try
189            {
190                params = AlgorithmParameters.getInstance("DES", BouncyCastleProvider.PROVIDER_NAME);
191                params.init(new IvParameterSpec(iv));
192            }
193            catch (Exception e)
194            {
195                throw new RuntimeException(e.getMessage());
196            }
197
198            return params;
199        }
200    }
201
202  /**
203     * DES - the default for this is to generate a key in
204     * a-b-a format that's 24 bytes long but has 16 bytes of
205     * key material (the first 8 bytes is repeated as the last
206     * 8 bytes). If you give it a size, you'll get just what you
207     * asked for.
208     */
209    public static class KeyGenerator
210        extends BaseKeyGenerator
211    {
212        public KeyGenerator()
213        {
214            super("DES", 64, new DESKeyGenerator());
215        }
216
217        protected void engineInit(
218            int             keySize,
219            SecureRandom random)
220        {
221            super.engineInit(keySize, random);
222        }
223
224        protected SecretKey engineGenerateKey()
225        {
226            if (uninitialised)
227            {
228                engine.init(new KeyGenerationParameters(new SecureRandom(), defaultKeySize));
229                uninitialised = false;
230            }
231
232            return new SecretKeySpec(engine.generateKey(), algName);
233        }
234    }
235
236    static public class KeyFactory
237        extends BaseSecretKeyFactory
238    {
239        public KeyFactory()
240        {
241            super("DES", null);
242        }
243
244        protected KeySpec engineGetKeySpec(
245            SecretKey key,
246            Class keySpec)
247        throws InvalidKeySpecException
248        {
249            if (keySpec == null)
250            {
251                throw new InvalidKeySpecException("keySpec parameter is null");
252            }
253            if (key == null)
254            {
255                throw new InvalidKeySpecException("key parameter is null");
256            }
257
258            if (SecretKeySpec.class.isAssignableFrom(keySpec))
259            {
260                return new SecretKeySpec(key.getEncoded(), algName);
261            }
262            else if (DESKeySpec.class.isAssignableFrom(keySpec))
263            {
264                byte[]  bytes = key.getEncoded();
265
266                try
267                {
268                    return new DESKeySpec(bytes);
269                }
270                catch (Exception e)
271                {
272                    throw new InvalidKeySpecException(e.toString());
273                }
274            }
275
276            throw new InvalidKeySpecException("Invalid KeySpec");
277        }
278
279        protected SecretKey engineGenerateSecret(
280            KeySpec keySpec)
281        throws InvalidKeySpecException
282        {
283            if (keySpec instanceof DESKeySpec)
284            {
285                DESKeySpec desKeySpec = (DESKeySpec)keySpec;
286                return new SecretKeySpec(desKeySpec.getKey(), "DES");
287            }
288
289            return super.engineGenerateSecret(keySpec);
290        }
291    }
292
293    static public class DESPBEKeyFactory
294        extends BaseSecretKeyFactory
295    {
296        private boolean forCipher;
297        private int     scheme;
298        private int     digest;
299        private int     keySize;
300        private int     ivSize;
301
302        public DESPBEKeyFactory(
303            String              algorithm,
304            ASN1ObjectIdentifier oid,
305            boolean             forCipher,
306            int                 scheme,
307            int                 digest,
308            int                 keySize,
309            int                 ivSize)
310        {
311            super(algorithm, oid);
312
313            this.forCipher = forCipher;
314            this.scheme = scheme;
315            this.digest = digest;
316            this.keySize = keySize;
317            this.ivSize = ivSize;
318        }
319
320        protected SecretKey engineGenerateSecret(
321            KeySpec keySpec)
322        throws InvalidKeySpecException
323        {
324            if (keySpec instanceof PBEKeySpec)
325            {
326                PBEKeySpec pbeSpec = (PBEKeySpec)keySpec;
327                CipherParameters param;
328
329                if (pbeSpec.getSalt() == null)
330                {
331                    return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, null);
332                }
333
334                if (forCipher)
335                {
336                    param = PBE.Util.makePBEParameters(pbeSpec, scheme, digest, keySize, ivSize);
337                }
338                else
339                {
340                    param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize);
341                }
342
343                KeyParameter kParam;
344                if (param instanceof ParametersWithIV)
345                {
346                    kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
347                }
348                else
349                {
350                    kParam = (KeyParameter)param;
351                }
352
353                DESParameters.setOddParity(kParam.getKey());
354
355                return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param);
356            }
357
358            throw new InvalidKeySpecException("Invalid KeySpec");
359        }
360    }
361
362    // BEGIN android-removed
363    // /**
364    //  * PBEWithMD2AndDES
365    //  */
366    // static public class PBEWithMD2KeyFactory
367    //     extends DESPBEKeyFactory
368    // {
369    //     public PBEWithMD2KeyFactory()
370    //     {
371    //         super("PBEwithMD2andDES", PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, true, PKCS5S1, MD2, 64, 64);
372    //     }
373    // }
374    // END android-removed
375
376    /**
377     * PBEWithMD5AndDES
378     */
379    static public class PBEWithMD5KeyFactory
380        extends DESPBEKeyFactory
381    {
382        public PBEWithMD5KeyFactory()
383        {
384            super("PBEwithMD5andDES", PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, true, PKCS5S1, MD5, 64, 64);
385        }
386    }
387
388    /**
389     * PBEWithSHA1AndDES
390     */
391    static public class PBEWithSHA1KeyFactory
392        extends DESPBEKeyFactory
393    {
394        public PBEWithSHA1KeyFactory()
395        {
396            super("PBEwithSHA1andDES", PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, true, PKCS5S1, SHA1, 64, 64);
397        }
398    }
399
400    // BEGIN android-removed
401    // /**
402    //  * PBEWithMD2AndDES
403    //  */
404    // static public class PBEWithMD2
405    //     extends BaseBlockCipher
406    // {
407    //     public PBEWithMD2()
408    //     {
409    //         super(new CBCBlockCipher(new DESEngine()));
410    //     }
411    // }
412    // END android-removed
413
414    /**
415     * PBEWithMD5AndDES
416     */
417    static public class PBEWithMD5
418        extends BaseBlockCipher
419    {
420        public PBEWithMD5()
421        {
422            super(new CBCBlockCipher(new DESEngine()));
423        }
424    }
425
426    /**
427     * PBEWithSHA1AndDES
428     */
429    static public class PBEWithSHA1
430        extends BaseBlockCipher
431    {
432        public PBEWithSHA1()
433        {
434            super(new CBCBlockCipher(new DESEngine()));
435        }
436    }
437
438    public static class Mappings
439        extends AlgorithmProvider
440    {
441        private static final String PREFIX = DES.class.getName();
442        private static final String PACKAGE = "org.bouncycastle.jcajce.provider.symmetric"; // JDK 1.2
443
444        public Mappings()
445        {
446        }
447
448        public void configure(ConfigurableProvider provider)
449        {
450
451            provider.addAlgorithm("Cipher.DES", PREFIX + "$ECB");
452            // BEGIN android-removed
453            // provider.addAlgorithm("Cipher." + OIWObjectIdentifiers.desCBC, PREFIX + "$CBC");
454            //
455            // addAlias(provider, OIWObjectIdentifiers.desCBC, "DES");
456            //
457            // provider.addAlgorithm("Cipher.DESRFC3211WRAP", PREFIX + "$RFC3211");
458            // END android-removed
459
460            provider.addAlgorithm("KeyGenerator.DES", PREFIX + "$KeyGenerator");
461
462            provider.addAlgorithm("SecretKeyFactory.DES", PREFIX + "$KeyFactory");
463
464            // BEGIN android-removed
465            // provider.addAlgorithm("Mac.DESCMAC", PREFIX + "$CMAC");
466            // provider.addAlgorithm("Mac.DESMAC", PREFIX + "$CBCMAC");
467            // provider.addAlgorithm("Alg.Alias.Mac.DES", "DESMAC");
468            //
469            // provider.addAlgorithm("Mac.DESMAC/CFB8", PREFIX + "$DESCFB8");
470            // provider.addAlgorithm("Alg.Alias.Mac.DES/CFB8", "DESMAC/CFB8");
471            //
472            // provider.addAlgorithm("Mac.DESMAC64", PREFIX + "$DES64");
473            // provider.addAlgorithm("Alg.Alias.Mac.DES64", "DESMAC64");
474            //
475            // provider.addAlgorithm("Mac.DESMAC64WITHISO7816-4PADDING", PREFIX + "$DES64with7816d4");
476            // provider.addAlgorithm("Alg.Alias.Mac.DES64WITHISO7816-4PADDING", "DESMAC64WITHISO7816-4PADDING");
477            // provider.addAlgorithm("Alg.Alias.Mac.DESISO9797ALG1MACWITHISO7816-4PADDING", "DESMAC64WITHISO7816-4PADDING");
478            // provider.addAlgorithm("Alg.Alias.Mac.DESISO9797ALG1WITHISO7816-4PADDING", "DESMAC64WITHISO7816-4PADDING");
479            //
480            // provider.addAlgorithm("Mac.DESWITHISO9797", PREFIX + "$DES9797Alg3");
481            // provider.addAlgorithm("Alg.Alias.Mac.DESISO9797MAC", "DESWITHISO9797");
482            //
483            // provider.addAlgorithm("Mac.ISO9797ALG3MAC", PREFIX + "$DES9797Alg3");
484            // provider.addAlgorithm("Alg.Alias.Mac.ISO9797ALG3", "ISO9797ALG3MAC");
485            // provider.addAlgorithm("Mac.ISO9797ALG3WITHISO7816-4PADDING", PREFIX + "$DES9797Alg3with7816d4");
486            // provider.addAlgorithm("Alg.Alias.Mac.ISO9797ALG3MACWITHISO7816-4PADDING", "ISO9797ALG3WITHISO7816-4PADDING");
487            // END android-removed
488
489            provider.addAlgorithm("AlgorithmParameters.DES", PACKAGE + ".util.IvAlgorithmParameters");
490            provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + OIWObjectIdentifiers.desCBC, "DES");
491
492            // BEGIN android-removed
493            // provider.addAlgorithm("AlgorithmParameterGenerator.DES",  PREFIX + "$AlgParamGen");
494            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + OIWObjectIdentifiers.desCBC, "DES");
495            //
496            // provider.addAlgorithm("Cipher.PBEWITHMD2ANDDES", PREFIX + "$PBEWithMD2");
497            // END android-removed
498            provider.addAlgorithm("Cipher.PBEWITHMD5ANDDES", PREFIX + "$PBEWithMD5");
499            provider.addAlgorithm("Cipher.PBEWITHSHA1ANDDES", PREFIX + "$PBEWithSHA1");
500
501            // BEGIN android-removed
502            // provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, "PBEWITHMD2ANDDES");
503            // END android-removed
504            provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES");
505            provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES");
506
507            // BEGIN android-removed
508            // provider.addAlgorithm("SecretKeyFactory.PBEWITHMD2ANDDES", PREFIX + "$PBEWithMD2KeyFactory");
509            // END android-removed
510            provider.addAlgorithm("SecretKeyFactory.PBEWITHMD5ANDDES", PREFIX + "$PBEWithMD5KeyFactory");
511            provider.addAlgorithm("SecretKeyFactory.PBEWITHSHA1ANDDES", PREFIX + "$PBEWithSHA1KeyFactory");
512
513            // BEGIN android-removed
514            // provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHMD2ANDDES-CBC", "PBEWITHMD2ANDDES");
515            // END android-removed
516            provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHMD5ANDDES-CBC", "PBEWITHMD5ANDDES");
517            provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA1ANDDES-CBC", "PBEWITHSHA1ANDDES");
518            // BEGIN android-removed
519            // provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, "PBEWITHMD2ANDDES");
520            // END android-removed
521            provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES");
522            provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES");
523        }
524
525        private void addAlias(ConfigurableProvider provider, ASN1ObjectIdentifier oid, String name)
526        {
527            provider.addAlgorithm("Alg.Alias.KeyGenerator." + oid.getId(), name);
528            provider.addAlgorithm("Alg.Alias.KeyFactory." + oid.getId(), name);
529        }
530    }
531}
532