001: /*
002:
003: Derby - Class org.apache.derbyTesting.unitTests.crypto.T_Cipher
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derbyTesting.unitTests.crypto;
023:
024: import org.apache.derbyTesting.unitTests.harness.T_Generic;
025: import org.apache.derbyTesting.unitTests.harness.T_Fail;
026:
027: import org.apache.derby.iapi.services.crypto.*;
028:
029: import org.apache.derby.iapi.services.monitor.Monitor;
030:
031: import org.apache.derby.iapi.db.PropertyInfo;
032:
033: import org.apache.derby.iapi.error.StandardException;
034:
035: import java.security.AccessController;
036: import java.security.Key;
037: import java.security.PrivilegedAction;
038: import java.security.PrivilegedExceptionAction;
039:
040: import java.io.File;
041: import java.io.FileNotFoundException;
042: import java.io.InputStream;
043: import java.io.OutputStream;
044: import java.io.FileInputStream;
045: import java.io.FileOutputStream;
046: import java.io.RandomAccessFile;
047: import java.io.IOException;
048:
049: import java.util.Properties;
050:
051: /*
052: // PT
053: import javax.crypto.Cipher;
054: import javax.crypto.spec.SecretKeySpec;
055: import java.security.spec.KeySpec;
056: import java.security.AlgorithmParameters;
057: // import java.security.spec.AlgorithmParameterSpec;
058: import javax.crypto.spec.IvParameterSpec;
059: import java.security.GeneralSecurityException;
060: import java.security.MessageDigest;
061: import java.lang.reflect.*;
062: */
063:
064: /*
065: To run, put the following line in derby.properties
066: derby.module.test.T_Cipher=org.apache.derbyTesting.unitTests.crypto.T_Cipher
067:
068: and run java org.apache.derbyTesting.unitTests.harness.UnitTestMain
069:
070: */
071: public class T_Cipher extends T_Generic {
072: private static final String testService = "CipherText";
073:
074: CipherProvider enEngine;
075: CipherProvider deEngine;
076: Key secretKey;
077: byte[] IV;
078:
079: CipherFactory factory;
080:
081: public T_Cipher() {
082: super ();
083: }
084:
085: /*
086: ** Methods required by T_Generic
087: */
088:
089: public String getModuleToTestProtocolName() {
090: return org.apache.derby.iapi.reference.Module.CipherFactoryBuilder;
091: }
092:
093: protected String getAlgorithm() {
094: return "DES/CBC/NoPadding";
095: }
096:
097: protected String getProvider() {
098: // allow for alternate providers
099: String testProvider =
100:
101: (String) AccessController.doPrivileged(new PrivilegedAction() {
102: public Object run() {
103: return System.getProperty("testEncryptionProvider");
104: }
105: });
106:
107: if (testProvider != null)
108: return testProvider;
109: else
110: return null;
111:
112: }
113:
114: public void runTests() throws T_Fail {
115:
116: File testFile = new File("extinout/T_Cipher.data");
117: deleteFile(testFile);
118:
119: String bootPassword = "a secret, don't tell anyone";
120:
121: try {
122: RandomAccessFile file = new RandomAccessFile(testFile, "rw");
123:
124: setupCiphers(bootPassword);
125:
126: // run thru some in patterns
127: int patternLength = 8192;
128: byte[] pattern = new byte[patternLength];
129: for (int i = 0; i < patternLength; i++)
130: pattern[i] = (byte) (i & 0xFF);
131:
132: test(pattern, 0, 8, file); // test short patterns
133: test(pattern, 8, 8, file);
134: test(pattern, 1, 16, file);
135:
136: test(pattern, 0, patternLength, file); // test long pattern
137: test(pattern, 0, patternLength / 2, file);
138: test(pattern, 1, patternLength / 2, file);
139: test(pattern, 2, patternLength / 2, file);
140: test(pattern, 3, patternLength / 2, file);
141:
142: file.seek(0);
143: check(pattern, 0, 8, file); // file offset 0
144: check(pattern, 8, 8, file); // file offset 8
145: check(pattern, 1, 16, file); // file offset 16
146: check(pattern, 0, patternLength, file); // file offset 32
147: check(pattern, 0, patternLength / 2, file);// file offset 32+patternLength
148: check(pattern, 1, patternLength / 2, file);// file offset 32+patternLength+(patternLength/2)
149: check(pattern, 2, patternLength / 2, file);// file offset 32+(2*patternLength)
150: check(pattern, 3, patternLength / 2, file);// file offset 32+(2*patternLength)+(patternLength/2);
151:
152: REPORT("starting random test");
153:
154: // now do some random testing from file
155: file.seek(32 + patternLength);
156: check(pattern, 0, patternLength / 2, file);
157:
158: file.seek(32);
159: check(pattern, 0, patternLength, file);
160:
161: file.seek(32 + (2 * patternLength));
162: check(pattern, 2, patternLength / 2, file);
163:
164: file.seek(0);
165: check(pattern, 0, 8, file);
166:
167: file.seek(16);
168: check(pattern, 1, 16, file);
169:
170: file.seek(32 + (2 * patternLength) + (patternLength / 2));
171: check(pattern, 3, patternLength / 2, file);
172:
173: file.seek(8);
174: check(pattern, 8, 8, file);
175:
176: file.seek(32 + patternLength + (patternLength / 2));
177: check(pattern, 1, patternLength / 2, file);
178:
179: file.close();
180: } catch (StandardException se) {
181: se.printStackTrace(System.out);
182: throw T_Fail.exceptionFail(se);
183: } catch (IOException ioe) {
184: throw T_Fail.exceptionFail(ioe);
185: }
186:
187: PASS("T_Cipher");
188: }
189:
190: protected void setupCiphers(String bootPassword) throws T_Fail,
191: StandardException {
192: // set properties for testing
193: Properties props = new Properties();
194: props.put("encryptionAlgorithm", getAlgorithm());
195: String provider = getProvider();
196: if (provider != null)
197: props.put("encryptionProvider", getProvider());
198: props.put("bootPassword", bootPassword);
199:
200: REPORT("encryption algorithm used : " + getAlgorithm());
201: REPORT("encryption provider used : " + provider);
202:
203: CipherFactoryBuilder cb = (CipherFactoryBuilder) Monitor
204: .startSystemModule(org.apache.derby.iapi.reference.Module.CipherFactoryBuilder);
205:
206: factory = cb.createCipherFactory(true, props, false);
207:
208: if (factory == null)
209: throw T_Fail.testFailMsg("cannot find Cipher factory ");
210:
211: enEngine = factory.createNewCipher(CipherFactory.ENCRYPT);
212: deEngine = factory.createNewCipher(CipherFactory.DECRYPT);
213:
214: if (enEngine == null)
215: throw T_Fail.testFailMsg("cannot create encryption engine");
216: if (deEngine == null)
217: throw T_Fail.testFailMsg("cannot create decryption engine");
218: }
219:
220: protected void test(byte[] cleartext, int offset, int length,
221: RandomAccessFile outfile) throws T_Fail, StandardException,
222: IOException {
223: byte[] ciphertext = new byte[length];
224: System.arraycopy(cleartext, offset, ciphertext, 0, length);
225:
226: if (enEngine.encrypt(ciphertext, 0, length, ciphertext, 0) != length)
227: throw T_Fail.testFailMsg("encrypted text length != length");
228:
229: if (byteArrayIdentical(ciphertext, cleartext, offset, length))
230: throw T_Fail
231: .testFailMsg("encryption just made a copy of the clear text");
232:
233: outfile.write(ciphertext);
234:
235: // now decrypt it and check
236: deEngine.decrypt(ciphertext, 0, length, ciphertext, 0);
237: if (byteArrayIdentical(ciphertext, cleartext, offset, length) == false)
238: throw T_Fail
239: .testFailMsg("decryption did not yield the same clear text");
240: }
241:
242: protected void check(byte[] cleartext, int offset, int length,
243: RandomAccessFile infile) throws IOException, T_Fail,
244: StandardException {
245: byte[] ciphertext = new byte[length];
246: infile.read(ciphertext);
247:
248: if (deEngine.decrypt(ciphertext, 0, length, ciphertext, 0) != length)
249: throw T_Fail.testFailMsg("decrypted text length != length");
250:
251: if (byteArrayIdentical(ciphertext, cleartext, offset, length) == false)
252: throw T_Fail
253: .testFailMsg("decryption did not yield the same clear text");
254:
255: }
256:
257: // see if 2 byte arrays are identical
258: protected boolean byteArrayIdentical(byte[] compare,
259: byte[] original, int offset, int length) {
260: for (int i = 0; i < length; i++) {
261: if (compare[i] != original[offset + i])
262: return false;
263: }
264: return true;
265: }
266:
267: /*
268: private void testBlowfish()
269: {
270: System.out.println("Running testBlowfish");
271: try
272: {
273: // set up the provider
274: java.security.Provider sunJce = new com.sun.crypto.provider.SunJCE();
275: java.security.Security.addProvider(sunJce);
276:
277: // String key = "Paula bla la da trish123 sdkfs;ldkg;sa'jlskjgklad";
278: String key = "Paulabla123456789012345";
279: byte[] buf = key.getBytes();
280: System.out.println("key length is " + buf.length);
281: SecretKeySpec sKeySpec = new SecretKeySpec(buf,"Blowfish");
282: // SecretKeySpec sKeySpec = new SecretKeySpec(buf,"DESede");
283:
284: Cipher cipher = Cipher.getInstance("Blowfish/CBC/NoPadding");
285: // Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
286: // Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
287: cipher.init(Cipher.ENCRYPT_MODE,sKeySpec);
288: // only works with NoPadding if size is a multiple of 8 bytes
289: // with PKCS5Padding, works for all sizes
290: byte[] original = "This is what should get encrypte".getBytes();
291: System.out.println("original length is " + original.length);
292: byte[] encrypted = cipher.doFinal(original);
293: // works
294: // AlgorithmParameters algParam = cipher.getParameters();
295: byte[] iv = cipher.getIV();
296: System.out.println("length of iv is " + iv.length);
297:
298: Cipher cipher2 = Cipher.getInstance("Blowfish/CBC/NoPadding");
299: // Cipher cipher2 = Cipher.getInstance("DESede/CBC/NoPadding");
300: // Cipher cipher2 = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
301:
302: // works
303: // cipher2.init(Cipher.DECRYPT_MODE,sKeySpec,algParam);
304: IvParameterSpec ivClass = new IvParameterSpec(iv);
305: cipher2.init(Cipher.DECRYPT_MODE,sKeySpec,ivClass);
306: byte[] decrypted = cipher2.doFinal(encrypted);
307:
308: if (byteArrayIdentical(original,decrypted,0,original.length))
309: System.out.println("PASSED");
310: else
311: System.out.println("FAILED");
312:
313: System.out.println("original length is " + original.length);
314: System.out.println("encrypted length is " + encrypted.length);
315: System.out.println("decrypted length is " + decrypted.length);
316: }
317: catch (Throwable t)
318: {
319: System.out.println("got an exception");
320: t.printStackTrace();
321: }
322:
323: System.out.println("Finished testBlowfish");
324: }
325:
326:
327: private void testCryptix()
328: {
329: System.out.println("Running testCryptix");
330: try
331: {
332: // set up the provider
333: Class jceClass = Class.forName("cryptix.jce.provider.Cryptix");
334: java.security.Provider cryptixProvider = (java.security.Provider) jceClass.newInstance();
335: java.security.Security.addProvider(cryptixProvider);
336:
337: byte[] userkey = "a secret".getBytes();
338: System.out.println("userkey length is " + userkey.length);
339: Key secretKey = (Key) (new SecretKeySpec(userkey, "DES"));
340: byte[] IV = "anivspec".getBytes();
341:
342: Cipher enCipher = Cipher.getInstance("DES/CBC/NoPadding","Cryptix");
343: Cipher deCipher = Cipher.getInstance("DES/CBC/NoPadding","Cryptix");
344: IvParameterSpec ivspec = new IvParameterSpec(IV);
345:
346: enCipher.init(Cipher.ENCRYPT_MODE,secretKey,ivspec);
347: deCipher.init(Cipher.DECRYPT_MODE,secretKey,ivspec);
348:
349: int patternLength = 8;
350: byte[] pattern = new byte[patternLength];
351: for (int i = 0; i < patternLength; i++)
352: pattern[i] = (byte)(i & 0xFF);
353:
354: byte[] cipherOutput1 = new byte[patternLength];
355: byte[] cipherOutput2 = new byte[patternLength];
356:
357: int retval = 0;
358: retval = enCipher.doFinal(pattern, 0, 8, cipherOutput1, 0);
359:
360: retval = deCipher.doFinal(cipherOutput1, 0, 8, cipherOutput2, 0);
361:
362: if (byteArrayIdentical(cipherOutput2,pattern,0,patternLength))
363: System.out.println("PASSED TEST 1");
364: else
365: System.out.println("FAILED TEST 1");
366:
367: retval = deCipher.doFinal(cipherOutput1, 0, 8, cipherOutput2, 0);
368:
369: if (byteArrayIdentical(cipherOutput2,pattern,0,patternLength))
370: System.out.println("PASSED TEST 2");
371: else
372: System.out.println("FAILED TEST 2");
373: }
374: catch (Throwable t)
375: {
376: System.out.println("got an exception");
377: t.printStackTrace();
378: }
379:
380: System.out.println("Finished testCryptix");
381: }
382:
383:
384:
385: private void testMessageDigest()
386: {
387: // No provider needs to be installed for this to work.
388: try
389: {
390: MessageDigest md = MessageDigest.getInstance("MD5");
391: byte[] data = "Paulas digest".getBytes();
392: byte[] digest = md.digest(data);
393: byte[] digest2 = md.digest(data);
394: if (byteArrayIdentical(digest,digest2,0,digest.length))
395: System.out.println("PASSED");
396: else
397: System.out.println("FAILED");
398:
399: System.out.println("data length is " + data.length);
400: System.out.println("digest length is " + digest.length);
401: System.out.println("digest2 length is " + digest2.length);
402: }
403: catch (Throwable t)
404: {
405: System.out.println("got an exception");
406: t.printStackTrace();
407: }
408:
409: System.out.println("Finished testBlowfish");
410: }
411:
412: // PT
413: private void testPCBC()
414: {
415: System.out.println("Running testPCBC");
416: try
417: {
418: // set up the provider
419: Class jceClass = Class.forName("com.sun.crypto.provider.SunJCE");
420: java.security.Provider myProvider = (java.security.Provider) jceClass.newInstance();
421: java.security.Security.addProvider(myProvider);
422: // java.security.Provider sunJce = new com.sun.crypto.provider.SunJCE();
423: // java.security.Security.addProvider(sunJce);
424:
425: // String key = "Paula bla la da trish123 sdkfs;ldkg;sa'jlskjgklad";
426: String key = "PaulablaPaulablaPaulabla";
427: byte[] buf = key.getBytes();
428: System.out.println("key length is " + buf.length);
429: SecretKeySpec sKeySpec = new SecretKeySpec(buf,"DESede");
430:
431: Cipher cipher = Cipher.getInstance("DESede/PCBC/NoPadding");
432: // Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
433: // Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
434: cipher.init(Cipher.ENCRYPT_MODE,sKeySpec);
435: // only works with NoPadding if size is a multiple of 8 bytes
436: // with PKCS5Padding, works for all sizes
437: byte[] original = "This is what should get encrypte".getBytes();
438: System.out.println("original length is " + original.length);
439: byte[] encrypted = cipher.doFinal(original);
440: // works
441: // AlgorithmParameters algParam = cipher.getParameters();
442: byte[] iv = cipher.getIV();
443: System.out.println("length of iv is " + iv.length);
444:
445: Cipher cipher2 = Cipher.getInstance("DESede/PCBC/NoPadding");
446: // Cipher cipher2 = Cipher.getInstance("DESede/CBC/NoPadding");
447: // Cipher cipher2 = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
448:
449: // works
450: // cipher2.init(Cipher.DECRYPT_MODE,sKeySpec,algParam);
451: IvParameterSpec ivClass = new IvParameterSpec(iv);
452: cipher2.init(Cipher.DECRYPT_MODE,sKeySpec,ivClass);
453: byte[] decrypted = cipher2.doFinal(encrypted);
454:
455: if (byteArrayIdentical(original,decrypted,0,original.length))
456: System.out.println("PASSED");
457: else
458: System.out.println("FAILED");
459:
460: System.out.println("original length is " + original.length);
461: System.out.println("encrypted length is " + encrypted.length);
462: System.out.println("decrypted length is " + decrypted.length);
463: }
464: catch (Throwable t)
465: {
466: System.out.println("got an exception");
467: t.printStackTrace();
468: }
469:
470: System.out.println("Finished testPCBC");
471: }
472:
473:
474: private void testPCBC2()
475: {
476: System.out.println("Running testPCBC2");
477: try
478: {
479: // set up the provider
480: Class jceClass = Class.forName("com.sun.crypto.provider.SunJCE");
481: java.security.Provider myProvider = (java.security.Provider) jceClass.newInstance();
482: java.security.Security.addProvider(myProvider);
483:
484: byte[] userkey = "a secreta secreta secret".getBytes();
485: System.out.println("userkey length is " + userkey.length);
486: Key secretKey = (Key) (new SecretKeySpec(userkey, "DESede"));
487: byte[] IV = "anivspec".getBytes();
488:
489: Cipher enCipher = Cipher.getInstance("DESede/PCBC/NoPadding","SunJCE");
490: Cipher deCipher = Cipher.getInstance("DESede/PCBC/NoPadding","SunJCE");
491: IvParameterSpec ivspec = new IvParameterSpec(IV);
492:
493: enCipher.init(Cipher.ENCRYPT_MODE,secretKey,ivspec);
494: deCipher.init(Cipher.DECRYPT_MODE,secretKey,ivspec);
495:
496: int patternLength = 24;
497: byte[] pattern = new byte[patternLength];
498: for (int i = 0; i < patternLength; i++)
499: pattern[i] = (byte)(i & 0xFF);
500:
501: byte[] cipherOutput1 = new byte[patternLength];
502: byte[] cipherOutput2 = new byte[patternLength];
503:
504: int retval = 0;
505: retval = enCipher.doFinal(pattern, 0, 24, cipherOutput1, 0);
506:
507: retval = deCipher.doFinal(cipherOutput1, 0, 24, cipherOutput2, 0);
508:
509: if (byteArrayIdentical(cipherOutput2,pattern,0,patternLength))
510: System.out.println("PASSED TEST 1");
511: else
512: System.out.println("FAILED TEST 1");
513:
514: retval = deCipher.doFinal(cipherOutput1, 0, 24, cipherOutput2, 0);
515:
516: if (byteArrayIdentical(cipherOutput2,pattern,0,patternLength))
517: System.out.println("PASSED TEST 2");
518: else
519: System.out.println("FAILED TEST 2");
520: }
521: catch (Throwable t)
522: {
523: System.out.println("got an exception");
524: t.printStackTrace();
525: }
526:
527: System.out.println("Finished testPCBC2");
528: }
529:
530: private void testIAIK()
531: {
532: System.out.println("Running testIAIK");
533: try
534: {
535: // set up the provider
536: Class jceClass = Class.forName("iaik.security.provider.IAIK");
537: java.security.Provider myProvider = (java.security.Provider) jceClass.newInstance();
538: java.security.Security.addProvider(myProvider);
539:
540: // iaik.security.provider.IAIK.addAsProvider(true);
541:
542: // iaik.utils.Util.loadClass("iaik.security.provider.IAIK",true);
543: // IAIK p=new IAIK();
544: // iaik.security.provider.IAIK.getMd5();
545:
546: byte[] userkey = "a secret".getBytes();
547: System.out.println("userkey length is " + userkey.length);
548: Key secretKey = (Key) (new SecretKeySpec(userkey, "DES"));
549: byte[] IV = "anivspec".getBytes();
550:
551: Cipher enCipher = Cipher.getInstance("DES/CBC/NoPadding","IAIK");
552: Cipher deCipher = Cipher.getInstance("DES/CBC/NoPadding","IAIK");
553: IvParameterSpec ivspec = new IvParameterSpec(IV);
554:
555: enCipher.init(Cipher.ENCRYPT_MODE,secretKey,ivspec);
556: deCipher.init(Cipher.DECRYPT_MODE,secretKey,ivspec);
557:
558: int patternLength = 8;
559: byte[] pattern = new byte[patternLength];
560: for (int i = 0; i < patternLength; i++)
561: pattern[i] = (byte)(i & 0xFF);
562:
563: byte[] cipherOutput1 = new byte[patternLength];
564: byte[] cipherOutput2 = new byte[patternLength];
565:
566: int retval = 0;
567: retval = enCipher.doFinal(pattern, 0, 8, cipherOutput1, 0);
568:
569: retval = deCipher.doFinal(cipherOutput1, 0, 8, cipherOutput2, 0);
570:
571: if (byteArrayIdentical(cipherOutput2,pattern,0,patternLength))
572: System.out.println("PASSED TEST 1");
573: else
574: System.out.println("FAILED TEST 1");
575:
576: retval = deCipher.doFinal(cipherOutput1, 0, 8, cipherOutput2, 0);
577:
578: if (byteArrayIdentical(cipherOutput2,pattern,0,patternLength))
579: System.out.println("PASSED TEST 2");
580: else
581: System.out.println("FAILED TEST 2");
582: }
583: catch (Throwable t)
584: {
585: System.out.println("got an exception");
586: t.printStackTrace();
587: }
588:
589: System.out.println("Finished testIAIK");
590: }
591:
592: private void printByteArray(String name, byte[] array)
593: {
594: System.out.println("printing array " + name);
595: for (int i = 0; i < array.length; i++)
596: System.out.println("index " + i + " : " + array[i]);
597: }
598: */
599:
600: /**
601: * Delete a file in a Privileged block as these tests are
602: * run under the embedded engine code.
603: */
604: private void deleteFile(final File f) {
605: AccessController.doPrivileged(new PrivilegedAction() {
606: public Object run() {
607: if (f.exists())
608: f.delete();
609: return null;
610: }
611: });
612: }
613: }
|