001: package org.bouncycastle.crypto.test;
002:
003: import java.math.BigInteger;
004: import java.security.SecureRandom;
005: import java.util.Vector;
006:
007: import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
008: import org.bouncycastle.crypto.InvalidCipherTextException;
009: import org.bouncycastle.crypto.engines.NaccacheSternEngine;
010: import org.bouncycastle.crypto.generators.NaccacheSternKeyPairGenerator;
011: import org.bouncycastle.crypto.params.NaccacheSternKeyGenerationParameters;
012: import org.bouncycastle.crypto.params.NaccacheSternKeyParameters;
013: import org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters;
014: import org.bouncycastle.util.encoders.Hex;
015: import org.bouncycastle.util.test.SimpleTest;
016:
017: /**
018: * Test case for NaccacheStern cipher. For details on this cipher, please see
019: *
020: * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
021: *
022: * Performs the following tests:
023: * <ul>
024: * <li> Toy example from the NaccacheSternPaper </li>
025: * <li> 768 bit test with text "Now is the time for all good men." (ripped from RSA test) and
026: * the same test with the first byte replaced by 0xFF </li>
027: * <li> 1024 bit test analog to 768 bit test </li>
028: * </ul>
029: */
030: public class NaccacheSternTest extends SimpleTest {
031: static final boolean debug = false;
032:
033: static final NaccacheSternEngine cryptEng = new NaccacheSternEngine();
034:
035: static final NaccacheSternEngine decryptEng = new NaccacheSternEngine();
036:
037: static {
038: cryptEng.setDebug(debug);
039: decryptEng.setDebug(debug);
040: }
041:
042: // Values from NaccacheStern paper
043: static final BigInteger a = BigInteger.valueOf(101);
044:
045: static final BigInteger u1 = BigInteger.valueOf(3);
046:
047: static final BigInteger u2 = BigInteger.valueOf(5);
048:
049: static final BigInteger u3 = BigInteger.valueOf(7);
050:
051: static final BigInteger b = BigInteger.valueOf(191);
052:
053: static final BigInteger v1 = BigInteger.valueOf(11);
054:
055: static final BigInteger v2 = BigInteger.valueOf(13);
056:
057: static final BigInteger v3 = BigInteger.valueOf(17);
058:
059: static final BigInteger ONE = BigInteger.valueOf(1);
060:
061: static final BigInteger TWO = BigInteger.valueOf(2);
062:
063: static final BigInteger sigma = u1.multiply(u2).multiply(u3)
064: .multiply(v1).multiply(v2).multiply(v3);
065:
066: static final BigInteger p = TWO.multiply(a).multiply(u1).multiply(
067: u2).multiply(u3).add(ONE);
068:
069: static final BigInteger q = TWO.multiply(b).multiply(v1).multiply(
070: v2).multiply(v3).add(ONE);
071:
072: static final BigInteger n = p.multiply(q);
073:
074: static final BigInteger phi_n = p.subtract(ONE).multiply(
075: q.subtract(ONE));
076:
077: static final BigInteger g = BigInteger.valueOf(131);
078:
079: static final Vector smallPrimes = new Vector();
080:
081: // static final BigInteger paperTest = BigInteger.valueOf(202);
082:
083: static final String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
084:
085: static final BigInteger paperTest = BigInteger.valueOf(202);
086:
087: //
088: // to check that we handling byte extension by big number correctly.
089: //
090: static final String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
091:
092: public String getName() {
093: return "NaccacheStern";
094: }
095:
096: public void performTest() {
097: // Test with given key from NaccacheSternPaper (totally insecure)
098:
099: // First the Parameters from the NaccacheStern Paper
100: // (see http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf )
101:
102: smallPrimes.addElement(u1);
103: smallPrimes.addElement(u2);
104: smallPrimes.addElement(u3);
105: smallPrimes.addElement(v1);
106: smallPrimes.addElement(v2);
107: smallPrimes.addElement(v3);
108:
109: NaccacheSternKeyParameters pubParameters = new NaccacheSternKeyParameters(
110: false, g, n, sigma.bitLength());
111:
112: NaccacheSternPrivateKeyParameters privParameters = new NaccacheSternPrivateKeyParameters(
113: g, n, sigma.bitLength(), smallPrimes, phi_n);
114:
115: AsymmetricCipherKeyPair pair = new AsymmetricCipherKeyPair(
116: pubParameters, privParameters);
117:
118: // Initialize Engines with KeyPair
119:
120: if (debug) {
121: System.out.println("initializing encryption engine");
122: }
123: cryptEng.init(true, pair.getPublic());
124:
125: if (debug) {
126: System.out.println("initializing decryption engine");
127: }
128: decryptEng.init(false, pair.getPrivate());
129:
130: byte[] data = paperTest.toByteArray();
131:
132: if (!new BigInteger(data)
133: .equals(new BigInteger(enDeCrypt(data)))) {
134: fail("failed NaccacheStern paper test");
135: }
136:
137: //
138: // key generation test
139: //
140:
141: //
142: // 768 Bit test
143: //
144:
145: if (debug) {
146: System.out.println();
147: System.out.println("768 Bit TEST");
148: }
149:
150: // specify key generation parameters
151: NaccacheSternKeyGenerationParameters genParam = new NaccacheSternKeyGenerationParameters(
152: new SecureRandom(), 768, 8, 30, debug);
153:
154: // Initialize Key generator and generate key pair
155: NaccacheSternKeyPairGenerator pGen = new NaccacheSternKeyPairGenerator();
156: pGen.init(genParam);
157:
158: pair = pGen.generateKeyPair();
159:
160: if (((NaccacheSternKeyParameters) pair.getPublic())
161: .getModulus().bitLength() < 768) {
162: System.out.println("FAILED: key size is <786 bit, exactly "
163: + ((NaccacheSternKeyParameters) pair.getPublic())
164: .getModulus().bitLength() + " bit");
165: fail("failed key generation (768) length test");
166: }
167:
168: // Initialize Engines with KeyPair
169:
170: if (debug) {
171: System.out.println("initializing " + genParam.getStrength()
172: + " bit encryption engine");
173: }
174: cryptEng.init(true, pair.getPublic());
175:
176: if (debug) {
177: System.out.println("initializing " + genParam.getStrength()
178: + " bit decryption engine");
179: }
180: decryptEng.init(false, pair.getPrivate());
181:
182: // Basic data input
183: data = Hex.decode(input);
184:
185: if (!new BigInteger(1, data).equals(new BigInteger(1,
186: enDeCrypt(data)))) {
187: fail("failed encryption decryption ("
188: + genParam.getStrength() + ") basic test");
189: }
190:
191: // Data starting with FF byte (would be interpreted as negative
192: // BigInteger)
193:
194: data = Hex.decode(edgeInput);
195:
196: if (!new BigInteger(1, data).equals(new BigInteger(1,
197: enDeCrypt(data)))) {
198: fail("failed encryption decryption ("
199: + genParam.getStrength() + ") edgeInput test");
200: }
201:
202: //
203: // 1024 Bit Test
204: //
205: /*
206: if (debug)
207: {
208: System.out.println();
209: System.out.println("1024 Bit TEST");
210: }
211:
212: // specify key generation parameters
213: genParam = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 1024, 8, 40);
214:
215: pGen.init(genParam);
216: pair = pGen.generateKeyPair();
217:
218: if (((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
219: {
220: if (debug)
221: {
222: System.out.println("FAILED: key size is <1024 bit, exactly "
223: + ((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() + " bit");
224: }
225: fail("failed key generation (1024) length test");
226: }
227:
228: // Initialize Engines with KeyPair
229:
230: if (debug)
231: {
232: System.out.println("initializing " + genParam.getStrength() + " bit encryption engine");
233: }
234: cryptEng.init(true, pair.getPublic());
235:
236: if (debug)
237: {
238: System.out.println("initializing " + genParam.getStrength() + " bit decryption engine");
239: }
240: decryptEng.init(false, pair.getPrivate());
241:
242: if (debug)
243: {
244: System.out.println("Data is " + new BigInteger(1, data));
245: }
246:
247: // Basic data input
248: data = Hex.decode(input);
249:
250: if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
251: {
252: fail("failed encryption decryption (" + genParam.getStrength() + ") basic test");
253: }
254:
255: // Data starting with FF byte (would be interpreted as negative
256: // BigInteger)
257:
258: data = Hex.decode(edgeInput);
259:
260: if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
261: {
262: fail("failed encryption decryption (" + genParam.getStrength() + ") edgeInput test");
263: }
264: */
265: // END OF TEST CASE
266: try {
267: new NaccacheSternEngine().processBlock(new byte[] { 1 }, 0,
268: 1);
269: fail("failed initialisation check");
270: } catch (IllegalStateException e) {
271: // expected
272: } catch (InvalidCipherTextException e) {
273: fail("failed initialisation check");
274: }
275:
276: if (debug) {
277: System.out.println("All tests successful");
278: }
279: }
280:
281: private byte[] enDeCrypt(byte[] input) {
282:
283: // create work array
284: byte[] data = new byte[input.length];
285: System.arraycopy(input, 0, data, 0, data.length);
286:
287: // Perform encryption like in the paper from Naccache-Stern
288: if (debug) {
289: System.out.println("encrypting data. Data representation\n"
290: // + "As String:.... " + new String(data) + "\n"
291: + "As BigInteger: " + new BigInteger(1, data));
292: System.out.println("data length is " + data.length);
293: }
294:
295: try {
296: data = cryptEng.processData(data);
297: } catch (InvalidCipherTextException e) {
298: if (debug) {
299: System.out.println("failed - exception " + e.toString()
300: + "\n" + e.getMessage());
301: }
302: fail("failed - exception " + e.toString() + "\n"
303: + e.getMessage());
304: }
305:
306: if (debug) {
307: System.out.println("enrypted data representation\n"
308: // + "As String:.... " + new String(data) + "\n"
309: + "As BigInteger: " + new BigInteger(1, data));
310: System.out.println("data length is " + data.length);
311: }
312:
313: try {
314: data = decryptEng.processData(data);
315: } catch (InvalidCipherTextException e) {
316: if (debug) {
317: System.out.println("failed - exception " + e.toString()
318: + "\n" + e.getMessage());
319: }
320: fail("failed - exception " + e.toString() + "\n"
321: + e.getMessage());
322: }
323:
324: if (debug) {
325: System.out.println("decrypted data representation\n"
326: // + "As String:.... " + new String(data) + "\n"
327: + "As BigInteger: " + new BigInteger(1, data));
328: System.out.println("data length is " + data.length);
329: }
330:
331: return data;
332:
333: }
334:
335: public static void main(String[] args) {
336: runTest(new NaccacheSternTest());
337: }
338: }
|