001: package org.bouncycastle.jce.provider.test;
002:
003: import org.bouncycastle.jce.provider.BouncyCastleProvider;
004: import org.bouncycastle.util.encoders.Hex;
005: import org.bouncycastle.util.test.SimpleTest;
006:
007: import javax.crypto.Cipher;
008: import javax.crypto.CipherInputStream;
009: import javax.crypto.CipherOutputStream;
010: import javax.crypto.KeyGenerator;
011: import javax.crypto.SecretKey;
012: import javax.crypto.ShortBufferException;
013: import javax.crypto.spec.IvParameterSpec;
014: import javax.crypto.spec.SecretKeySpec;
015: import java.io.ByteArrayInputStream;
016: import java.io.ByteArrayOutputStream;
017: import java.security.InvalidKeyException;
018: import java.security.Key;
019: import java.security.PrivateKey;
020: import java.security.PublicKey;
021: import java.security.Security;
022:
023: /**
024: * check that cipher input/output streams are working correctly
025: */
026: public class CipherStreamTest extends SimpleTest {
027:
028: private static byte[] RK = Hex.decode("0123456789ABCDEF");
029: private static byte[] RIN = Hex.decode("4e6f772069732074");
030: private static byte[] ROUT = Hex.decode("3afbb5c77938280d");
031:
032: private static byte[] SIN = Hex
033: .decode("00000000000000000000000000000000"
034: + "00000000000000000000000000000000"
035: + "00000000000000000000000000000000"
036: + "00000000000000000000000000000000");
037: private static final byte[] SK = Hex
038: .decode("80000000000000000000000000000000");
039: private static final byte[] SIV = Hex.decode("0000000000000000");
040: private static final byte[] SOUT = Hex
041: .decode("4DFA5E481DA23EA09A31022050859936"
042: + "DA52FCEE218005164F267CB65F5CFD7F"
043: + "2B4F97E0FF16924A52DF269515110A07"
044: + "F9E460BC65EF95DA58F740B7D1DBB0AA");
045:
046: private static final byte[] HCIN = new byte[64];
047: private static final byte[] HCIV = new byte[32];
048:
049: private static final byte[] HCK256A = new byte[32];
050: private static final byte[] HC256A = Hex
051: .decode("8589075b0df3f6d82fc0c5425179b6a6"
052: + "3465f053f2891f808b24744e18480b72"
053: + "ec2792cdbf4dcfeb7769bf8dfa14aee4"
054: + "7b4c50e8eaf3a9c8f506016c81697e32");
055:
056: private static final byte[] HCK128A = new byte[16];
057: private static final byte[] HC128A = Hex
058: .decode("731500823bfd03a0fb2fd77faa63af0e"
059: + "de122fc6a7dc29b662a685278b75ec68"
060: + "9036db1e8189600500ade078491fbf9a"
061: + "1cdc30136c3d6e2490f664b29cd57102");
062:
063: public CipherStreamTest() {
064: }
065:
066: private void runTest(String name) throws Exception {
067: String lCode = "ABCDEFGHIJKLMNOPQRSTUVWXY0123456789";
068: KeyGenerator kGen;
069:
070: if (name.indexOf('/') < 0) {
071: kGen = KeyGenerator.getInstance(name, "BC");
072: } else {
073: kGen = KeyGenerator.getInstance(name.substring(0, name
074: .indexOf('/')), "BC");
075: }
076:
077: Cipher in = Cipher.getInstance(name, "BC");
078: Cipher out = Cipher.getInstance(name, "BC");
079: Key key = kGen.generateKey();
080: ByteArrayInputStream bIn = new ByteArrayInputStream(lCode
081: .getBytes());
082: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
083:
084: in.init(Cipher.ENCRYPT_MODE, key);
085: if (in.getIV() != null) {
086: out.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(in
087: .getIV()));
088: } else {
089: out.init(Cipher.DECRYPT_MODE, key);
090: }
091:
092: CipherInputStream cIn = new CipherInputStream(bIn, in);
093: CipherOutputStream cOut = new CipherOutputStream(bOut, out);
094:
095: int c;
096:
097: while ((c = cIn.read()) >= 0) {
098: cOut.write(c);
099: }
100:
101: cIn.close();
102:
103: cOut.flush();
104: cOut.close();
105:
106: String res = new String(bOut.toByteArray());
107:
108: if (!res.equals(lCode)) {
109: fail("Failed - decrypted data doesn't match.");
110: }
111: }
112:
113: private void testAlgorithm(String name, byte[] keyBytes, byte[] iv,
114: byte[] plainText, byte[] cipherText) throws Exception {
115: SecretKey key = new SecretKeySpec(keyBytes, name);
116: Cipher in = Cipher.getInstance(name, "BC");
117: Cipher out = Cipher.getInstance(name, "BC");
118:
119: if (iv != null) {
120: in.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
121: out.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
122: } else {
123: in.init(Cipher.ENCRYPT_MODE, key);
124: out.init(Cipher.DECRYPT_MODE, key);
125: }
126:
127: byte[] enc = in.doFinal(plainText);
128: if (!areEqual(enc, cipherText)) {
129: fail(name + ": cipher text doesn't match");
130: }
131:
132: byte[] dec = out.doFinal(enc);
133:
134: if (!areEqual(dec, plainText)) {
135: fail(name + ": plain text doesn't match");
136: }
137: }
138:
139: private void testException(String name) {
140: try {
141: byte[] key128 = { (byte) 128, (byte) 131, (byte) 133,
142: (byte) 134, (byte) 137, (byte) 138, (byte) 140,
143: (byte) 143, (byte) 128, (byte) 131, (byte) 133,
144: (byte) 134, (byte) 137, (byte) 138, (byte) 140,
145: (byte) 143 };
146:
147: byte[] key256 = { (byte) 128, (byte) 131, (byte) 133,
148: (byte) 134, (byte) 137, (byte) 138, (byte) 140,
149: (byte) 143, (byte) 128, (byte) 131, (byte) 133,
150: (byte) 134, (byte) 137, (byte) 138, (byte) 140,
151: (byte) 143, (byte) 128, (byte) 131, (byte) 133,
152: (byte) 134, (byte) 137, (byte) 138, (byte) 140,
153: (byte) 143, (byte) 128, (byte) 131, (byte) 133,
154: (byte) 134, (byte) 137, (byte) 138, (byte) 140,
155: (byte) 143 };
156:
157: byte[] keyBytes;
158: if (name.equals("HC256")) {
159: keyBytes = key256;
160: } else {
161: keyBytes = key128;
162: }
163:
164: SecretKeySpec cipherKey = new SecretKeySpec(keyBytes, name);
165: Cipher ecipher = Cipher.getInstance(name, "BC");
166: ecipher.init(Cipher.ENCRYPT_MODE, cipherKey);
167:
168: byte[] cipherText = new byte[0];
169: try {
170: // According specification Method engineUpdate(byte[] input,
171: // int inputOffset, int inputLen, byte[] output, int
172: // outputOffset)
173: // throws ShortBufferException - if the given output buffer is
174: // too
175: // small to hold the result
176: ecipher.update(new byte[20], 0, 20, cipherText);
177:
178: fail("failed exception test - no ShortBufferException thrown");
179: } catch (ShortBufferException e) {
180: // ignore
181: }
182:
183: try {
184: Cipher c = Cipher.getInstance(name, "BC");
185:
186: Key k = new PublicKey() {
187:
188: public String getAlgorithm() {
189: return "STUB";
190: }
191:
192: public String getFormat() {
193: return null;
194: }
195:
196: public byte[] getEncoded() {
197: return null;
198: }
199:
200: };
201:
202: c.init(Cipher.ENCRYPT_MODE, k);
203:
204: fail("failed exception test - no InvalidKeyException thrown for public key");
205: } catch (InvalidKeyException e) {
206: // okay
207: }
208:
209: try {
210: Cipher c = Cipher.getInstance(name, "BC");
211:
212: Key k = new PrivateKey() {
213:
214: public String getAlgorithm() {
215: return "STUB";
216: }
217:
218: public String getFormat() {
219: return null;
220: }
221:
222: public byte[] getEncoded() {
223: return null;
224: }
225:
226: };
227:
228: c.init(Cipher.DECRYPT_MODE, k);
229:
230: fail("failed exception test - no InvalidKeyException thrown for private key");
231: } catch (InvalidKeyException e) {
232: // okay
233: }
234: } catch (Exception e) {
235: fail("unexpected exception.", e);
236: }
237: }
238:
239: public void performTest() throws Exception {
240: runTest("RC4");
241: testException("RC4");
242: testAlgorithm("RC4", RK, null, RIN, ROUT);
243: runTest("Salsa20");
244: testException("Salsa20");
245: testAlgorithm("Salsa20", SK, SIV, SIN, SOUT);
246: runTest("HC128");
247: testException("HC128");
248: testAlgorithm("HC128", HCK128A, HCIV, HCIN, HC128A);
249: runTest("HC256");
250: testException("HC256");
251: testAlgorithm("HC256", HCK256A, HCIV, HCIN, HC256A);
252: runTest("VMPC");
253: testException("VMPC");
254: //testAlgorithm("VMPC", a, iv, in, a);
255: runTest("VMPC-KSA3");
256: testException("VMPC-KSA3");
257: //testAlgorithm("VMPC-KSA3", a, iv, in, a);
258: runTest("DES/ECB/PKCS7Padding");
259: runTest("DES/CFB8/NoPadding");
260: }
261:
262: public String getName() {
263: return "CipherStreamTest";
264: }
265:
266: public static void main(String[] args) {
267: Security.addProvider(new BouncyCastleProvider());
268:
269: runTest(new CipherStreamTest());
270: }
271: }
|