/*
*
*
* Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.satsa.crypto;
import com.sun.midp.i3test.TestCase;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
/**
* This test case tests ARCFOUR (RC4) cipher
*/
public class TestRC4 extends TestCase {
private static final byte[] SECRET_KEY = {
0x73, 0x65, 0x63, 0x72, 0x65, 0x74 // "secret"
};
private static final byte[] PLAIN_TEXT = {
0x70, 0x6C, 0x61, 0x69, 0x6E, 0x74, 0x65, 0x78, 0x74 // "plaintext"
};
// cipher text corresponded to the plain text "plaintextplaintext"
private static final byte[] CIPHER_TEXT_PART_1 = {
(byte) 0x9D, 0x5A, (byte) 0xB3, 0x75, (byte) 0xEC,
(byte) 0xD0, (byte) 0xB3, (byte) 0xDE, 0x46
};
private static final byte[] CIPHER_TEXT_PART_2 = {
(byte) 0xBB, (byte) 0xD7, (byte) 0xBD, (byte) 0x9A,
(byte) 0x88, (byte) 0x81, 0x52, (byte) 0xD5, 0x43
};
private static final String ALGORITHM = "arcfour";
private static final String MODE = "/none";
private static final String PADDING = "/nopadding";
private byte[] outBuf1 = null;
private byte[] outBuf2 = null;
private Cipher cipher = null;
private SecretKeySpec key = null;
/**
* Test all primitive operations.
*/
private void testOne() {
// preparation
boolean noSuchAlg = false;
boolean noSuchPad = false;
boolean invKey = false;
boolean illState = false;
boolean shortBuf = false;
boolean illBlSize = false;
boolean badPad = false;
int outLen = 0;
outBuf1 = new byte[PLAIN_TEXT.length];
outBuf2 = new byte[PLAIN_TEXT.length];
assertNotNull("no memory for outBuf1", outBuf1);
assertNotNull("no memory for outBuf2", outBuf2);
cipher = null;
key = null;
// create cipher for not supported algorithm/mode
// -> NoSuchAlgorithmException should be thrown
try {
cipher = Cipher.getInstance(null);
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("Cipher.getInstance(null): NoSuchPaddingException",
noSuchPad);
assertTrue("Cipher.getInstance(null): no NoSuchAlgorithmException",
noSuchAlg);
assertNull("Cipher.getInstance(null): returned not null", cipher);
noSuchAlg = false;
try {
cipher = Cipher.getInstance("");
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("Cipher.getInstance(): NoSuchPaddingException",
noSuchPad);
assertTrue("Cipher.getInstance(): no NoSuchAlgorithmException",
noSuchAlg);
assertNull("Cipher.getInstance(): returned not null", cipher);
noSuchAlg = false;
try {
cipher = Cipher.getInstance("///");
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("Cipher.getInstance(///): NoSuchPaddingException",
noSuchPad);
assertTrue("Cipher.getInstance(///): no NoSuchAlgorithmException",
noSuchAlg);
assertNull("Cipher.getInstance(///): returned not null", cipher);
noSuchAlg = false;
try {
cipher = Cipher.getInstance("a/b/c");
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("Cipher.getInstance(a/b/c): NoSuchPaddingException",
noSuchPad);
assertTrue("Cipher.getInstance(a/b/c): no NoSuchAlgorithmException",
noSuchAlg);
assertNull("Cipher.getInstance(a/b/c): returned not null", cipher);
noSuchAlg = false;
try {
cipher = Cipher.getInstance("a/d/f/t/y");
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("Cipher.getInstance(a/d/f/t/y): NoSuchPaddingException",
noSuchPad);
assertTrue("Cipher.getInstance(a/d/f/t/y): no NoSuchAlgorithmException",
noSuchAlg);
assertNull("Cipher.getInstance(a/d/f/t/y): returned not null", cipher);
noSuchAlg = false;
try {
cipher = Cipher.getInstance(ALGORITHM + "/zzz");
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("Cipher.getInstance(ALG+/zzz): NoSuchPaddingException",
noSuchPad);
assertTrue("Cipher.getInstance(ALG+/zzz): no NoSuchAlgorithmException",
noSuchAlg);
assertNull("Cipher.getInstance(ALG+/zzz): returned not null", cipher);
noSuchAlg = false;
try {
cipher = Cipher.getInstance(ALGORITHM + MODE + PADDING + "/xxx");
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("Cipher.getInstance(+/xxx): NoSuchPaddingException",
noSuchPad);
assertTrue("Cipher.getInstance(+/xxx): no NoSuchAlgorithmException",
noSuchAlg);
assertNull("Cipher.getInstance(+/xxx): returned not null", cipher);
noSuchAlg = false;
// create cipher with not supported padding
// -> NoSuchPaddingException should be thrown
try {
cipher = Cipher.getInstance(ALGORITHM + MODE + "/yyy");
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("Cipher.getInstance(+/yyy): NoSuchAlgorithmException",
noSuchAlg);
assertTrue("Cipher.getInstance(+/yyy): no NoSuchPaddingException",
noSuchPad);
assertNull("Cipher.getInstance(+/yyy): returned not null", cipher);
noSuchPad = false;
// create cipher
try {
cipher = Cipher.getInstance(ALGORITHM + MODE + PADDING);
} catch (NoSuchAlgorithmException e) {
noSuchAlg = true;
} catch (NoSuchPaddingException e) {
noSuchPad = true;
}
assertFalse("NoSuchAlgorithmException exception", noSuchAlg);
assertFalse("NoSuchPaddingException exception", noSuchPad);
assertNotNull("Cipher.getInstance returned null", cipher);
// create key
key = new SecretKeySpec(SECRET_KEY, 0, SECRET_KEY.length, ALGORITHM);
assertNotNull("SecretKeySpec returned null", key);
assertEquals("wrong algorithm name", ALGORITHM.toUpperCase(),
key.getAlgorithm().toUpperCase());
assertTrue("wrong secret data", cmpArr(SECRET_KEY, key.getEncoded()));
// update() before init() -> IllegalStateException should be thrown
try {
outLen = cipher.update(PLAIN_TEXT, 0, PLAIN_TEXT.length,
outBuf1, 0);
} catch (IllegalStateException e) {
illState = true;
} catch (ShortBufferException e) {
shortBuf = true;
}
assertFalse("ShortBufferException exception", shortBuf);
assertTrue("no IllegalStateException after update()", illState);
illState = false;
// doFinal() before init() -> IllegalStateException should be thrown
try {
outLen = cipher.doFinal(PLAIN_TEXT, 0, PLAIN_TEXT.length,
outBuf2, 0);
} catch (IllegalStateException e) {
illState = true;
} catch (ShortBufferException e) {
shortBuf = true;
} catch (IllegalBlockSizeException e) {
illBlSize = true;
} catch (BadPaddingException e) {
badPad = true;
}
assertFalse("ShortBufferException exception", shortBuf);
assertFalse("IllegalBlockSizeException exception", illBlSize);
assertFalse("BadPaddingException exception", badPad);
assertTrue("no IllegalStateException after doFinal()", illState);
illState = false;
// init cipher for encryption
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
} catch (InvalidKeyException e) {
invKey = true;
}
assertFalse("InvalidKeyException exception", invKey);
// encrypt using update()
try {
outLen = cipher.update(PLAIN_TEXT, 0, PLAIN_TEXT.length,
outBuf1, 0);
} catch (IllegalStateException e) {
illState = true;
} catch (ShortBufferException e) {
shortBuf = true;
}
assertFalse("ShortBufferException exception", shortBuf);
assertFalse("IllegalStateException exception", illState);
assertEquals("outLen1 is not correct", PLAIN_TEXT.length, outLen);
// encrypt using doFinal()
try {
outLen = cipher.doFinal(PLAIN_TEXT, 0, PLAIN_TEXT.length,
outBuf2, 0);
} catch (IllegalStateException e) {
illState = true;
} catch (ShortBufferException e) {
shortBuf = true;
} catch (IllegalBlockSizeException e) {
illBlSize = true;
} catch (BadPaddingException e) {
badPad = true;
}
assertFalse("ShortBufferException exception", shortBuf);
assertFalse("IllegalBlockSizeException exception", illBlSize);
assertFalse("BadPaddingException exception", badPad);
assertFalse("IllegalStateException exception", illState);
assertEquals("outLen2 is not correct", PLAIN_TEXT.length, outLen);
// check encryption results
assertTrue("first part of encryption is wrong",
cmpArr(CIPHER_TEXT_PART_1, outBuf1));
assertTrue("second part of encryption is wrong",
cmpArr(CIPHER_TEXT_PART_2, outBuf2));
// init cipher for decryption
try {
cipher.init(Cipher.DECRYPT_MODE, key);
} catch (InvalidKeyException e) {
invKey = true;
}
assertFalse("InvalidKeyException exception", invKey);
// decrypt using update()
try {
outLen = cipher.update(CIPHER_TEXT_PART_1, 0,
CIPHER_TEXT_PART_1.length, outBuf1, 0);
} catch (IllegalStateException e) {
illState = true;
} catch (ShortBufferException e) {
shortBuf = true;
}
assertFalse("ShortBufferException exception", shortBuf);
assertFalse("IllegalStateException exception", illState);
assertEquals("outLen1 is not correct", PLAIN_TEXT.length, outLen);
// decrypt using doFinal()
try {
outLen = cipher.doFinal(CIPHER_TEXT_PART_2, 0,
CIPHER_TEXT_PART_2.length, outBuf2, 0);
} catch (IllegalStateException e) {
illState = true;
} catch (ShortBufferException e) {
shortBuf = true;
} catch (IllegalBlockSizeException e) {
illBlSize = true;
} catch (BadPaddingException e) {
badPad = true;
}
assertFalse("ShortBufferException exception", shortBuf);
assertFalse("IllegalBlockSizeException exception", illBlSize);
assertFalse("BadPaddingException exception", badPad);
assertFalse("IllegalStateException exception", illState);
assertEquals("outLen2 is not correct", PLAIN_TEXT.length, outLen);
// check decryption results
assertTrue("first part of decryption is wrong",
cmpArr(PLAIN_TEXT, outBuf1));
assertTrue("second part of decryption is wrong",
cmpArr(PLAIN_TEXT, outBuf2));
// incorrect outBuf size -> ShortBufferException should be thrown
try {
outLen = cipher.update(PLAIN_TEXT, 0, PLAIN_TEXT.length,
outBuf1, 1);
} catch (IllegalStateException e) {
illState = true;
} catch (ShortBufferException e) {
shortBuf = true;
}
assertFalse("IllegalStateException exception", illState);
assertTrue("no ShortBufferException after update()", shortBuf);
shortBuf = false;
try {
outLen = cipher.doFinal(PLAIN_TEXT, 0, PLAIN_TEXT.length,
outBuf2, 1);
} catch (IllegalStateException e) {
illState = true;
} catch (ShortBufferException e) {
shortBuf = true;
} catch (IllegalBlockSizeException e) {
illBlSize = true;
} catch (BadPaddingException e) {
badPad = true;
}
assertFalse("IllegalStateException exception", illState);
assertFalse("IllegalBlockSizeException exception", illBlSize);
assertFalse("BadPaddingException exception", badPad);
assertTrue("no ShortBufferException after doFinal()", shortBuf);
shortBuf = false;
}
/**
* Run tests.
*/
public void runTests() {
try {
declare("testOne");
testOne();
}
catch (Throwable t) {
fail("" + t);
}
}
/**
* Compare two byte arrays.
*/
private boolean cmpArr(byte[] one, byte[] two) {
if (one.length != two.length) {
return false;
}
for (int i = 0; i < one.length; i++) {
if (one[i] != two[i]) {
return false;
}
}
return true;
}
}
|