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.InvalidAlgorithmParameterException;
008: import java.security.Key;
009: import java.security.KeyException;
010: import java.security.Security;
011:
012: import javax.crypto.Cipher;
013: import javax.crypto.CipherInputStream;
014: import javax.crypto.CipherOutputStream;
015: import javax.crypto.spec.IvParameterSpec;
016: import javax.crypto.spec.SecretKeySpec;
017:
018: import org.bouncycastle.jce.provider.BouncyCastleProvider;
019: import org.bouncycastle.util.encoders.Hex;
020: import org.bouncycastle.util.test.SimpleTestResult;
021: import org.bouncycastle.util.test.Test;
022: import org.bouncycastle.util.test.TestResult;
023:
024: /**
025: * basic FIPS test class for a block cipher, just to make sure ECB/CBC/OFB/CFB are behaving
026: * correctly. Tests from <a href=http://www.itl.nist.gov/fipspubs/fip81.htm>FIPS 81</a>.
027: */
028: public class FIPSDESTest implements Test {
029: static String[] fips1Tests = { "DES/ECB/NoPadding",
030: "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53",
031: "DES/CBC/NoPadding",
032: "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6",
033: "DES/CFB/NoPadding",
034: "f3096249c7f46e51a69e839b1a92f78403467133898ea622" };
035:
036: static String[] fips2Tests = { "DES/CFB8/NoPadding",
037: "f31fda07011462ee187f", "DES/OFB8/NoPadding",
038: "f34a2850c9c64985d684" };
039:
040: static byte[] input1 = Hex
041: .decode("4e6f77206973207468652074696d6520666f7220616c6c20");
042: static byte[] input2 = Hex.decode("4e6f7720697320746865");
043:
044: public String getName() {
045: return "FIPSDESTest";
046: }
047:
048: private boolean equalArray(byte[] a, byte[] b) {
049: if (a.length != b.length) {
050: return false;
051: }
052:
053: for (int i = 0; i != a.length; i++) {
054: if (a[i] != b[i]) {
055: return false;
056: }
057: }
058:
059: return true;
060: }
061:
062: public TestResult test(String algorithm, byte[] input, byte[] output) {
063: Key key;
064: Cipher in, out;
065: CipherInputStream cIn;
066: CipherOutputStream cOut;
067: ByteArrayInputStream bIn;
068: ByteArrayOutputStream bOut;
069: IvParameterSpec spec = new IvParameterSpec(Hex
070: .decode("1234567890abcdef"));
071:
072: try {
073: String baseAlgorithm;
074:
075: key = new SecretKeySpec(Hex.decode("0123456789abcdef"),
076: "DES");
077:
078: in = Cipher.getInstance(algorithm, "BC");
079: out = Cipher.getInstance(algorithm, "BC");
080:
081: if (algorithm.startsWith("DES/ECB")) {
082: out.init(Cipher.ENCRYPT_MODE, key);
083: } else {
084: out.init(Cipher.ENCRYPT_MODE, key, spec);
085: }
086: } catch (Exception e) {
087: return new SimpleTestResult(false, getName() + ": "
088: + algorithm + " failed initialisation - "
089: + e.toString(), e);
090: }
091:
092: try {
093: if (algorithm.startsWith("DES/ECB")) {
094: in.init(Cipher.DECRYPT_MODE, key);
095: } else {
096: in.init(Cipher.DECRYPT_MODE, key, spec);
097: }
098: } catch (Exception e) {
099: return new SimpleTestResult(false, getName() + ": "
100: + algorithm + " failed initialisation - "
101: + e.toString(), e);
102: }
103:
104: //
105: // encryption pass
106: //
107: bOut = new ByteArrayOutputStream();
108:
109: cOut = new CipherOutputStream(bOut, out);
110:
111: try {
112: for (int i = 0; i != input.length / 2; i++) {
113: cOut.write(input[i]);
114: }
115: cOut.write(input, input.length / 2, input.length
116: - input.length / 2);
117: cOut.close();
118: } catch (IOException e) {
119: return new SimpleTestResult(false, getName() + ": "
120: + algorithm + " failed encryption - "
121: + e.toString());
122: }
123:
124: byte[] bytes;
125:
126: bytes = bOut.toByteArray();
127:
128: if (!equalArray(bytes, output)) {
129: return new SimpleTestResult(false, getName() + ": "
130: + algorithm + " failed encryption - expected "
131: + new String(Hex.encode(output)) + " got "
132: + new String(Hex.encode(bytes)));
133: }
134:
135: //
136: // decryption pass
137: //
138: bIn = new ByteArrayInputStream(bytes);
139:
140: cIn = new CipherInputStream(bIn, in);
141:
142: try {
143: DataInputStream dIn = new DataInputStream(cIn);
144:
145: bytes = new byte[input.length];
146:
147: for (int i = 0; i != input.length / 2; i++) {
148: bytes[i] = (byte) dIn.read();
149: }
150: dIn.readFully(bytes, input.length / 2, bytes.length
151: - input.length / 2);
152: } catch (Exception e) {
153: return new SimpleTestResult(false, getName() + ": "
154: + algorithm + " failed encryption - "
155: + e.toString());
156: }
157:
158: if (!equalArray(bytes, input)) {
159: return new SimpleTestResult(false, getName() + ": "
160: + algorithm + " failed decryption - expected "
161: + new String(Hex.encode(input)) + " got "
162: + new String(Hex.encode(bytes)));
163: }
164:
165: return new SimpleTestResult(true, getName() + ": " + algorithm
166: + " Okay");
167: }
168:
169: public TestResult perform() {
170: for (int i = 0; i != fips1Tests.length; i += 2) {
171: TestResult result;
172:
173: result = test(fips1Tests[i], input1, Hex
174: .decode(fips1Tests[i + 1]));
175: if (!result.isSuccessful()) {
176: return result;
177: }
178: }
179:
180: for (int i = 0; i != fips2Tests.length; i += 2) {
181: TestResult result;
182:
183: result = test(fips2Tests[i], input2, Hex
184: .decode(fips2Tests[i + 1]));
185: if (!result.isSuccessful()) {
186: return result;
187: }
188: }
189:
190: return new SimpleTestResult(true, getName() + ": Okay");
191: }
192:
193: public static void main(String[] args) throws KeyException,
194: InvalidAlgorithmParameterException {
195: Security.addProvider(new BouncyCastleProvider());
196:
197: Test test = new FIPSDESTest();
198: TestResult result = test.perform();
199:
200: System.out.println(result.toString());
201: }
202: }
|