001: package org.bouncycastle.jce.provider.test;
002:
003: import org.bouncycastle.asn1.ASN1InputStream;
004: import org.bouncycastle.asn1.ASN1Sequence;
005: import org.bouncycastle.asn1.DERInteger;
006: import org.bouncycastle.asn1.DERObjectIdentifier;
007: import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
008: import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
009: import org.bouncycastle.jce.provider.BouncyCastleProvider;
010: import org.bouncycastle.jce.spec.ECParameterSpec;
011: import org.bouncycastle.jce.spec.ECPrivateKeySpec;
012: import org.bouncycastle.jce.spec.ECPublicKeySpec;
013: import org.bouncycastle.math.ec.ECCurve;
014: import org.bouncycastle.util.BigIntegers;
015: import org.bouncycastle.util.encoders.Hex;
016: import org.bouncycastle.util.test.FixedSecureRandom;
017: import org.bouncycastle.util.test.SimpleTest;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.ByteArrayOutputStream;
021: import java.io.IOException;
022: import java.io.ObjectInputStream;
023: import java.io.ObjectOutputStream;
024: import java.math.BigInteger;
025: import java.security.AlgorithmParameterGenerator;
026: import java.security.AlgorithmParameters;
027: import java.security.KeyFactory;
028: import java.security.KeyPair;
029: import java.security.KeyPairGenerator;
030: import java.security.PrivateKey;
031: import java.security.PublicKey;
032: import java.security.SecureRandom;
033: import java.security.Security;
034: import java.security.Signature;
035: import java.security.interfaces.DSAPrivateKey;
036: import java.security.interfaces.DSAPublicKey;
037: import java.security.spec.DSAParameterSpec;
038: import java.security.spec.PKCS8EncodedKeySpec;
039: import java.security.spec.X509EncodedKeySpec;
040:
041: public class DSATest extends SimpleTest {
042: byte[] k1 = Hex.decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
043: byte[] k2 = Hex
044: .decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
045:
046: SecureRandom random = new FixedSecureRandom(new byte[][] { k1, k2 });
047:
048: public void testCompat() throws Exception {
049: Signature s = Signature.getInstance("DSA", "SUN");
050: KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "SUN");
051: byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
052:
053: g.initialize(512, new SecureRandom());
054:
055: KeyPair p = g.generateKeyPair();
056:
057: PrivateKey sKey = p.getPrivate();
058: PublicKey vKey = p.getPublic();
059:
060: //
061: // sign SUN - verify with BC
062: //
063: s.initSign(sKey);
064:
065: s.update(data);
066:
067: byte[] sigBytes = s.sign();
068:
069: s = Signature.getInstance("DSA", "BC");
070:
071: s.initVerify(vKey);
072:
073: s.update(data);
074:
075: if (!s.verify(sigBytes)) {
076: fail("SUN -> BC verification failed");
077: }
078:
079: //
080: // sign BC - verify with SUN
081: //
082:
083: s.initSign(sKey);
084:
085: s.update(data);
086:
087: sigBytes = s.sign();
088:
089: s = Signature.getInstance("DSA", "SUN");
090:
091: s.initVerify(vKey);
092:
093: s.update(data);
094:
095: if (!s.verify(sigBytes)) {
096: fail("BC -> SUN verification failed");
097: }
098:
099: //
100: // key encoding test - BC decoding Sun keys
101: //
102: KeyFactory f = KeyFactory.getInstance("DSA", "BC");
103: X509EncodedKeySpec x509s = new X509EncodedKeySpec(vKey
104: .getEncoded());
105:
106: DSAPublicKey k1 = (DSAPublicKey) f.generatePublic(x509s);
107:
108: checkPublic(k1, vKey);
109:
110: PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(sKey
111: .getEncoded());
112:
113: DSAPrivateKey k2 = (DSAPrivateKey) f.generatePrivate(pkcs8);
114:
115: checkPrivateKey(k2, sKey);
116:
117: //
118: // key decoding test - SUN decoding BC keys
119: //
120: f = KeyFactory.getInstance("DSA", "SUN");
121: x509s = new X509EncodedKeySpec(k1.getEncoded());
122:
123: vKey = (DSAPublicKey) f.generatePublic(x509s);
124:
125: checkPublic(k1, vKey);
126:
127: pkcs8 = new PKCS8EncodedKeySpec(k2.getEncoded());
128: sKey = f.generatePrivate(pkcs8);
129:
130: checkPrivateKey(k2, sKey);
131: }
132:
133: private void checkPublic(DSAPublicKey k1, PublicKey vKey) {
134: if (!k1.getY().equals(((DSAPublicKey) vKey).getY())) {
135: fail("public number not decoded properly");
136: }
137:
138: if (!k1.getParams().getG().equals(
139: ((DSAPublicKey) vKey).getParams().getG())) {
140: fail("public generator not decoded properly");
141: }
142:
143: if (!k1.getParams().getP().equals(
144: ((DSAPublicKey) vKey).getParams().getP())) {
145: fail("public p value not decoded properly");
146: }
147:
148: if (!k1.getParams().getQ().equals(
149: ((DSAPublicKey) vKey).getParams().getQ())) {
150: fail("public q value not decoded properly");
151: }
152: }
153:
154: private void checkPrivateKey(DSAPrivateKey k2, PrivateKey sKey) {
155: if (!k2.getX().equals(((DSAPrivateKey) sKey).getX())) {
156: fail("private number not decoded properly");
157: }
158:
159: if (!k2.getParams().getG().equals(
160: ((DSAPrivateKey) sKey).getParams().getG())) {
161: fail("private generator not decoded properly");
162: }
163:
164: if (!k2.getParams().getP().equals(
165: ((DSAPrivateKey) sKey).getParams().getP())) {
166: fail("private p value not decoded properly");
167: }
168:
169: if (!k2.getParams().getQ().equals(
170: ((DSAPrivateKey) sKey).getParams().getQ())) {
171: fail("private q value not decoded properly");
172: }
173: }
174:
175: private Object serializeDeserialize(Object o) throws Exception {
176: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
177: ObjectOutputStream oOut = new ObjectOutputStream(bOut);
178:
179: oOut.writeObject(o);
180: oOut.close();
181:
182: ObjectInputStream oIn = new ObjectInputStream(
183: new ByteArrayInputStream(bOut.toByteArray()));
184:
185: return oIn.readObject();
186: }
187:
188: /**
189: * X9.62 - 1998,<br>
190: * J.3.2, Page 155, ECDSA over the field Fp<br>
191: * an example with 239 bit prime
192: */
193: private void testECDSA239bitPrime() throws Exception {
194: BigInteger r = new BigInteger(
195: "308636143175167811492622547300668018854959378758531778147462058306432176");
196: BigInteger s = new BigInteger(
197: "323813553209797357708078776831250505931891051755007842781978505179448783");
198:
199: byte[] kData = BigIntegers
200: .asUnsignedByteArray(new BigInteger(
201: "700000017569056646655505781757157107570501575775705779575555657156756655"));
202:
203: SecureRandom k = new FixedSecureRandom(kData);
204:
205: ECCurve curve = new ECCurve.Fp(
206: new BigInteger(
207: "883423532389192164791648750360308885314476597252960362792450860609699839"), // q
208: new BigInteger(
209: "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc",
210: 16), // a
211: new BigInteger(
212: "6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a",
213: 16)); // b
214:
215: ECParameterSpec spec = new ECParameterSpec(
216: curve,
217: curve
218: .decodePoint(Hex
219: .decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
220: new BigInteger(
221: "883423532389192164791648750360308884807550341691627752275345424702807307")); // n
222:
223: ECPrivateKeySpec priKey = new ECPrivateKeySpec(
224: new BigInteger(
225: "876300101507107567501066130761671078357010671067781776716671676178726717"), // d
226: spec);
227:
228: ECPublicKeySpec pubKey = new ECPublicKeySpec(
229: curve
230: .decodePoint(Hex
231: .decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
232: spec);
233:
234: Signature sgr = Signature.getInstance("ECDSA", "BC");
235: KeyFactory f = KeyFactory.getInstance("ECDSA", "BC");
236: PrivateKey sKey = f.generatePrivate(priKey);
237: PublicKey vKey = f.generatePublic(pubKey);
238:
239: sgr.initSign(sKey, k);
240:
241: byte[] message = new byte[] { (byte) 'a', (byte) 'b',
242: (byte) 'c' };
243:
244: sgr.update(message);
245:
246: byte[] sigBytes = sgr.sign();
247:
248: sgr.initVerify(vKey);
249:
250: sgr.update(message);
251:
252: if (!sgr.verify(sigBytes)) {
253: fail("239 Bit EC verification failed");
254: }
255:
256: BigInteger[] sig = derDecode(sigBytes);
257:
258: if (!r.equals(sig[0])) {
259: fail("r component wrong."
260: + System.getProperty("line.separator")
261: + " expecting: " + r
262: + System.getProperty("line.separator")
263: + " got : " + sig[0]);
264: }
265:
266: if (!s.equals(sig[1])) {
267: fail("s component wrong."
268: + System.getProperty("line.separator")
269: + " expecting: " + s
270: + System.getProperty("line.separator")
271: + " got : " + sig[1]);
272: }
273: }
274:
275: /**
276: * X9.62 - 1998,<br>
277: * J.2.1, Page 100, ECDSA over the field F2m<br>
278: * an example with 191 bit binary field
279: */
280: private void testECDSA239bitBinary() throws Exception {
281: BigInteger r = new BigInteger(
282: "21596333210419611985018340039034612628818151486841789642455876922391552");
283: BigInteger s = new BigInteger(
284: "197030374000731686738334997654997227052849804072198819102649413465737174");
285:
286: byte[] kData = BigIntegers
287: .asUnsignedByteArray(new BigInteger(
288: "171278725565216523967285789236956265265265235675811949404040041670216363"));
289:
290: SecureRandom k = new FixedSecureRandom(kData);
291:
292: ECCurve curve = new ECCurve.F2m(
293: 239, // m
294: 36, // k
295: new BigInteger(
296: "32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
297: 16), // a
298: new BigInteger(
299: "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
300: 16)); // b
301:
302: ECParameterSpec params = new ECParameterSpec(
303: curve,
304: curve
305: .decodePoint(Hex
306: .decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
307: new BigInteger(
308: "220855883097298041197912187592864814557886993776713230936715041207411783"), // n
309: BigInteger.valueOf(4)); // h
310:
311: ECPrivateKeySpec priKeySpec = new ECPrivateKeySpec(
312: new BigInteger(
313: "145642755521911534651321230007534120304391871461646461466464667494947990"), // d
314: params);
315:
316: ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(
317: curve
318: .decodePoint(Hex
319: .decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
320: params);
321:
322: Signature sgr = Signature.getInstance("ECDSA", "BC");
323: KeyFactory f = KeyFactory.getInstance("ECDSA", "BC");
324: PrivateKey sKey = f.generatePrivate(priKeySpec);
325: PublicKey vKey = f.generatePublic(pubKeySpec);
326: byte[] message = new byte[] { (byte) 'a', (byte) 'b',
327: (byte) 'c' };
328:
329: sgr.initSign(sKey, k);
330:
331: sgr.update(message);
332:
333: byte[] sigBytes = sgr.sign();
334:
335: sgr.initVerify(vKey);
336:
337: sgr.update(message);
338:
339: if (!sgr.verify(sigBytes)) {
340: fail("239 Bit EC verification failed");
341: }
342:
343: BigInteger[] sig = derDecode(sigBytes);
344:
345: if (!r.equals(sig[0])) {
346: fail("r component wrong."
347: + System.getProperty("line.separator")
348: + " expecting: " + r
349: + System.getProperty("line.separator")
350: + " got : " + sig[0]);
351: }
352:
353: if (!s.equals(sig[1])) {
354: fail("s component wrong."
355: + System.getProperty("line.separator")
356: + " expecting: " + s
357: + System.getProperty("line.separator")
358: + " got : " + sig[1]);
359: }
360: }
361:
362: private void testECDSA239bitBinary(String algorithm,
363: DERObjectIdentifier oid) throws Exception {
364: BigInteger r = new BigInteger(
365: "21596333210419611985018340039034612628818151486841789642455876922391552");
366: BigInteger s = new BigInteger(
367: "197030374000731686738334997654997227052849804072198819102649413465737174");
368:
369: byte[] kData = BigIntegers
370: .asUnsignedByteArray(new BigInteger(
371: "171278725565216523967285789236956265265265235675811949404040041670216363"));
372:
373: SecureRandom k = new FixedSecureRandom(kData);
374:
375: ECCurve curve = new ECCurve.F2m(
376: 239, // m
377: 36, // k
378: new BigInteger(
379: "32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
380: 16), // a
381: new BigInteger(
382: "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
383: 16)); // b
384:
385: ECParameterSpec params = new ECParameterSpec(
386: curve,
387: curve
388: .decodePoint(Hex
389: .decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
390: new BigInteger(
391: "220855883097298041197912187592864814557886993776713230936715041207411783"), // n
392: BigInteger.valueOf(4)); // h
393:
394: ECPrivateKeySpec priKeySpec = new ECPrivateKeySpec(
395: new BigInteger(
396: "145642755521911534651321230007534120304391871461646461466464667494947990"), // d
397: params);
398:
399: ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(
400: curve
401: .decodePoint(Hex
402: .decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
403: params);
404:
405: Signature sgr = Signature.getInstance(algorithm, "BC");
406: KeyFactory f = KeyFactory.getInstance("ECDSA", "BC");
407: PrivateKey sKey = f.generatePrivate(priKeySpec);
408: PublicKey vKey = f.generatePublic(pubKeySpec);
409: byte[] message = new byte[] { (byte) 'a', (byte) 'b',
410: (byte) 'c' };
411:
412: sgr.initSign(sKey, k);
413:
414: sgr.update(message);
415:
416: byte[] sigBytes = sgr.sign();
417:
418: sgr = Signature.getInstance(oid.getId(), "BC");
419:
420: sgr.initVerify(vKey);
421:
422: sgr.update(message);
423:
424: if (!sgr.verify(sigBytes)) {
425: fail("239 Bit EC RIPEMD160 verification failed");
426: }
427: }
428:
429: private void testGeneration() throws Exception {
430: Signature s = Signature.getInstance("DSA", "BC");
431: KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC");
432: byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
433:
434: // test exception
435: //
436: try {
437: g.initialize(513, new SecureRandom());
438:
439: fail("illegal parameter 513 check failed.");
440: } catch (IllegalArgumentException e) {
441: // expected
442: }
443:
444: try {
445: g.initialize(510, new SecureRandom());
446:
447: fail("illegal parameter 510 check failed.");
448: } catch (IllegalArgumentException e) {
449: // expected
450: }
451:
452: try {
453: g.initialize(1025, new SecureRandom());
454:
455: fail("illegal parameter 1025 check failed.");
456: } catch (IllegalArgumentException e) {
457: // expected
458: }
459:
460: g.initialize(512, new SecureRandom());
461:
462: KeyPair p = g.generateKeyPair();
463:
464: PrivateKey sKey = p.getPrivate();
465: PublicKey vKey = p.getPublic();
466:
467: s.initSign(sKey);
468:
469: s.update(data);
470:
471: byte[] sigBytes = s.sign();
472:
473: s = Signature.getInstance("DSA", "BC");
474:
475: s.initVerify(vKey);
476:
477: s.update(data);
478:
479: if (!s.verify(sigBytes)) {
480: fail("DSA verification failed");
481: }
482:
483: //
484: // key decoding test - serialisation test
485: //
486:
487: DSAPublicKey k1 = (DSAPublicKey) serializeDeserialize(vKey);
488:
489: checkPublic(k1, vKey);
490:
491: DSAPrivateKey k2 = (DSAPrivateKey) serializeDeserialize(sKey);
492:
493: checkPrivateKey(k2, sKey);
494:
495: //
496: // ECDSA Fp generation test
497: //
498: s = Signature.getInstance("ECDSA", "BC");
499: g = KeyPairGenerator.getInstance("ECDSA", "BC");
500:
501: ECCurve curve = new ECCurve.Fp(
502: new BigInteger(
503: "883423532389192164791648750360308885314476597252960362792450860609699839"), // q
504: new BigInteger(
505: "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc",
506: 16), // a
507: new BigInteger(
508: "6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a",
509: 16)); // b
510:
511: ECParameterSpec ecSpec = new ECParameterSpec(
512: curve,
513: curve
514: .decodePoint(Hex
515: .decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
516: new BigInteger(
517: "883423532389192164791648750360308884807550341691627752275345424702807307")); // n
518:
519: g.initialize(ecSpec, new SecureRandom());
520:
521: p = g.generateKeyPair();
522:
523: sKey = p.getPrivate();
524: vKey = p.getPublic();
525:
526: s.initSign(sKey);
527:
528: s.update(data);
529:
530: sigBytes = s.sign();
531:
532: s = Signature.getInstance("ECDSA", "BC");
533:
534: s.initVerify(vKey);
535:
536: s.update(data);
537:
538: if (!s.verify(sigBytes)) {
539: fail("ECDSA verification failed");
540: }
541:
542: //
543: // ECDSA F2m generation test
544: //
545: s = Signature.getInstance("ECDSA", "BC");
546: g = KeyPairGenerator.getInstance("ECDSA", "BC");
547:
548: curve = new ECCurve.F2m(
549: 239, // m
550: 36, // k
551: new BigInteger(
552: "32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
553: 16), // a
554: new BigInteger(
555: "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
556: 16)); // b
557:
558: ecSpec = new ECParameterSpec(
559: curve,
560: curve
561: .decodePoint(Hex
562: .decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
563: new BigInteger(
564: "220855883097298041197912187592864814557886993776713230936715041207411783"), // n
565: BigInteger.valueOf(4)); // h
566:
567: g.initialize(ecSpec, new SecureRandom());
568:
569: p = g.generateKeyPair();
570:
571: sKey = p.getPrivate();
572: vKey = p.getPublic();
573:
574: s.initSign(sKey);
575:
576: s.update(data);
577:
578: sigBytes = s.sign();
579:
580: s = Signature.getInstance("ECDSA", "BC");
581:
582: s.initVerify(vKey);
583:
584: s.update(data);
585:
586: if (!s.verify(sigBytes)) {
587: fail("ECDSA verification failed");
588: }
589: }
590:
591: private void testParameters() throws Exception {
592: AlgorithmParameterGenerator a = AlgorithmParameterGenerator
593: .getInstance("DSA", "BC");
594: a.init(512, random);
595: AlgorithmParameters params = a.generateParameters();
596:
597: byte[] encodeParams = params.getEncoded();
598:
599: AlgorithmParameters a2 = AlgorithmParameters.getInstance("DSA",
600: "BC");
601: a2.init(encodeParams);
602:
603: // a and a2 should be equivalent!
604: byte[] encodeParams_2 = a2.getEncoded();
605:
606: if (!areEqual(encodeParams, encodeParams_2)) {
607: fail("encode/decode parameters failed");
608: }
609:
610: DSAParameterSpec dsaP = (DSAParameterSpec) params
611: .getParameterSpec(DSAParameterSpec.class);
612:
613: KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC");
614: g.initialize(dsaP, new SecureRandom());
615: KeyPair p = g.generateKeyPair();
616:
617: PrivateKey sKey = p.getPrivate();
618: PublicKey vKey = p.getPublic();
619:
620: Signature s = Signature.getInstance("DSA", "BC");
621: byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
622:
623: s.initSign(sKey);
624:
625: s.update(data);
626:
627: byte[] sigBytes = s.sign();
628:
629: s = Signature.getInstance("DSA", "BC");
630:
631: s.initVerify(vKey);
632:
633: s.update(data);
634:
635: if (!s.verify(sigBytes)) {
636: fail("DSA verification failed");
637: }
638: }
639:
640: public void performTest() throws Exception {
641: testCompat();
642: testECDSA239bitPrime();
643: testECDSA239bitBinary();
644: testECDSA239bitBinary("RIPEMD160withECDSA",
645: TeleTrusTObjectIdentifiers.ecSignWithRipemd160);
646: testECDSA239bitBinary("SHA1withECDSA",
647: TeleTrusTObjectIdentifiers.ecSignWithSha1);
648: testECDSA239bitBinary("SHA224withECDSA",
649: X9ObjectIdentifiers.ecdsa_with_SHA224);
650: testECDSA239bitBinary("SHA256withECDSA",
651: X9ObjectIdentifiers.ecdsa_with_SHA256);
652: testECDSA239bitBinary("SHA384withECDSA",
653: X9ObjectIdentifiers.ecdsa_with_SHA384);
654: testECDSA239bitBinary("SHA512withECDSA",
655: X9ObjectIdentifiers.ecdsa_with_SHA512);
656: testGeneration();
657: testParameters();
658: }
659:
660: protected BigInteger[] derDecode(byte[] encoding)
661: throws IOException {
662: ByteArrayInputStream bIn = new ByteArrayInputStream(encoding);
663: ASN1InputStream aIn = new ASN1InputStream(bIn);
664: ASN1Sequence s = (ASN1Sequence) aIn.readObject();
665:
666: BigInteger[] sig = new BigInteger[2];
667:
668: sig[0] = ((DERInteger) s.getObjectAt(0)).getValue();
669: sig[1] = ((DERInteger) s.getObjectAt(1)).getValue();
670:
671: return sig;
672: }
673:
674: public String getName() {
675: return "DSA/ECDSA";
676: }
677:
678: public static void main(String[] args) {
679: Security.addProvider(new BouncyCastleProvider());
680:
681: runTest(new DSATest());
682: }
683: }
|