001: package org.bouncycastle.crypto.test;
002:
003: import java.math.BigInteger;
004: import java.security.SecureRandom;
005:
006: import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
007: import org.bouncycastle.crypto.BasicAgreement;
008: import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
009: import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
010: import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
011: import org.bouncycastle.crypto.params.ECDomainParameters;
012: import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
013: import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
014: import org.bouncycastle.crypto.params.ECPublicKeyParameters;
015: import org.bouncycastle.crypto.params.ParametersWithRandom;
016: import org.bouncycastle.crypto.signers.ECDSASigner;
017: import org.bouncycastle.math.ec.ECCurve;
018: import org.bouncycastle.math.ec.ECPoint;
019: import org.bouncycastle.util.BigIntegers;
020: import org.bouncycastle.util.encoders.Hex;
021: import org.bouncycastle.util.test.FixedSecureRandom;
022: import org.bouncycastle.util.test.SimpleTest;
023:
024: /**
025: * ECDSA tests are taken from X9.62.
026: */
027: public class ECTest extends SimpleTest {
028: /**
029: * X9.62 - 1998,<br>
030: * J.3.1, Page 152, ECDSA over the field Fp<br>
031: * an example with 192 bit prime
032: */
033: private void testECDSA192bitPrime() {
034: BigInteger r = new BigInteger(
035: "3342403536405981729393488334694600415596881826869351677613");
036: BigInteger s = new BigInteger(
037: "5735822328888155254683894997897571951568553642892029982342");
038:
039: byte[] kData = BigIntegers
040: .asUnsignedByteArray(new BigInteger(
041: "6140507067065001063065065565667405560006161556565665656654"));
042:
043: SecureRandom k = new FixedSecureRandom(kData);
044:
045: ECCurve.Fp curve = new ECCurve.Fp(
046: new BigInteger(
047: "6277101735386680763835789423207666416083908700390324961279"), // q
048: new BigInteger(
049: "fffffffffffffffffffffffffffffffefffffffffffffffc",
050: 16), // a
051: new BigInteger(
052: "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
053: 16)); // b
054:
055: ECDomainParameters params = new ECDomainParameters(
056: curve,
057: curve
058: .decodePoint(Hex
059: .decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
060: new BigInteger(
061: "6277101735386680763835789423176059013767194773182842284081")); // n
062:
063: ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
064: new BigInteger(
065: "651056770906015076056810763456358567190100156695615665659"), // d
066: params);
067:
068: ParametersWithRandom param = new ParametersWithRandom(priKey, k);
069:
070: ECDSASigner ecdsa = new ECDSASigner();
071:
072: ecdsa.init(true, param);
073:
074: byte[] message = new BigInteger(
075: "968236873715988614170569073515315707566766479517")
076: .toByteArray();
077: BigInteger[] sig = ecdsa.generateSignature(message);
078:
079: if (!r.equals(sig[0])) {
080: fail("r component wrong."
081: + System.getProperty("line.separator")
082: + " expecting: " + r
083: + System.getProperty("line.separator")
084: + " got : " + sig[0]);
085: }
086:
087: if (!s.equals(sig[1])) {
088: fail("s component wrong."
089: + System.getProperty("line.separator")
090: + " expecting: " + s
091: + System.getProperty("line.separator")
092: + " got : " + sig[1]);
093: }
094:
095: // Verify the signature
096: ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
097: curve
098: .decodePoint(Hex
099: .decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
100: params);
101:
102: ecdsa.init(false, pubKey);
103: if (!ecdsa.verifySignature(message, sig[0], sig[1])) {
104: fail("verification fails");
105: }
106: }
107:
108: private void decodeTest() {
109: ECCurve.Fp curve = new ECCurve.Fp(
110: new BigInteger(
111: "6277101735386680763835789423207666416083908700390324961279"), // q
112: new BigInteger(
113: "fffffffffffffffffffffffffffffffefffffffffffffffc",
114: 16), // a
115: new BigInteger(
116: "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
117: 16)); // b
118:
119: ECPoint p = curve
120: .decodePoint(Hex
121: .decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"));
122:
123: if (!p
124: .getX()
125: .toBigInteger()
126: .equals(
127: new BigInteger(
128: "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
129: 16))) {
130: fail("x uncompressed incorrectly");
131: }
132:
133: if (!p
134: .getY()
135: .toBigInteger()
136: .equals(
137: new BigInteger(
138: "7192b95ffc8da78631011ed6b24cdd573f977a11e794811",
139: 16))) {
140: fail("y uncompressed incorrectly");
141: }
142:
143: byte[] encoding = p.getEncoded();
144:
145: if (!areEqual(
146: encoding,
147: Hex
148: .decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"))) {
149: fail("point compressed incorrectly");
150: }
151: }
152:
153: /**
154: * X9.62 - 1998,<br>
155: * J.3.2, Page 155, ECDSA over the field Fp<br>
156: * an example with 239 bit prime
157: */
158: private void testECDSA239bitPrime() {
159: BigInteger r = new BigInteger(
160: "308636143175167811492622547300668018854959378758531778147462058306432176");
161: BigInteger s = new BigInteger(
162: "323813553209797357708078776831250505931891051755007842781978505179448783");
163:
164: byte[] kData = BigIntegers
165: .asUnsignedByteArray(new BigInteger(
166: "700000017569056646655505781757157107570501575775705779575555657156756655"));
167:
168: SecureRandom k = new FixedSecureRandom(true, kData);
169:
170: ECCurve.Fp curve = new ECCurve.Fp(
171: new BigInteger(
172: "883423532389192164791648750360308885314476597252960362792450860609699839"), // q
173: new BigInteger(
174: "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc",
175: 16), // a
176: new BigInteger(
177: "6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a",
178: 16)); // b
179:
180: ECDomainParameters params = new ECDomainParameters(
181: curve,
182: curve
183: .decodePoint(Hex
184: .decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
185: new BigInteger(
186: "883423532389192164791648750360308884807550341691627752275345424702807307")); // n
187:
188: ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
189: new BigInteger(
190: "876300101507107567501066130761671078357010671067781776716671676178726717"), // d
191: params);
192:
193: ECDSASigner ecdsa = new ECDSASigner();
194: ParametersWithRandom param = new ParametersWithRandom(priKey, k);
195:
196: ecdsa.init(true, param);
197:
198: byte[] message = new BigInteger(
199: "968236873715988614170569073515315707566766479517")
200: .toByteArray();
201: BigInteger[] sig = ecdsa.generateSignature(message);
202:
203: if (!r.equals(sig[0])) {
204: fail("r component wrong."
205: + System.getProperty("line.separator")
206: + " expecting: " + r
207: + System.getProperty("line.separator")
208: + " got : " + sig[0]);
209: }
210:
211: if (!s.equals(sig[1])) {
212: fail("s component wrong."
213: + System.getProperty("line.separator")
214: + " expecting: " + s
215: + System.getProperty("line.separator")
216: + " got : " + sig[1]);
217: }
218:
219: // Verify the signature
220: ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
221: curve
222: .decodePoint(Hex
223: .decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
224: params);
225:
226: ecdsa.init(false, pubKey);
227: if (!ecdsa.verifySignature(message, sig[0], sig[1])) {
228: fail("signature fails");
229: }
230: }
231:
232: /**
233: * X9.62 - 1998,<br>
234: * J.2.1, Page 100, ECDSA over the field F2m<br>
235: * an example with 191 bit binary field
236: */
237: private void testECDSA191bitBinary() {
238: BigInteger r = new BigInteger(
239: "87194383164871543355722284926904419997237591535066528048");
240: BigInteger s = new BigInteger(
241: "308992691965804947361541664549085895292153777025772063598");
242:
243: byte[] kData = BigIntegers
244: .asUnsignedByteArray(new BigInteger(
245: "1542725565216523985789236956265265265235675811949404040041"));
246:
247: SecureRandom k = new FixedSecureRandom(kData);
248:
249: ECCurve.F2m curve = new ECCurve.F2m(
250: 191, // m
251: 9, //k
252: new BigInteger(
253: "2866537B676752636A68F56554E12640276B649EF7526267",
254: 16), // a
255: new BigInteger(
256: "2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC",
257: 16)); // b
258:
259: ECDomainParameters params = new ECDomainParameters(
260: curve,
261: curve
262: .decodePoint(Hex
263: .decode("0436B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB")), // G
264: new BigInteger(
265: "1569275433846670190958947355803350458831205595451630533029"), // n
266: BigInteger.valueOf(2)); // h
267:
268: ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
269: new BigInteger(
270: "1275552191113212300012030439187146164646146646466749494799"), // d
271: params);
272:
273: ECDSASigner ecdsa = new ECDSASigner();
274: ParametersWithRandom param = new ParametersWithRandom(priKey, k);
275:
276: ecdsa.init(true, param);
277:
278: byte[] message = new BigInteger(
279: "968236873715988614170569073515315707566766479517")
280: .toByteArray();
281: BigInteger[] sig = ecdsa.generateSignature(message);
282:
283: if (!r.equals(sig[0])) {
284: fail("r component wrong."
285: + System.getProperty("line.separator")
286: + " expecting: " + r
287: + System.getProperty("line.separator")
288: + " got : " + sig[0]);
289: }
290:
291: if (!s.equals(sig[1])) {
292: fail("s component wrong."
293: + System.getProperty("line.separator")
294: + " expecting: " + s
295: + System.getProperty("line.separator")
296: + " got : " + sig[1]);
297: }
298:
299: // Verify the signature
300: ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
301: curve
302: .decodePoint(Hex
303: .decode("045DE37E756BD55D72E3768CB396FFEB962614DEA4CE28A2E755C0E0E02F5FB132CAF416EF85B229BBB8E1352003125BA1")), // Q
304: params);
305:
306: ecdsa.init(false, pubKey);
307: if (!ecdsa.verifySignature(message, sig[0], sig[1])) {
308: fail("signature fails");
309: }
310: }
311:
312: /**
313: * X9.62 - 1998,<br>
314: * J.2.1, Page 100, ECDSA over the field F2m<br>
315: * an example with 191 bit binary field
316: */
317: private void testECDSA239bitBinary() {
318: BigInteger r = new BigInteger(
319: "21596333210419611985018340039034612628818151486841789642455876922391552");
320: BigInteger s = new BigInteger(
321: "197030374000731686738334997654997227052849804072198819102649413465737174");
322:
323: byte[] kData = BigIntegers
324: .asUnsignedByteArray(new BigInteger(
325: "171278725565216523967285789236956265265265235675811949404040041670216363"));
326:
327: SecureRandom k = new FixedSecureRandom(kData);
328:
329: ECCurve.F2m curve = new ECCurve.F2m(
330: 239, // m
331: 36, //k
332: new BigInteger(
333: "32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
334: 16), // a
335: new BigInteger(
336: "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
337: 16)); // b
338:
339: ECDomainParameters params = new ECDomainParameters(
340: curve,
341: curve
342: .decodePoint(Hex
343: .decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
344: new BigInteger(
345: "220855883097298041197912187592864814557886993776713230936715041207411783"), // n
346: BigInteger.valueOf(4)); // h
347:
348: ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
349: new BigInteger(
350: "145642755521911534651321230007534120304391871461646461466464667494947990"), // d
351: params);
352:
353: ECDSASigner ecdsa = new ECDSASigner();
354: ParametersWithRandom param = new ParametersWithRandom(priKey, k);
355:
356: ecdsa.init(true, param);
357:
358: byte[] message = new BigInteger(
359: "968236873715988614170569073515315707566766479517")
360: .toByteArray();
361: BigInteger[] sig = ecdsa.generateSignature(message);
362:
363: if (!r.equals(sig[0])) {
364: fail("r component wrong."
365: + System.getProperty("line.separator")
366: + " expecting: " + r
367: + System.getProperty("line.separator")
368: + " got : " + sig[0]);
369: }
370:
371: if (!s.equals(sig[1])) {
372: fail("s component wrong."
373: + System.getProperty("line.separator")
374: + " expecting: " + s
375: + System.getProperty("line.separator")
376: + " got : " + sig[1]);
377: }
378:
379: // Verify the signature
380: ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
381: curve
382: .decodePoint(Hex
383: .decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
384: params);
385:
386: ecdsa.init(false, pubKey);
387: if (!ecdsa.verifySignature(message, sig[0], sig[1])) {
388: fail("signature fails");
389: }
390: }
391:
392: /**
393: * General test for long digest.
394: */
395: private void testECDSA239bitBinaryAndLargeDigest() {
396: BigInteger r = new BigInteger(
397: "21596333210419611985018340039034612628818151486841789642455876922391552");
398: BigInteger s = new BigInteger(
399: "87626799441093658509023277770579403014298417038607966989658087651831660");
400:
401: byte[] kData = BigIntegers
402: .asUnsignedByteArray(new BigInteger(
403: "171278725565216523967285789236956265265265235675811949404040041670216363"));
404:
405: SecureRandom k = new FixedSecureRandom(kData);
406:
407: ECCurve.F2m curve = new ECCurve.F2m(
408: 239, // m
409: 36, //k
410: new BigInteger(
411: "32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
412: 16), // a
413: new BigInteger(
414: "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
415: 16)); // b
416:
417: ECDomainParameters params = new ECDomainParameters(
418: curve,
419: curve
420: .decodePoint(Hex
421: .decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
422: new BigInteger(
423: "220855883097298041197912187592864814557886993776713230936715041207411783"), // n
424: BigInteger.valueOf(4)); // h
425:
426: ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
427: new BigInteger(
428: "145642755521911534651321230007534120304391871461646461466464667494947990"), // d
429: params);
430:
431: ECDSASigner ecdsa = new ECDSASigner();
432: ParametersWithRandom param = new ParametersWithRandom(priKey, k);
433:
434: ecdsa.init(true, param);
435:
436: byte[] message = new BigInteger(
437: "968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517")
438: .toByteArray();
439: BigInteger[] sig = ecdsa.generateSignature(message);
440:
441: if (!r.equals(sig[0])) {
442: fail("r component wrong."
443: + System.getProperty("line.separator")
444: + " expecting: " + r
445: + System.getProperty("line.separator")
446: + " got : " + sig[0]);
447: }
448:
449: if (!s.equals(sig[1])) {
450: fail("s component wrong."
451: + System.getProperty("line.separator")
452: + " expecting: " + s
453: + System.getProperty("line.separator")
454: + " got : " + sig[1]);
455: }
456:
457: // Verify the signature
458: ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
459: curve
460: .decodePoint(Hex
461: .decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
462: params);
463:
464: ecdsa.init(false, pubKey);
465: if (!ecdsa.verifySignature(message, sig[0], sig[1])) {
466: fail("signature fails");
467: }
468: }
469:
470: /**
471: * key generation test
472: */
473: private void testECDSAKeyGenTest() {
474: SecureRandom random = new SecureRandom();
475: ECCurve.Fp curve = new ECCurve.Fp(
476: new BigInteger(
477: "883423532389192164791648750360308885314476597252960362792450860609699839"), // q
478: new BigInteger(
479: "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc",
480: 16), // a
481: new BigInteger(
482: "6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a",
483: 16)); // b
484:
485: ECDomainParameters params = new ECDomainParameters(
486: curve,
487: curve
488: .decodePoint(Hex
489: .decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
490: new BigInteger(
491: "883423532389192164791648750360308884807550341691627752275345424702807307")); // n
492:
493: ECKeyPairGenerator pGen = new ECKeyPairGenerator();
494: ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
495: params, random);
496:
497: pGen.init(genParam);
498:
499: AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
500:
501: ParametersWithRandom param = new ParametersWithRandom(pair
502: .getPrivate(), random);
503:
504: ECDSASigner ecdsa = new ECDSASigner();
505:
506: ecdsa.init(true, param);
507:
508: byte[] message = new BigInteger(
509: "968236873715988614170569073515315707566766479517")
510: .toByteArray();
511: BigInteger[] sig = ecdsa.generateSignature(message);
512:
513: ecdsa.init(false, pair.getPublic());
514:
515: if (!ecdsa.verifySignature(message, sig[0], sig[1])) {
516: fail("signature fails");
517: }
518: }
519:
520: /**
521: * Basic Key Agreement Test
522: */
523: private void testECBasicAgreementTest() {
524: SecureRandom random = new SecureRandom();
525: ECCurve.Fp curve = new ECCurve.Fp(
526: new BigInteger(
527: "883423532389192164791648750360308885314476597252960362792450860609699839"), // q
528: new BigInteger(
529: "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc",
530: 16), // a
531: new BigInteger(
532: "6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a",
533: 16)); // b
534:
535: ECDomainParameters params = new ECDomainParameters(
536: curve,
537: curve
538: .decodePoint(Hex
539: .decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
540: new BigInteger(
541: "883423532389192164791648750360308884807550341691627752275345424702807307")); // n
542:
543: ECKeyPairGenerator pGen = new ECKeyPairGenerator();
544: ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
545: params, random);
546:
547: pGen.init(genParam);
548:
549: AsymmetricCipherKeyPair p1 = pGen.generateKeyPair();
550: AsymmetricCipherKeyPair p2 = pGen.generateKeyPair();
551:
552: //
553: // two way
554: //
555: BasicAgreement e1 = new ECDHBasicAgreement();
556: BasicAgreement e2 = new ECDHBasicAgreement();
557:
558: e1.init(p1.getPrivate());
559: e2.init(p2.getPrivate());
560:
561: BigInteger k1 = e1.calculateAgreement(p2.getPublic());
562: BigInteger k2 = e2.calculateAgreement(p1.getPublic());
563:
564: if (!k1.equals(k2)) {
565: fail("calculated agreement test failed");
566: }
567:
568: //
569: // two way
570: //
571: e1 = new ECDHCBasicAgreement();
572: e2 = new ECDHCBasicAgreement();
573:
574: e1.init(p1.getPrivate());
575: e2.init(p2.getPrivate());
576:
577: k1 = e1.calculateAgreement(p2.getPublic());
578: k2 = e2.calculateAgreement(p1.getPublic());
579:
580: if (!k1.equals(k2)) {
581: fail("calculated agreement test failed");
582: }
583: }
584:
585: public String getName() {
586: return "EC";
587: }
588:
589: public void performTest() {
590: decodeTest();
591: testECDSA192bitPrime();
592: testECDSA239bitPrime();
593: testECDSA191bitBinary();
594: testECDSA239bitBinary();
595: testECDSAKeyGenTest();
596: testECBasicAgreementTest();
597: testECDSA239bitBinaryAndLargeDigest();
598: }
599:
600: public static void main(String[] args) {
601: runTest(new ECTest());
602: }
603: }
|