001: package org.bouncycastle.crypto.test;
002:
003: import org.bouncycastle.crypto.BlockCipher;
004: import org.bouncycastle.crypto.InvalidCipherTextException;
005: import org.bouncycastle.crypto.Wrapper;
006: import org.bouncycastle.crypto.engines.DESEngine;
007: import org.bouncycastle.crypto.engines.DESedeEngine;
008: import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
009: import org.bouncycastle.crypto.modes.CBCBlockCipher;
010: import org.bouncycastle.crypto.params.KeyParameter;
011: import org.bouncycastle.crypto.params.ParametersWithIV;
012: import org.bouncycastle.crypto.params.ParametersWithRandom;
013: import org.bouncycastle.util.Arrays;
014: import org.bouncycastle.util.encoders.Hex;
015: import org.bouncycastle.util.test.SimpleTest;
016:
017: import java.security.SecureRandom;
018:
019: /**
020: * Wrap Test based on RFC3211 test vectors
021: */
022: public class RFC3211WrapTest extends SimpleTest {
023: SecureRandom r1 = new SecureRandom() {
024: int[] ints = { 0xC4, 0x36, 0xF5, 0x41 };
025: int count = 0;
026:
027: public int nextInt() {
028: return ints[count++];
029: }
030: };
031:
032: SecureRandom r2 = new SecureRandom() {
033: int[] ints = { 0xFA, 0x06, 0x0A, 0x45 };
034: int count = 0;
035:
036: public int nextInt() {
037: return ints[count++];
038: }
039: };
040:
041: public String getName() {
042: return "RFC3211Wrap";
043: }
044:
045: private void wrapTest(int id, BlockCipher engine, byte[] kek,
046: byte[] iv, SecureRandom rand, byte[] in, byte[] out)
047: throws Exception {
048: Wrapper wrapper = new RFC3211WrapEngine(engine);
049:
050: wrapper.init(true, new ParametersWithRandom(
051: new ParametersWithIV(new KeyParameter(kek), iv), rand));
052:
053: byte[] cText = wrapper.wrap(in, 0, in.length);
054: if (!Arrays.areEqual(cText, out)) {
055: fail("failed wrap test " + id + " expected "
056: + new String(Hex.encode(out)) + " got "
057: + new String(Hex.encode(cText)));
058: }
059:
060: wrapper.init(false, new ParametersWithIV(new KeyParameter(kek),
061: iv));
062:
063: byte[] pText = wrapper.unwrap(out, 0, out.length);
064: if (!Arrays.areEqual(pText, in)) {
065: fail("rfailed unwrap test " + id + " expected "
066: + new String(Hex.encode(in)) + " got "
067: + new String(Hex.encode(pText)));
068: }
069: }
070:
071: private void testCorruption() throws InvalidCipherTextException {
072: byte[] kek = Hex.decode("D1DAA78615F287E6");
073: byte[] iv = Hex.decode("EFE598EF21B33D6D");
074:
075: Wrapper wrapper = new RFC3211WrapEngine(new DESEngine());
076:
077: wrapper.init(false, new ParametersWithIV(new KeyParameter(kek),
078: iv));
079:
080: byte[] block = Hex.decode("ff739D838C627C897323A2F8C436F541");
081: encryptBlock(kek, iv, block);
082:
083: try {
084: wrapper.unwrap(block, 0, block.length);
085:
086: fail("bad length not detected");
087: } catch (InvalidCipherTextException e) {
088: if (!e.getMessage().equals("wrapped key corrupted")) {
089: fail("wrong exception on length");
090: }
091: }
092:
093: block = Hex.decode("08639D838C627C897323A2F8C436F541");
094: testChecksum(kek, iv, block, wrapper);
095:
096: block = Hex.decode("08736D838C627C897323A2F8C436F541");
097: testChecksum(kek, iv, block, wrapper);
098:
099: block = Hex.decode("08739D638C627C897323A2F8C436F541");
100: testChecksum(kek, iv, block, wrapper);
101: }
102:
103: private void testChecksum(byte[] kek, byte[] iv, byte[] block,
104: Wrapper wrapper) {
105: encryptBlock(kek, iv, block);
106:
107: try {
108: wrapper.unwrap(block, 0, block.length);
109:
110: fail("bad checksum not detected");
111: } catch (InvalidCipherTextException e) {
112: if (!e.getMessage().equals("wrapped key fails checksum")) {
113: fail("wrong exception");
114: }
115: }
116: }
117:
118: private void encryptBlock(byte[] key, byte[] iv, byte[] cekBlock) {
119: BlockCipher engine = new CBCBlockCipher(new DESEngine());
120:
121: engine.init(true, new ParametersWithIV(new KeyParameter(key),
122: iv));
123:
124: for (int i = 0; i < cekBlock.length; i += 8) {
125: engine.processBlock(cekBlock, i, cekBlock, i);
126: }
127:
128: for (int i = 0; i < cekBlock.length; i += 8) {
129: engine.processBlock(cekBlock, i, cekBlock, i);
130: }
131: }
132:
133: public void performTest() throws Exception {
134: wrapTest(1, new DESEngine(), Hex.decode("D1DAA78615F287E6"),
135: Hex.decode("EFE598EF21B33D6D"), r1, Hex
136: .decode("8C627C897323A2F8"), Hex
137: .decode("B81B2565EE373CA6DEDCA26A178B0C10"));
138: wrapTest(
139: 2,
140: new DESedeEngine(),
141: Hex
142: .decode("6A8970BF68C92CAEA84A8DF28510858607126380CC47AB2D"),
143: Hex.decode("BAF1CA7931213C4E"),
144: r2,
145: Hex
146: .decode("8C637D887223A2F965B566EB014B0FA5D52300A3F7EA40FFFC577203C71BAF3B"),
147: Hex
148: .decode("C03C514ABDB9E2C5AAC038572B5E24553876B377AAFB82ECA5A9D73F8AB143D9EC74E6CAD7DB260C"));
149:
150: testCorruption();
151:
152: Wrapper wrapper = new RFC3211WrapEngine(new DESEngine());
153: ParametersWithIV params = new ParametersWithIV(
154: new KeyParameter(new byte[16]), new byte[16]);
155: byte[] buf = new byte[16];
156:
157: try {
158: wrapper.init(true, params);
159:
160: wrapper.unwrap(buf, 0, buf.length);
161:
162: fail("failed unwrap state test.");
163: } catch (IllegalStateException e) {
164: // expected
165: } catch (InvalidCipherTextException e) {
166: fail("unexpected exception: " + e, e);
167: }
168:
169: try {
170: wrapper.init(false, params);
171:
172: wrapper.wrap(buf, 0, buf.length);
173:
174: fail("failed unwrap state test.");
175: } catch (IllegalStateException e) {
176: // expected
177: }
178:
179: //
180: // short test
181: //
182: try {
183: wrapper.init(false, params);
184:
185: wrapper.unwrap(buf, 0, buf.length / 2);
186:
187: fail("failed unwrap short test.");
188: } catch (InvalidCipherTextException e) {
189: // expected
190: }
191: }
192:
193: public static void main(String[] args) {
194: runTest(new RFC3211WrapTest());
195: }
196: }
|