001: package org.bouncycastle.jce.provider;
002:
003: import org.bouncycastle.crypto.BlockCipher;
004: import org.bouncycastle.crypto.CipherParameters;
005: import org.bouncycastle.crypto.DataLengthException;
006: import org.bouncycastle.crypto.StreamBlockCipher;
007: import org.bouncycastle.crypto.StreamCipher;
008: import org.bouncycastle.crypto.engines.BlowfishEngine;
009: import org.bouncycastle.crypto.engines.DESEngine;
010: import org.bouncycastle.crypto.engines.DESedeEngine;
011: import org.bouncycastle.crypto.engines.HC128Engine;
012: import org.bouncycastle.crypto.engines.HC256Engine;
013: import org.bouncycastle.crypto.engines.IDEAEngine;
014: import org.bouncycastle.crypto.engines.RC4Engine;
015: import org.bouncycastle.crypto.engines.Salsa20Engine;
016: import org.bouncycastle.crypto.engines.SkipjackEngine;
017: import org.bouncycastle.crypto.engines.TwofishEngine;
018: import org.bouncycastle.crypto.engines.VMPCEngine;
019: import org.bouncycastle.crypto.engines.VMPCKSA3Engine;
020: import org.bouncycastle.crypto.modes.CFBBlockCipher;
021: import org.bouncycastle.crypto.modes.OFBBlockCipher;
022: import org.bouncycastle.crypto.params.KeyParameter;
023: import org.bouncycastle.crypto.params.ParametersWithIV;
024:
025: import javax.crypto.Cipher;
026: import javax.crypto.NoSuchPaddingException;
027: import javax.crypto.SecretKey;
028: import javax.crypto.ShortBufferException;
029: import javax.crypto.spec.IvParameterSpec;
030: import javax.crypto.spec.PBEParameterSpec;
031: import javax.crypto.spec.RC2ParameterSpec;
032: import javax.crypto.spec.RC5ParameterSpec;
033: import java.security.AlgorithmParameters;
034: import java.security.InvalidAlgorithmParameterException;
035: import java.security.InvalidKeyException;
036: import java.security.Key;
037: import java.security.SecureRandom;
038: import java.security.spec.AlgorithmParameterSpec;
039:
040: public class JCEStreamCipher extends WrapCipherSpi implements PBE {
041: //
042: // specs we can handle.
043: //
044: private Class[] availableSpecs = { RC2ParameterSpec.class,
045: RC5ParameterSpec.class, IvParameterSpec.class,
046: PBEParameterSpec.class };
047:
048: private StreamCipher cipher;
049: private ParametersWithIV ivParam;
050:
051: private int ivLength = 0;
052:
053: private PBEParameterSpec pbeSpec = null;
054: private String pbeAlgorithm = null;
055:
056: protected JCEStreamCipher(StreamCipher engine, int ivLength) {
057: cipher = engine;
058: this .ivLength = ivLength;
059: }
060:
061: protected JCEStreamCipher(BlockCipher engine, int ivLength) {
062: this .ivLength = ivLength;
063:
064: cipher = new StreamBlockCipher(engine);
065: }
066:
067: protected int engineGetBlockSize() {
068: return 0;
069: }
070:
071: protected byte[] engineGetIV() {
072: return (ivParam != null) ? ivParam.getIV() : null;
073: }
074:
075: protected int engineGetKeySize(Key key) {
076: return key.getEncoded().length * 8;
077: }
078:
079: protected int engineGetOutputSize(int inputLen) {
080: return inputLen;
081: }
082:
083: protected AlgorithmParameters engineGetParameters() {
084: if (engineParams == null) {
085: if (pbeSpec != null) {
086: try {
087: AlgorithmParameters engineParams = AlgorithmParameters
088: .getInstance(pbeAlgorithm, "BC");
089: engineParams.init(pbeSpec);
090:
091: return engineParams;
092: } catch (Exception e) {
093: return null;
094: }
095: }
096: }
097:
098: return engineParams;
099: }
100:
101: /**
102: * should never be called.
103: */
104: protected void engineSetMode(String mode) {
105: if (!mode.equalsIgnoreCase("ECB")) {
106: throw new IllegalArgumentException("can't support mode "
107: + mode);
108: }
109: }
110:
111: /**
112: * should never be called.
113: */
114: protected void engineSetPadding(String padding)
115: throws NoSuchPaddingException {
116: if (!padding.equalsIgnoreCase("NoPadding")) {
117: throw new NoSuchPaddingException("Padding " + padding
118: + " unknown.");
119: }
120: }
121:
122: protected void engineInit(int opmode, Key key,
123: AlgorithmParameterSpec params, SecureRandom random)
124: throws InvalidKeyException,
125: InvalidAlgorithmParameterException {
126: CipherParameters param;
127:
128: this .pbeSpec = null;
129: this .pbeAlgorithm = null;
130:
131: this .engineParams = null;
132:
133: //
134: // basic key check
135: //
136: if (!(key instanceof SecretKey)) {
137: throw new InvalidKeyException("Key for algorithm "
138: + key.getAlgorithm()
139: + " not suitable for symmetric enryption.");
140: }
141:
142: if (key instanceof JCEPBEKey) {
143: JCEPBEKey k = (JCEPBEKey) key;
144:
145: if (k.getOID() != null) {
146: pbeAlgorithm = k.getOID().getId();
147: } else {
148: pbeAlgorithm = k.getAlgorithm();
149: }
150:
151: if (k.getParam() != null) {
152: param = k.getParam();
153: pbeSpec = new PBEParameterSpec(k.getSalt(), k
154: .getIterationCount());
155: } else if (params instanceof PBEParameterSpec) {
156: param = PBE.Util.makePBEParameters(k, params, cipher
157: .getAlgorithmName());
158: pbeSpec = (PBEParameterSpec) params;
159: } else {
160: throw new InvalidAlgorithmParameterException(
161: "PBE requires PBE parameters to be set.");
162: }
163:
164: if (k.getIvSize() != 0) {
165: ivParam = (ParametersWithIV) param;
166: }
167: } else if (params == null) {
168: param = new KeyParameter(key.getEncoded());
169: } else if (params instanceof IvParameterSpec) {
170: param = new ParametersWithIV(new KeyParameter(key
171: .getEncoded()), ((IvParameterSpec) params).getIV());
172: ivParam = (ParametersWithIV) param;
173: } else {
174: throw new IllegalArgumentException(
175: "unknown parameter type.");
176: }
177:
178: if ((ivLength != 0) && !(param instanceof ParametersWithIV)) {
179: SecureRandom ivRandom = random;
180:
181: if (ivRandom == null) {
182: ivRandom = new SecureRandom();
183: }
184:
185: if ((opmode == Cipher.ENCRYPT_MODE)
186: || (opmode == Cipher.WRAP_MODE)) {
187: byte[] iv = new byte[ivLength];
188:
189: ivRandom.nextBytes(iv);
190: param = new ParametersWithIV(param, iv);
191: ivParam = (ParametersWithIV) param;
192: } else {
193: throw new InvalidAlgorithmParameterException(
194: "no IV set when one expected");
195: }
196: }
197:
198: switch (opmode) {
199: case Cipher.ENCRYPT_MODE:
200: case Cipher.WRAP_MODE:
201: cipher.init(true, param);
202: break;
203: case Cipher.DECRYPT_MODE:
204: case Cipher.UNWRAP_MODE:
205: cipher.init(false, param);
206: break;
207: default:
208: System.out.println("eeek!");
209: }
210: }
211:
212: protected void engineInit(int opmode, Key key,
213: AlgorithmParameters params, SecureRandom random)
214: throws InvalidKeyException,
215: InvalidAlgorithmParameterException {
216: AlgorithmParameterSpec paramSpec = null;
217:
218: if (params != null) {
219: for (int i = 0; i != availableSpecs.length; i++) {
220: try {
221: paramSpec = params
222: .getParameterSpec(availableSpecs[i]);
223: break;
224: } catch (Exception e) {
225: continue;
226: }
227: }
228:
229: if (paramSpec == null) {
230: throw new InvalidAlgorithmParameterException(
231: "can't handle parameter " + params.toString());
232: }
233: }
234:
235: engineInit(opmode, key, paramSpec, random);
236: engineParams = params;
237: }
238:
239: protected void engineInit(int opmode, Key key, SecureRandom random)
240: throws InvalidKeyException {
241: try {
242: engineInit(opmode, key, (AlgorithmParameterSpec) null,
243: random);
244: } catch (InvalidAlgorithmParameterException e) {
245: throw new InvalidKeyException(e.getMessage());
246: }
247: }
248:
249: protected byte[] engineUpdate(byte[] input, int inputOffset,
250: int inputLen) {
251: byte[] out = new byte[inputLen];
252:
253: cipher.processBytes(input, inputOffset, inputLen, out, 0);
254:
255: return out;
256: }
257:
258: protected int engineUpdate(byte[] input, int inputOffset,
259: int inputLen, byte[] output, int outputOffset)
260: throws ShortBufferException {
261: try {
262: cipher.processBytes(input, inputOffset, inputLen, output,
263: outputOffset);
264:
265: return inputLen;
266: } catch (DataLengthException e) {
267: throw new ShortBufferException(e.getMessage());
268: }
269: }
270:
271: protected byte[] engineDoFinal(byte[] input, int inputOffset,
272: int inputLen) {
273: if (inputLen != 0) {
274: byte[] out = engineUpdate(input, inputOffset, inputLen);
275:
276: cipher.reset();
277:
278: return out;
279: }
280:
281: cipher.reset();
282:
283: return new byte[0];
284: }
285:
286: protected int engineDoFinal(byte[] input, int inputOffset,
287: int inputLen, byte[] output, int outputOffset) {
288: if (inputLen != 0) {
289: cipher.processBytes(input, inputOffset, inputLen, output,
290: outputOffset);
291: }
292:
293: cipher.reset();
294:
295: return inputLen;
296: }
297:
298: /*
299: * The ciphers that inherit from us.
300: */
301:
302: /**
303: * DES
304: */
305: static public class DES_CFB8 extends JCEStreamCipher {
306: public DES_CFB8() {
307: super (new CFBBlockCipher(new DESEngine(), 8), 64);
308: }
309: }
310:
311: /**
312: * DESede
313: */
314: static public class DESede_CFB8 extends JCEStreamCipher {
315: public DESede_CFB8() {
316: super (new CFBBlockCipher(new DESedeEngine(), 8), 64);
317: }
318: }
319:
320: /**
321: * SKIPJACK
322: */
323: static public class Skipjack_CFB8 extends JCEStreamCipher {
324: public Skipjack_CFB8() {
325: super (new CFBBlockCipher(new SkipjackEngine(), 8), 64);
326: }
327: }
328:
329: /**
330: * Blowfish
331: */
332: static public class Blowfish_CFB8 extends JCEStreamCipher {
333: public Blowfish_CFB8() {
334: super (new CFBBlockCipher(new BlowfishEngine(), 8), 64);
335: }
336: }
337:
338: /**
339: * Twofish
340: */
341: static public class Twofish_CFB8 extends JCEStreamCipher {
342: public Twofish_CFB8() {
343: super (new CFBBlockCipher(new TwofishEngine(), 8), 128);
344: }
345: }
346:
347: /**
348: * IDEA
349: */
350: static public class IDEA_CFB8 extends JCEStreamCipher {
351: public IDEA_CFB8() {
352: super (new CFBBlockCipher(new IDEAEngine(), 8), 64);
353: }
354: }
355:
356: /**
357: * DES
358: */
359: static public class DES_OFB8 extends JCEStreamCipher {
360: public DES_OFB8() {
361: super (new OFBBlockCipher(new DESEngine(), 8), 64);
362: }
363: }
364:
365: /**
366: * DESede
367: */
368: static public class DESede_OFB8 extends JCEStreamCipher {
369: public DESede_OFB8() {
370: super (new OFBBlockCipher(new DESedeEngine(), 8), 64);
371: }
372: }
373:
374: /**
375: * SKIPJACK
376: */
377: static public class Skipjack_OFB8 extends JCEStreamCipher {
378: public Skipjack_OFB8() {
379: super (new OFBBlockCipher(new SkipjackEngine(), 8), 64);
380: }
381: }
382:
383: /**
384: * Blowfish
385: */
386: static public class Blowfish_OFB8 extends JCEStreamCipher {
387: public Blowfish_OFB8() {
388: super (new OFBBlockCipher(new BlowfishEngine(), 8), 64);
389: }
390: }
391:
392: /**
393: * Twofish
394: */
395: static public class Twofish_OFB8 extends JCEStreamCipher {
396: public Twofish_OFB8() {
397: super (new OFBBlockCipher(new TwofishEngine(), 8), 128);
398: }
399: }
400:
401: /**
402: * IDEA
403: */
404: static public class IDEA_OFB8 extends JCEStreamCipher {
405: public IDEA_OFB8() {
406: super (new OFBBlockCipher(new IDEAEngine(), 8), 64);
407: }
408: }
409:
410: /**
411: * RC4
412: */
413: static public class RC4 extends JCEStreamCipher {
414: public RC4() {
415: super (new RC4Engine(), 0);
416: }
417: }
418:
419: /**
420: * PBEWithSHAAnd128BitRC4
421: */
422: static public class PBEWithSHAAnd128BitRC4 extends JCEStreamCipher {
423: public PBEWithSHAAnd128BitRC4() {
424: super (new RC4Engine(), 0);
425: }
426: }
427:
428: /**
429: * PBEWithSHAAnd40BitRC4
430: */
431: static public class PBEWithSHAAnd40BitRC4 extends JCEStreamCipher {
432: public PBEWithSHAAnd40BitRC4() {
433: super (new RC4Engine(), 0);
434: }
435: }
436:
437: /**
438: * Salsa20
439: */
440: static public class Salsa20 extends JCEStreamCipher {
441: public Salsa20() {
442: super (new Salsa20Engine(), 8);
443: }
444: }
445:
446: /**
447: * HC-128
448: */
449: static public class HC128 extends JCEStreamCipher {
450: public HC128() {
451: super (new HC128Engine(), 16);
452: }
453: }
454:
455: /**
456: * HC-256
457: */
458: static public class HC256 extends JCEStreamCipher {
459: public HC256() {
460: super (new HC256Engine(), 32);
461: }
462: }
463:
464: /**
465: * VMPC
466: */
467: static public class VMPC extends JCEStreamCipher {
468: public VMPC() {
469: super (new VMPCEngine(), 16);
470: }
471: }
472:
473: /**
474: * VMPC-KSA3
475: */
476: static public class VMPCKSA3 extends JCEStreamCipher {
477: public VMPCKSA3() {
478: super (new VMPCKSA3Engine(), 16);
479: }
480: }
481: }
|