001: package org.bouncycastle.jce.provider.test;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.ByteArrayOutputStream;
005: import java.io.DataInputStream;
006: import java.io.IOException;
007: import java.security.Key;
008: import java.security.SecureRandom;
009: import java.security.Security;
010:
011: import javax.crypto.Cipher;
012: import javax.crypto.CipherInputStream;
013: import javax.crypto.CipherOutputStream;
014: import javax.crypto.KeyGenerator;
015: import javax.crypto.SecretKey;
016: import javax.crypto.SecretKeyFactory;
017: import javax.crypto.spec.DESedeKeySpec;
018: import javax.crypto.spec.IvParameterSpec;
019: import javax.crypto.spec.RC2ParameterSpec;
020: import javax.crypto.spec.RC5ParameterSpec;
021: import javax.crypto.spec.SecretKeySpec;
022:
023: import org.bouncycastle.jce.provider.BouncyCastleProvider;
024: import org.bouncycastle.util.encoders.Hex;
025: import org.bouncycastle.util.test.SimpleTest;
026:
027: /**
028: * basic test class for key generation for a DES-EDE block cipher, basically
029: * this just exercises the provider, and makes sure we are behaving sensibly,
030: * correctness of the implementation is shown in the lightweight test classes.
031: */
032: public class DESedeTest extends SimpleTest {
033: static String[] cipherTests1 = {
034: "112",
035: "2f4bc6b30c893fa549d82c560d61cf3eb088aed020603de249d82c560d61cf3e529e95ecd8e05394",
036: "128",
037: "2f4bc6b30c893fa549d82c560d61cf3eb088aed020603de249d82c560d61cf3e529e95ecd8e05394",
038: "168",
039: "50ddb583a25c21e6c9233f8e57a86d40bb034af421c03096c9233f8e57a86d402fce91e8eb639f89",
040: "192",
041: "50ddb583a25c21e6c9233f8e57a86d40bb034af421c03096c9233f8e57a86d402fce91e8eb639f89", };
042:
043: static byte[] input1 = Hex
044: .decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
045: static byte[] input2 = Hex
046: .decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c");
047:
048: static RC2ParameterSpec rc2Spec = new RC2ParameterSpec(128, Hex
049: .decode("0123456789abcdef"));
050: static RC5ParameterSpec rc5Spec = new RC5ParameterSpec(16, 16, 32,
051: Hex.decode("0123456789abcdef"));
052:
053: /**
054: * a fake random number generator - we just want to make sure the random numbers
055: * aren't random so that we get the same output, while still getting to test the
056: * key generation facilities.
057: */
058: private class FixedSecureRandom extends SecureRandom {
059: byte[] seed = { (byte) 0xaa, (byte) 0xfd, (byte) 0x12,
060: (byte) 0xf6, (byte) 0x59, (byte) 0xca, (byte) 0xe6,
061: (byte) 0x34, (byte) 0x89, (byte) 0xb4, (byte) 0x79,
062: (byte) 0xe5, (byte) 0x07, (byte) 0x6d, (byte) 0xde,
063: (byte) 0xc2, (byte) 0xf0, (byte) 0x6c, (byte) 0xb5,
064: (byte) 0x8f };
065:
066: public void nextBytes(byte[] bytes) {
067: int offset = 0;
068:
069: while ((offset + seed.length) < bytes.length) {
070: System.arraycopy(seed, 0, bytes, offset, seed.length);
071: offset += seed.length;
072: }
073:
074: System.arraycopy(seed, 0, bytes, offset, bytes.length
075: - offset);
076: }
077: }
078:
079: public String getName() {
080: return "DESEDE";
081: }
082:
083: private boolean equalArray(byte[] a, byte[] b) {
084: if (a.length != b.length) {
085: return false;
086: }
087:
088: for (int i = 0; i != a.length; i++) {
089: if (a[i] != b[i]) {
090: return false;
091: }
092: }
093:
094: return true;
095: }
096:
097: private boolean equalArray(byte[] a, byte[] b, int length) {
098: if (a.length < length) {
099: return false;
100: }
101:
102: if (b.length < length) {
103: return false;
104: }
105:
106: for (int i = 0; i != length; i++) {
107: if (a[i] != b[i]) {
108: return false;
109: }
110: }
111:
112: return true;
113: }
114:
115: private void wrapTest(int id, byte[] kek, byte[] iv, byte[] in,
116: byte[] out) {
117: try {
118: Cipher wrapper = Cipher.getInstance("DESedeWrap", "BC");
119:
120: wrapper.init(Cipher.WRAP_MODE, new SecretKeySpec(kek,
121: "DESEDE"), new IvParameterSpec(iv));
122:
123: try {
124: byte[] cText = wrapper.wrap(new SecretKeySpec(in,
125: "DESEDE"));
126: if (!equalArray(cText, out)) {
127: fail("failed wrap test " + id + " expected "
128: + new String(Hex.encode(out)) + " got "
129: + new String(Hex.encode(cText)));
130: }
131: } catch (Exception e) {
132: fail("failed wrap test exception " + e.toString());
133: }
134:
135: wrapper.init(Cipher.UNWRAP_MODE, new SecretKeySpec(kek,
136: "DESEDE"));
137:
138: try {
139: Key pText = wrapper.unwrap(out, "DESede",
140: Cipher.SECRET_KEY);
141: if (!equalArray(pText.getEncoded(), in)) {
142: fail("failed unwrap test "
143: + id
144: + " expected "
145: + new String(Hex.encode(in))
146: + " got "
147: + new String(Hex.encode(pText.getEncoded())));
148: }
149: } catch (Exception e) {
150: fail("failed unwrap test exception " + e.toString());
151: }
152: } catch (Exception ex) {
153: fail("failed exception " + ex.toString());
154: }
155: }
156:
157: public void test(int strength, byte[] input, byte[] output) {
158: Key key = null;
159: KeyGenerator keyGen;
160: SecureRandom rand;
161: Cipher in = null;
162: Cipher out = null;
163: CipherInputStream cIn;
164: CipherOutputStream cOut;
165: ByteArrayInputStream bIn;
166: ByteArrayOutputStream bOut;
167:
168: rand = new FixedSecureRandom();
169:
170: try {
171: keyGen = KeyGenerator.getInstance("DESEDE", "BC");
172: keyGen.init(strength, rand);
173:
174: key = keyGen.generateKey();
175:
176: in = Cipher.getInstance("DESEDE/ECB/PKCS7Padding", "BC");
177: out = Cipher.getInstance("DESEDE/ECB/PKCS7Padding", "BC");
178:
179: out.init(Cipher.ENCRYPT_MODE, key, rand);
180: } catch (Exception e) {
181: fail("DESEDE failed initialisation - " + e.toString());
182: }
183:
184: try {
185: in.init(Cipher.DECRYPT_MODE, key);
186: } catch (Exception e) {
187: fail("DESEDE failed initialisation - " + e.toString());
188: }
189:
190: //
191: // encryption pass
192: //
193: bOut = new ByteArrayOutputStream();
194:
195: cOut = new CipherOutputStream(bOut, out);
196:
197: try {
198: for (int i = 0; i != input.length / 2; i++) {
199: cOut.write(input[i]);
200: }
201: cOut.write(input, input.length / 2, input.length
202: - input.length / 2);
203: cOut.close();
204: } catch (IOException e) {
205: fail("DESEDE failed encryption - " + e.toString());
206: }
207:
208: byte[] bytes;
209:
210: bytes = bOut.toByteArray();
211:
212: if (!equalArray(bytes, output)) {
213: fail("DESEDE failed encryption - expected "
214: + new String(Hex.encode(output)) + " got "
215: + new String(Hex.encode(bytes)));
216: }
217:
218: //
219: // decryption pass
220: //
221: bIn = new ByteArrayInputStream(bytes);
222:
223: cIn = new CipherInputStream(bIn, in);
224:
225: try {
226: DataInputStream dIn = new DataInputStream(cIn);
227:
228: bytes = new byte[input.length];
229:
230: for (int i = 0; i != input.length / 2; i++) {
231: bytes[i] = (byte) dIn.read();
232: }
233: dIn.readFully(bytes, input.length / 2, bytes.length
234: - input.length / 2);
235: } catch (Exception e) {
236: fail("DESEDE failed encryption - " + e.toString());
237: }
238:
239: if (!equalArray(bytes, input)) {
240: fail("DESEDE failed decryption - expected "
241: + new String(Hex.encode(input)) + " got "
242: + new String(Hex.encode(bytes)));
243: }
244:
245: //
246: // keyspec test
247: //
248: try {
249: SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(
250: "DESede", "BC");
251: DESedeKeySpec keySpec = (DESedeKeySpec) keyFactory
252: .getKeySpec((SecretKey) key, DESedeKeySpec.class);
253:
254: if (!equalArray(key.getEncoded(), keySpec.getKey(), 16)) {
255: fail("DESEDE KeySpec does not match key.");
256: }
257: } catch (Exception e) {
258: fail("DESEDE failed keyspec - " + e.toString());
259: }
260: }
261:
262: public void performTest() {
263: for (int i = 0; i != cipherTests1.length; i += 2) {
264: test(Integer.parseInt(cipherTests1[i]), input1, Hex
265: .decode(cipherTests1[i + 1]));
266: }
267:
268: byte[] kek1 = Hex
269: .decode("255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f");
270: byte[] iv1 = Hex.decode("5dd4cbfc96f5453b");
271: byte[] in1 = Hex
272: .decode("2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98");
273: byte[] out1 = Hex
274: .decode("690107618ef092b3b48ca1796b234ae9fa33ebb4159604037db5d6a84eb3aac2768c632775a467d4");
275:
276: wrapTest(1, kek1, iv1, in1, out1);
277: }
278:
279: public static void main(String[] args) {
280: Security.addProvider(new BouncyCastleProvider());
281:
282: runTest(new DESedeTest());
283: }
284: }
|