001: package org.bouncycastle.crypto.test;
002:
003: import java.math.BigInteger;
004: import java.security.SecureRandom;
005:
006: import org.bouncycastle.crypto.AsymmetricBlockCipher;
007: import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
008: import org.bouncycastle.crypto.InvalidCipherTextException;
009: import org.bouncycastle.crypto.encodings.OAEPEncoding;
010: import org.bouncycastle.crypto.encodings.PKCS1Encoding;
011: import org.bouncycastle.crypto.engines.RSAEngine;
012: import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
013: import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
014: import org.bouncycastle.crypto.params.RSAKeyParameters;
015: import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
016: import org.bouncycastle.util.encoders.Hex;
017: import org.bouncycastle.util.test.SimpleTest;
018:
019: public class RSATest extends SimpleTest {
020: static BigInteger mod = new BigInteger(
021: "b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5",
022: 16);
023: static BigInteger pubExp = new BigInteger("11", 16);
024: static BigInteger privExp = new BigInteger(
025: "92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619",
026: 16);
027: static BigInteger p = new BigInteger(
028: "f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03",
029: 16);
030: static BigInteger q = new BigInteger(
031: "b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947",
032: 16);
033: static BigInteger pExp = new BigInteger(
034: "1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5",
035: 16);
036: static BigInteger qExp = new BigInteger(
037: "6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded",
038: 16);
039: static BigInteger crtCoef = new BigInteger(
040: "dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339",
041: 16);
042:
043: static String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
044:
045: //
046: // to check that we handling byte extension by big number correctly.
047: //
048: static String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
049:
050: static byte[] oversizedSig = Hex
051: .decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
052: static byte[] dudBlock = Hex
053: .decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
054: static byte[] truncatedDataBlock = Hex
055: .decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
056: static byte[] incorrectPadding = Hex
057: .decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
058: static byte[] missingDataBlock = Hex
059: .decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
060:
061: public String getName() {
062: return "RSA";
063: }
064:
065: private void testStrictPKCS1Length(RSAKeyParameters pubParameters,
066: RSAKeyParameters privParameters) {
067: AsymmetricBlockCipher eng = new RSAEngine();
068:
069: eng.init(true, privParameters);
070:
071: byte[] data = null;
072:
073: try {
074: data = eng.processBlock(oversizedSig, 0,
075: oversizedSig.length);
076: } catch (Exception e) {
077: fail("RSA: failed - exception " + e.toString(), e);
078: }
079:
080: eng = new PKCS1Encoding(eng);
081:
082: eng.init(false, pubParameters);
083:
084: try {
085: data = eng.processBlock(data, 0, data.length);
086:
087: fail("oversized signature block not recognised");
088: } catch (InvalidCipherTextException e) {
089: if (!e.getMessage().equals("block incorrect size")) {
090: fail("RSA: failed - exception " + e.toString(), e);
091: }
092: }
093:
094: //System.setProperty(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
095:
096: System.getProperties().put(
097: PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
098: eng = new PKCS1Encoding(new RSAEngine());
099:
100: eng.init(false, pubParameters);
101:
102: try {
103: data = eng.processBlock(data, 0, data.length);
104: } catch (InvalidCipherTextException e) {
105: fail("RSA: failed - exception " + e.toString(), e);
106: }
107:
108: System.getProperties().remove(
109: PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY);
110: }
111:
112: private void testTruncatedPKCS1Block(
113: RSAKeyParameters pubParameters,
114: RSAKeyParameters privParameters) {
115: checkForPKCS1Exception(pubParameters, privParameters,
116: truncatedDataBlock, "block truncated");
117: }
118:
119: private void testDudPKCS1Block(RSAKeyParameters pubParameters,
120: RSAKeyParameters privParameters) {
121: checkForPKCS1Exception(pubParameters, privParameters, dudBlock,
122: "unknown block type");
123: }
124:
125: private void testWrongPaddingPKCS1Block(
126: RSAKeyParameters pubParameters,
127: RSAKeyParameters privParameters) {
128: checkForPKCS1Exception(pubParameters, privParameters,
129: incorrectPadding, "block padding incorrect");
130: }
131:
132: private void testMissingDataPKCS1Block(
133: RSAKeyParameters pubParameters,
134: RSAKeyParameters privParameters) {
135: checkForPKCS1Exception(pubParameters, privParameters,
136: missingDataBlock, "no data in block");
137: }
138:
139: private void checkForPKCS1Exception(RSAKeyParameters pubParameters,
140: RSAKeyParameters privParameters, byte[] inputData,
141: String expectedMessage) {
142: AsymmetricBlockCipher eng = new RSAEngine();
143:
144: eng.init(true, privParameters);
145:
146: byte[] data = null;
147:
148: try {
149: data = eng.processBlock(inputData, 0, inputData.length);
150: } catch (Exception e) {
151: fail("RSA: failed - exception " + e.toString(), e);
152: }
153:
154: eng = new PKCS1Encoding(eng);
155:
156: eng.init(false, pubParameters);
157:
158: try {
159: data = eng.processBlock(data, 0, data.length);
160:
161: fail("missing data block not recognised");
162: } catch (InvalidCipherTextException e) {
163: if (!e.getMessage().equals(expectedMessage)) {
164: fail("RSA: failed - exception " + e.toString(), e);
165: }
166: }
167: }
168:
169: private void testOAEP(RSAKeyParameters pubParameters,
170: RSAKeyParameters privParameters) {
171: //
172: // OAEP - public encrypt, private decrypt
173: //
174: AsymmetricBlockCipher eng = new OAEPEncoding(new RSAEngine());
175: byte[] data = Hex.decode(input);
176:
177: eng.init(true, pubParameters);
178:
179: try {
180: data = eng.processBlock(data, 0, data.length);
181: } catch (Exception e) {
182: fail("failed - exception " + e.toString(), e);
183: }
184:
185: eng.init(false, privParameters);
186:
187: try {
188: data = eng.processBlock(data, 0, data.length);
189: } catch (Exception e) {
190: fail("failed - exception " + e.toString(), e);
191: }
192:
193: if (!input.equals(new String(Hex.encode(data)))) {
194: fail("failed OAEP Test");
195: }
196: }
197:
198: public void performTest() {
199: RSAKeyParameters pubParameters = new RSAKeyParameters(false,
200: mod, pubExp);
201: RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(
202: mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
203: byte[] data = Hex.decode(edgeInput);
204:
205: //
206: // RAW
207: //
208: AsymmetricBlockCipher eng = new RSAEngine();
209:
210: eng.init(true, pubParameters);
211:
212: try {
213: data = eng.processBlock(data, 0, data.length);
214: } catch (Exception e) {
215: fail("RSA: failed - exception " + e.toString(), e);
216: }
217:
218: eng.init(false, privParameters);
219:
220: try {
221: data = eng.processBlock(data, 0, data.length);
222: } catch (Exception e) {
223: fail("failed - exception " + e.toString(), e);
224: }
225:
226: if (!edgeInput.equals(new String(Hex.encode(data)))) {
227: fail("failed RAW edge Test");
228: }
229:
230: data = Hex.decode(input);
231:
232: eng.init(true, pubParameters);
233:
234: try {
235: data = eng.processBlock(data, 0, data.length);
236: } catch (Exception e) {
237: fail("failed - exception " + e.toString(), e);
238: }
239:
240: eng.init(false, privParameters);
241:
242: try {
243: data = eng.processBlock(data, 0, data.length);
244: } catch (Exception e) {
245: fail("failed - exception " + e.toString(), e);
246: }
247:
248: if (!input.equals(new String(Hex.encode(data)))) {
249: fail("failed RAW Test");
250: }
251:
252: //
253: // PKCS1 - public encrypt, private decrypt
254: //
255: eng = new PKCS1Encoding(eng);
256:
257: eng.init(true, pubParameters);
258:
259: if (eng.getOutputBlockSize() != ((PKCS1Encoding) eng)
260: .getUnderlyingCipher().getOutputBlockSize()) {
261: fail("PKCS1 output block size incorrect");
262: }
263:
264: try {
265: data = eng.processBlock(data, 0, data.length);
266: } catch (Exception e) {
267: fail("failed - exception " + e.toString(), e);
268: }
269:
270: eng.init(false, privParameters);
271:
272: try {
273: data = eng.processBlock(data, 0, data.length);
274: } catch (Exception e) {
275: fail("failed - exception " + e.toString(), e);
276: }
277:
278: if (!input.equals(new String(Hex.encode(data)))) {
279: fail("failed PKCS1 public/private Test");
280: }
281:
282: //
283: // PKCS1 - private encrypt, public decrypt
284: //
285: eng = new PKCS1Encoding(((PKCS1Encoding) eng)
286: .getUnderlyingCipher());
287:
288: eng.init(true, privParameters);
289:
290: try {
291: data = eng.processBlock(data, 0, data.length);
292: } catch (Exception e) {
293: fail("failed - exception " + e.toString(), e);
294: }
295:
296: eng.init(false, pubParameters);
297:
298: try {
299: data = eng.processBlock(data, 0, data.length);
300: } catch (Exception e) {
301: fail("failed - exception " + e.toString(), e);
302: }
303:
304: if (!input.equals(new String(Hex.encode(data)))) {
305: fail("failed PKCS1 private/public Test");
306: }
307:
308: //
309: // key generation test
310: //
311: RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
312: RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
313: BigInteger.valueOf(0x11), new SecureRandom(), 768, 25);
314:
315: pGen.init(genParam);
316:
317: AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
318:
319: eng = new RSAEngine();
320:
321: if (((RSAKeyParameters) pair.getPublic()).getModulus()
322: .bitLength() < 768) {
323: fail("failed key generation (768) length test");
324: }
325:
326: eng.init(true, pair.getPublic());
327:
328: try {
329: data = eng.processBlock(data, 0, data.length);
330: } catch (Exception e) {
331: fail("failed - exception " + e.toString(), e);
332: }
333:
334: eng.init(false, pair.getPrivate());
335:
336: try {
337: data = eng.processBlock(data, 0, data.length);
338: } catch (Exception e) {
339: fail("failed - exception " + e.toString(), e);
340: }
341:
342: if (!input.equals(new String(Hex.encode(data)))) {
343: fail("failed key generation (768) Test");
344: }
345:
346: genParam = new RSAKeyGenerationParameters(BigInteger
347: .valueOf(0x11), new SecureRandom(), 1024, 25);
348:
349: pGen.init(genParam);
350: pair = pGen.generateKeyPair();
351:
352: eng.init(true, pair.getPublic());
353:
354: if (((RSAKeyParameters) pair.getPublic()).getModulus()
355: .bitLength() < 1024) {
356: fail("failed key generation (1024) length test");
357: }
358:
359: try {
360: data = eng.processBlock(data, 0, data.length);
361: } catch (Exception e) {
362: fail("failed - exception " + e.toString(), e);
363: }
364:
365: eng.init(false, pair.getPrivate());
366:
367: try {
368: data = eng.processBlock(data, 0, data.length);
369: } catch (Exception e) {
370: fail("failed - exception " + e.toString(), e);
371: }
372:
373: if (!input.equals(new String(Hex.encode(data)))) {
374: fail("failed key generation (1024) test");
375: }
376:
377: testOAEP(pubParameters, privParameters);
378: testStrictPKCS1Length(pubParameters, privParameters);
379: testDudPKCS1Block(pubParameters, privParameters);
380: testMissingDataPKCS1Block(pubParameters, privParameters);
381: testTruncatedPKCS1Block(pubParameters, privParameters);
382: testWrongPaddingPKCS1Block(pubParameters, privParameters);
383:
384: try {
385: new RSAEngine().processBlock(new byte[] { 1 }, 0, 1);
386: fail("failed initialisation check");
387: } catch (IllegalStateException e) {
388: // expected
389: }
390: }
391:
392: public static void main(String[] args) {
393: runTest(new RSATest());
394: }
395: }
|