001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.satsa.crypto;
028:
029: import com.sun.midp.i3test.TestCase;
030:
031: import javax.crypto.*;
032: import javax.crypto.spec.SecretKeySpec;
033: import java.security.NoSuchAlgorithmException;
034: import java.security.InvalidKeyException;
035:
036: /**
037: * This test case tests ARCFOUR (RC4) cipher
038: */
039: public class TestRC4 extends TestCase {
040:
041: private static final byte[] SECRET_KEY = { 0x73, 0x65, 0x63, 0x72,
042: 0x65, 0x74 // "secret"
043: };
044:
045: private static final byte[] PLAIN_TEXT = { 0x70, 0x6C, 0x61, 0x69,
046: 0x6E, 0x74, 0x65, 0x78, 0x74 // "plaintext"
047: };
048:
049: // cipher text corresponded to the plain text "plaintextplaintext"
050: private static final byte[] CIPHER_TEXT_PART_1 = { (byte) 0x9D,
051: 0x5A, (byte) 0xB3, 0x75, (byte) 0xEC, (byte) 0xD0,
052: (byte) 0xB3, (byte) 0xDE, 0x46 };
053: private static final byte[] CIPHER_TEXT_PART_2 = { (byte) 0xBB,
054: (byte) 0xD7, (byte) 0xBD, (byte) 0x9A, (byte) 0x88,
055: (byte) 0x81, 0x52, (byte) 0xD5, 0x43 };
056:
057: private static final String ALGORITHM = "arcfour";
058: private static final String MODE = "/none";
059: private static final String PADDING = "/nopadding";
060:
061: private byte[] outBuf1 = null;
062: private byte[] outBuf2 = null;
063:
064: private Cipher cipher = null;
065: private SecretKeySpec key = null;
066:
067: /**
068: * Test all primitive operations.
069: */
070: private void testOne() {
071:
072: // preparation
073:
074: boolean noSuchAlg = false;
075: boolean noSuchPad = false;
076: boolean invKey = false;
077: boolean illState = false;
078: boolean shortBuf = false;
079: boolean illBlSize = false;
080: boolean badPad = false;
081:
082: int outLen = 0;
083: outBuf1 = new byte[PLAIN_TEXT.length];
084: outBuf2 = new byte[PLAIN_TEXT.length];
085: assertNotNull("no memory for outBuf1", outBuf1);
086: assertNotNull("no memory for outBuf2", outBuf2);
087:
088: cipher = null;
089: key = null;
090:
091: // create cipher for not supported algorithm/mode
092: // -> NoSuchAlgorithmException should be thrown
093:
094: try {
095: cipher = Cipher.getInstance(null);
096: } catch (NoSuchAlgorithmException e) {
097: noSuchAlg = true;
098: } catch (NoSuchPaddingException e) {
099: noSuchPad = true;
100: }
101: assertFalse("Cipher.getInstance(null): NoSuchPaddingException",
102: noSuchPad);
103: assertTrue(
104: "Cipher.getInstance(null): no NoSuchAlgorithmException",
105: noSuchAlg);
106: assertNull("Cipher.getInstance(null): returned not null",
107: cipher);
108: noSuchAlg = false;
109:
110: try {
111: cipher = Cipher.getInstance("");
112: } catch (NoSuchAlgorithmException e) {
113: noSuchAlg = true;
114: } catch (NoSuchPaddingException e) {
115: noSuchPad = true;
116: }
117: assertFalse("Cipher.getInstance(): NoSuchPaddingException",
118: noSuchPad);
119: assertTrue("Cipher.getInstance(): no NoSuchAlgorithmException",
120: noSuchAlg);
121: assertNull("Cipher.getInstance(): returned not null", cipher);
122: noSuchAlg = false;
123:
124: try {
125: cipher = Cipher.getInstance("///");
126: } catch (NoSuchAlgorithmException e) {
127: noSuchAlg = true;
128: } catch (NoSuchPaddingException e) {
129: noSuchPad = true;
130: }
131: assertFalse("Cipher.getInstance(///): NoSuchPaddingException",
132: noSuchPad);
133: assertTrue(
134: "Cipher.getInstance(///): no NoSuchAlgorithmException",
135: noSuchAlg);
136: assertNull("Cipher.getInstance(///): returned not null", cipher);
137: noSuchAlg = false;
138:
139: try {
140: cipher = Cipher.getInstance("a/b/c");
141: } catch (NoSuchAlgorithmException e) {
142: noSuchAlg = true;
143: } catch (NoSuchPaddingException e) {
144: noSuchPad = true;
145: }
146: assertFalse(
147: "Cipher.getInstance(a/b/c): NoSuchPaddingException",
148: noSuchPad);
149: assertTrue(
150: "Cipher.getInstance(a/b/c): no NoSuchAlgorithmException",
151: noSuchAlg);
152: assertNull("Cipher.getInstance(a/b/c): returned not null",
153: cipher);
154: noSuchAlg = false;
155:
156: try {
157: cipher = Cipher.getInstance("a/d/f/t/y");
158: } catch (NoSuchAlgorithmException e) {
159: noSuchAlg = true;
160: } catch (NoSuchPaddingException e) {
161: noSuchPad = true;
162: }
163: assertFalse(
164: "Cipher.getInstance(a/d/f/t/y): NoSuchPaddingException",
165: noSuchPad);
166: assertTrue(
167: "Cipher.getInstance(a/d/f/t/y): no NoSuchAlgorithmException",
168: noSuchAlg);
169: assertNull("Cipher.getInstance(a/d/f/t/y): returned not null",
170: cipher);
171: noSuchAlg = false;
172:
173: try {
174: cipher = Cipher.getInstance(ALGORITHM + "/zzz");
175: } catch (NoSuchAlgorithmException e) {
176: noSuchAlg = true;
177: } catch (NoSuchPaddingException e) {
178: noSuchPad = true;
179: }
180: assertFalse(
181: "Cipher.getInstance(ALG+/zzz): NoSuchPaddingException",
182: noSuchPad);
183: assertTrue(
184: "Cipher.getInstance(ALG+/zzz): no NoSuchAlgorithmException",
185: noSuchAlg);
186: assertNull("Cipher.getInstance(ALG+/zzz): returned not null",
187: cipher);
188: noSuchAlg = false;
189:
190: try {
191: cipher = Cipher.getInstance(ALGORITHM + MODE + PADDING
192: + "/xxx");
193: } catch (NoSuchAlgorithmException e) {
194: noSuchAlg = true;
195: } catch (NoSuchPaddingException e) {
196: noSuchPad = true;
197: }
198: assertFalse(
199: "Cipher.getInstance(+/xxx): NoSuchPaddingException",
200: noSuchPad);
201: assertTrue(
202: "Cipher.getInstance(+/xxx): no NoSuchAlgorithmException",
203: noSuchAlg);
204: assertNull("Cipher.getInstance(+/xxx): returned not null",
205: cipher);
206: noSuchAlg = false;
207:
208: // create cipher with not supported padding
209: // -> NoSuchPaddingException should be thrown
210:
211: try {
212: cipher = Cipher.getInstance(ALGORITHM + MODE + "/yyy");
213: } catch (NoSuchAlgorithmException e) {
214: noSuchAlg = true;
215: } catch (NoSuchPaddingException e) {
216: noSuchPad = true;
217: }
218: assertFalse(
219: "Cipher.getInstance(+/yyy): NoSuchAlgorithmException",
220: noSuchAlg);
221: assertTrue(
222: "Cipher.getInstance(+/yyy): no NoSuchPaddingException",
223: noSuchPad);
224: assertNull("Cipher.getInstance(+/yyy): returned not null",
225: cipher);
226: noSuchPad = false;
227:
228: // create cipher
229:
230: try {
231: cipher = Cipher.getInstance(ALGORITHM + MODE + PADDING);
232: } catch (NoSuchAlgorithmException e) {
233: noSuchAlg = true;
234: } catch (NoSuchPaddingException e) {
235: noSuchPad = true;
236: }
237: assertFalse("NoSuchAlgorithmException exception", noSuchAlg);
238: assertFalse("NoSuchPaddingException exception", noSuchPad);
239: assertNotNull("Cipher.getInstance returned null", cipher);
240:
241: // create key
242:
243: key = new SecretKeySpec(SECRET_KEY, 0, SECRET_KEY.length,
244: ALGORITHM);
245: assertNotNull("SecretKeySpec returned null", key);
246: assertEquals("wrong algorithm name", ALGORITHM.toUpperCase(),
247: key.getAlgorithm().toUpperCase());
248: assertTrue("wrong secret data", cmpArr(SECRET_KEY, key
249: .getEncoded()));
250:
251: // update() before init() -> IllegalStateException should be thrown
252:
253: try {
254: outLen = cipher.update(PLAIN_TEXT, 0, PLAIN_TEXT.length,
255: outBuf1, 0);
256: } catch (IllegalStateException e) {
257: illState = true;
258: } catch (ShortBufferException e) {
259: shortBuf = true;
260: }
261: assertFalse("ShortBufferException exception", shortBuf);
262: assertTrue("no IllegalStateException after update()", illState);
263: illState = false;
264:
265: // doFinal() before init() -> IllegalStateException should be thrown
266:
267: try {
268: outLen = cipher.doFinal(PLAIN_TEXT, 0, PLAIN_TEXT.length,
269: outBuf2, 0);
270: } catch (IllegalStateException e) {
271: illState = true;
272: } catch (ShortBufferException e) {
273: shortBuf = true;
274: } catch (IllegalBlockSizeException e) {
275: illBlSize = true;
276: } catch (BadPaddingException e) {
277: badPad = true;
278: }
279: assertFalse("ShortBufferException exception", shortBuf);
280: assertFalse("IllegalBlockSizeException exception", illBlSize);
281: assertFalse("BadPaddingException exception", badPad);
282: assertTrue("no IllegalStateException after doFinal()", illState);
283: illState = false;
284:
285: // init cipher for encryption
286:
287: try {
288: cipher.init(Cipher.ENCRYPT_MODE, key);
289: } catch (InvalidKeyException e) {
290: invKey = true;
291: }
292: assertFalse("InvalidKeyException exception", invKey);
293:
294: // encrypt using update()
295:
296: try {
297: outLen = cipher.update(PLAIN_TEXT, 0, PLAIN_TEXT.length,
298: outBuf1, 0);
299: } catch (IllegalStateException e) {
300: illState = true;
301: } catch (ShortBufferException e) {
302: shortBuf = true;
303: }
304: assertFalse("ShortBufferException exception", shortBuf);
305: assertFalse("IllegalStateException exception", illState);
306: assertEquals("outLen1 is not correct", PLAIN_TEXT.length,
307: outLen);
308:
309: // encrypt using doFinal()
310:
311: try {
312: outLen = cipher.doFinal(PLAIN_TEXT, 0, PLAIN_TEXT.length,
313: outBuf2, 0);
314: } catch (IllegalStateException e) {
315: illState = true;
316: } catch (ShortBufferException e) {
317: shortBuf = true;
318: } catch (IllegalBlockSizeException e) {
319: illBlSize = true;
320: } catch (BadPaddingException e) {
321: badPad = true;
322: }
323: assertFalse("ShortBufferException exception", shortBuf);
324: assertFalse("IllegalBlockSizeException exception", illBlSize);
325: assertFalse("BadPaddingException exception", badPad);
326: assertFalse("IllegalStateException exception", illState);
327: assertEquals("outLen2 is not correct", PLAIN_TEXT.length,
328: outLen);
329:
330: // check encryption results
331:
332: assertTrue("first part of encryption is wrong", cmpArr(
333: CIPHER_TEXT_PART_1, outBuf1));
334: assertTrue("second part of encryption is wrong", cmpArr(
335: CIPHER_TEXT_PART_2, outBuf2));
336:
337: // init cipher for decryption
338:
339: try {
340: cipher.init(Cipher.DECRYPT_MODE, key);
341: } catch (InvalidKeyException e) {
342: invKey = true;
343: }
344: assertFalse("InvalidKeyException exception", invKey);
345:
346: // decrypt using update()
347:
348: try {
349: outLen = cipher.update(CIPHER_TEXT_PART_1, 0,
350: CIPHER_TEXT_PART_1.length, outBuf1, 0);
351: } catch (IllegalStateException e) {
352: illState = true;
353: } catch (ShortBufferException e) {
354: shortBuf = true;
355: }
356: assertFalse("ShortBufferException exception", shortBuf);
357: assertFalse("IllegalStateException exception", illState);
358: assertEquals("outLen1 is not correct", PLAIN_TEXT.length,
359: outLen);
360:
361: // decrypt using doFinal()
362:
363: try {
364: outLen = cipher.doFinal(CIPHER_TEXT_PART_2, 0,
365: CIPHER_TEXT_PART_2.length, outBuf2, 0);
366: } catch (IllegalStateException e) {
367: illState = true;
368: } catch (ShortBufferException e) {
369: shortBuf = true;
370: } catch (IllegalBlockSizeException e) {
371: illBlSize = true;
372: } catch (BadPaddingException e) {
373: badPad = true;
374: }
375: assertFalse("ShortBufferException exception", shortBuf);
376: assertFalse("IllegalBlockSizeException exception", illBlSize);
377: assertFalse("BadPaddingException exception", badPad);
378: assertFalse("IllegalStateException exception", illState);
379: assertEquals("outLen2 is not correct", PLAIN_TEXT.length,
380: outLen);
381:
382: // check decryption results
383:
384: assertTrue("first part of decryption is wrong", cmpArr(
385: PLAIN_TEXT, outBuf1));
386: assertTrue("second part of decryption is wrong", cmpArr(
387: PLAIN_TEXT, outBuf2));
388:
389: // incorrect outBuf size -> ShortBufferException should be thrown
390:
391: try {
392: outLen = cipher.update(PLAIN_TEXT, 0, PLAIN_TEXT.length,
393: outBuf1, 1);
394: } catch (IllegalStateException e) {
395: illState = true;
396: } catch (ShortBufferException e) {
397: shortBuf = true;
398: }
399: assertFalse("IllegalStateException exception", illState);
400: assertTrue("no ShortBufferException after update()", shortBuf);
401: shortBuf = false;
402:
403: try {
404: outLen = cipher.doFinal(PLAIN_TEXT, 0, PLAIN_TEXT.length,
405: outBuf2, 1);
406: } catch (IllegalStateException e) {
407: illState = true;
408: } catch (ShortBufferException e) {
409: shortBuf = true;
410: } catch (IllegalBlockSizeException e) {
411: illBlSize = true;
412: } catch (BadPaddingException e) {
413: badPad = true;
414: }
415: assertFalse("IllegalStateException exception", illState);
416: assertFalse("IllegalBlockSizeException exception", illBlSize);
417: assertFalse("BadPaddingException exception", badPad);
418: assertTrue("no ShortBufferException after doFinal()", shortBuf);
419: shortBuf = false;
420: }
421:
422: /**
423: * Run tests.
424: */
425: public void runTests() {
426: try {
427: declare("testOne");
428: testOne();
429: } catch (Throwable t) {
430: fail("" + t);
431: }
432: }
433:
434: /**
435: * Compare two byte arrays.
436: */
437: private boolean cmpArr(byte[] one, byte[] two) {
438: if (one.length != two.length) {
439: return false;
440: }
441: for (int i = 0; i < one.length; i++) {
442: if (one[i] != two[i]) {
443: return false;
444: }
445: }
446: return true;
447: }
448:
449: }
|