001: package org.bouncycastle.jce.provider.test;
002:
003: import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
004: import org.bouncycastle.jce.ECPointUtil;
005: import org.bouncycastle.jce.provider.BouncyCastleProvider;
006: import org.bouncycastle.util.encoders.Hex;
007: import org.bouncycastle.util.test.SimpleTest;
008:
009: import javax.crypto.KeyAgreement;
010: import javax.crypto.SecretKey;
011: import javax.crypto.interfaces.DHPrivateKey;
012: import javax.crypto.interfaces.DHPublicKey;
013: import javax.crypto.spec.DESKeySpec;
014: import javax.crypto.spec.DESedeKeySpec;
015: import javax.crypto.spec.DHParameterSpec;
016: import java.io.ByteArrayInputStream;
017: import java.io.ByteArrayOutputStream;
018: import java.io.ObjectInputStream;
019: import java.io.ObjectOutputStream;
020: import java.math.BigInteger;
021: import java.security.AlgorithmParameterGenerator;
022: import java.security.AlgorithmParameters;
023: import java.security.Key;
024: import java.security.KeyFactory;
025: import java.security.KeyPair;
026: import java.security.KeyPairGenerator;
027: import java.security.SecureRandom;
028: import java.security.Security;
029: import java.security.interfaces.ECPrivateKey;
030: import java.security.interfaces.ECPublicKey;
031: import java.security.spec.ECFieldFp;
032: import java.security.spec.ECParameterSpec;
033: import java.security.spec.EllipticCurve;
034: import java.security.spec.PKCS8EncodedKeySpec;
035: import java.security.spec.X509EncodedKeySpec;
036:
037: public class DHTest extends SimpleTest {
038: private BigInteger g512 = new BigInteger(
039: "153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc",
040: 16);
041: private BigInteger p512 = new BigInteger(
042: "9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b",
043: 16);
044:
045: private BigInteger g768 = new BigInteger(
046: "7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1",
047: 16);
048: private BigInteger p768 = new BigInteger(
049: "8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f",
050: 16);
051:
052: private BigInteger g1024 = new BigInteger(
053: "1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf",
054: 16);
055: private BigInteger p1024 = new BigInteger(
056: "a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7",
057: 16);
058:
059: public String getName() {
060: return "DH";
061: }
062:
063: private void testGP(int size, int privateValueSize, BigInteger g,
064: BigInteger p) throws Exception {
065: DHParameterSpec dhParams = new DHParameterSpec(p, g,
066: privateValueSize);
067:
068: KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH",
069: "BC");
070:
071: keyGen.initialize(dhParams);
072:
073: //
074: // a side
075: //
076: KeyPair aKeyPair = keyGen.generateKeyPair();
077:
078: KeyAgreement aKeyAgree = KeyAgreement.getInstance("DH", "BC");
079:
080: checkKeySize(privateValueSize, aKeyPair);
081:
082: aKeyAgree.init(aKeyPair.getPrivate());
083:
084: //
085: // b side
086: //
087: KeyPair bKeyPair = keyGen.generateKeyPair();
088:
089: KeyAgreement bKeyAgree = KeyAgreement.getInstance("DH", "BC");
090:
091: checkKeySize(privateValueSize, bKeyPair);
092:
093: bKeyAgree.init(bKeyPair.getPrivate());
094:
095: //
096: // agreement
097: //
098: aKeyAgree.doPhase(bKeyPair.getPublic(), true);
099: bKeyAgree.doPhase(aKeyPair.getPublic(), true);
100:
101: BigInteger k1 = new BigInteger(aKeyAgree.generateSecret());
102: BigInteger k2 = new BigInteger(bKeyAgree.generateSecret());
103:
104: if (!k1.equals(k2)) {
105: fail(size + " bit 2-way test failed");
106: }
107:
108: //
109: // public key encoding test
110: //
111: byte[] pubEnc = aKeyPair.getPublic().getEncoded();
112: KeyFactory keyFac = KeyFactory.getInstance("DH", "BC");
113: X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc);
114: DHPublicKey pubKey = (DHPublicKey) keyFac
115: .generatePublic(pubX509);
116: DHParameterSpec spec = pubKey.getParams();
117:
118: if (!spec.getG().equals(dhParams.getG())
119: || !spec.getP().equals(dhParams.getP())) {
120: fail(size
121: + " bit public key encoding/decoding test failed on parameters");
122: }
123:
124: if (!((DHPublicKey) aKeyPair.getPublic()).getY().equals(
125: pubKey.getY())) {
126: fail(size
127: + " bit public key encoding/decoding test failed on y value");
128: }
129:
130: //
131: // public key serialisation test
132: //
133: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
134: ObjectOutputStream oOut = new ObjectOutputStream(bOut);
135:
136: oOut.writeObject(aKeyPair.getPublic());
137:
138: ByteArrayInputStream bIn = new ByteArrayInputStream(bOut
139: .toByteArray());
140: ObjectInputStream oIn = new ObjectInputStream(bIn);
141:
142: pubKey = (DHPublicKey) oIn.readObject();
143: spec = pubKey.getParams();
144:
145: if (!spec.getG().equals(dhParams.getG())
146: || !spec.getP().equals(dhParams.getP())) {
147: fail(size
148: + " bit public key serialisation test failed on parameters");
149: }
150:
151: if (!((DHPublicKey) aKeyPair.getPublic()).getY().equals(
152: pubKey.getY())) {
153: fail(size
154: + " bit public key serialisation test failed on y value");
155: }
156:
157: //
158: // private key encoding test
159: //
160: byte[] privEnc = aKeyPair.getPrivate().getEncoded();
161: PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc);
162: DHPrivateKey privKey = (DHPrivateKey) keyFac
163: .generatePrivate(privPKCS8);
164:
165: spec = privKey.getParams();
166:
167: if (!spec.getG().equals(dhParams.getG())
168: || !spec.getP().equals(dhParams.getP())) {
169: fail(size
170: + " bit private key encoding/decoding test failed on parameters");
171: }
172:
173: if (!((DHPrivateKey) aKeyPair.getPrivate()).getX().equals(
174: privKey.getX())) {
175: fail(size
176: + " bit private key encoding/decoding test failed on y value");
177: }
178:
179: //
180: // private key serialisation test
181: //
182: bOut = new ByteArrayOutputStream();
183: oOut = new ObjectOutputStream(bOut);
184:
185: oOut.writeObject(aKeyPair.getPrivate());
186:
187: bIn = new ByteArrayInputStream(bOut.toByteArray());
188: oIn = new ObjectInputStream(bIn);
189:
190: privKey = (DHPrivateKey) oIn.readObject();
191: spec = privKey.getParams();
192:
193: if (!spec.getG().equals(dhParams.getG())
194: || !spec.getP().equals(dhParams.getP())) {
195: fail(size
196: + " bit private key serialisation test failed on parameters");
197: }
198:
199: if (!((DHPrivateKey) aKeyPair.getPrivate()).getX().equals(
200: privKey.getX())) {
201: fail(size
202: + " bit private key serialisation test failed on y value");
203: }
204:
205: //
206: // three party test
207: //
208: KeyPairGenerator aPairGen = KeyPairGenerator.getInstance("DH",
209: "BC");
210: aPairGen.initialize(spec);
211: KeyPair aPair = aPairGen.generateKeyPair();
212:
213: KeyPairGenerator bPairGen = KeyPairGenerator.getInstance("DH",
214: "BC");
215: bPairGen.initialize(spec);
216: KeyPair bPair = bPairGen.generateKeyPair();
217:
218: KeyPairGenerator cPairGen = KeyPairGenerator.getInstance("DH",
219: "BC");
220: cPairGen.initialize(spec);
221: KeyPair cPair = cPairGen.generateKeyPair();
222:
223: aKeyAgree.init(aPair.getPrivate());
224:
225: bKeyAgree.init(bPair.getPrivate());
226:
227: KeyAgreement cKeyAgree = KeyAgreement.getInstance("DH", "BC");
228: cKeyAgree.init(cPair.getPrivate());
229:
230: Key ac = aKeyAgree.doPhase(cPair.getPublic(), false);
231:
232: Key ba = bKeyAgree.doPhase(aPair.getPublic(), false);
233:
234: Key cb = cKeyAgree.doPhase(bPair.getPublic(), false);
235:
236: aKeyAgree.doPhase(cb, true);
237:
238: bKeyAgree.doPhase(ac, true);
239:
240: cKeyAgree.doPhase(ba, true);
241:
242: BigInteger aShared = new BigInteger(aKeyAgree.generateSecret());
243: BigInteger bShared = new BigInteger(bKeyAgree.generateSecret());
244: BigInteger cShared = new BigInteger(cKeyAgree.generateSecret());
245:
246: if (!aShared.equals(bShared)) {
247: fail(size + " bit 3-way test failed (a and b differ)");
248: }
249:
250: if (!cShared.equals(bShared)) {
251: fail(size + " bit 3-way test failed (c and b differ)");
252: }
253: }
254:
255: private void testExplicitWrapping(int size, int privateValueSize,
256: BigInteger g, BigInteger p) throws Exception {
257: DHParameterSpec dhParams = new DHParameterSpec(p, g,
258: privateValueSize);
259:
260: KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH",
261: "BC");
262:
263: keyGen.initialize(dhParams);
264:
265: //
266: // a side
267: //
268: KeyPair aKeyPair = keyGen.generateKeyPair();
269:
270: KeyAgreement aKeyAgree = KeyAgreement.getInstance("DH", "BC");
271:
272: checkKeySize(privateValueSize, aKeyPair);
273:
274: aKeyAgree.init(aKeyPair.getPrivate());
275:
276: //
277: // b side
278: //
279: KeyPair bKeyPair = keyGen.generateKeyPair();
280:
281: KeyAgreement bKeyAgree = KeyAgreement.getInstance("DH", "BC");
282:
283: checkKeySize(privateValueSize, bKeyPair);
284:
285: bKeyAgree.init(bKeyPair.getPrivate());
286:
287: //
288: // agreement
289: //
290: aKeyAgree.doPhase(bKeyPair.getPublic(), true);
291: bKeyAgree.doPhase(aKeyPair.getPublic(), true);
292:
293: SecretKey k1 = aKeyAgree
294: .generateSecret(PKCSObjectIdentifiers.id_alg_CMS3DESwrap
295: .getId());
296: SecretKey k2 = aKeyAgree
297: .generateSecret(PKCSObjectIdentifiers.id_alg_CMS3DESwrap
298: .getId());
299: }
300:
301: private void checkKeySize(int privateValueSize, KeyPair aKeyPair) {
302: if (privateValueSize != 0) {
303: DHPrivateKey key = (DHPrivateKey) aKeyPair.getPrivate();
304:
305: if (key.getX().bitLength() != privateValueSize) {
306: fail("limited key check failed for key size "
307: + privateValueSize);
308: }
309: }
310: }
311:
312: private void testRandom(int size) throws Exception {
313: AlgorithmParameterGenerator a = AlgorithmParameterGenerator
314: .getInstance("DH", "BC");
315: a.init(size, new SecureRandom());
316: AlgorithmParameters params = a.generateParameters();
317:
318: byte[] encodeParams = params.getEncoded();
319:
320: AlgorithmParameters a2 = AlgorithmParameters.getInstance("DH",
321: "BC");
322: a2.init(encodeParams);
323:
324: // a and a2 should be equivalent!
325: byte[] encodeParams_2 = a2.getEncoded();
326:
327: if (!areEqual(encodeParams, encodeParams_2)) {
328: fail("encode/decode parameters failed");
329: }
330:
331: DHParameterSpec dhP = (DHParameterSpec) params
332: .getParameterSpec(DHParameterSpec.class);
333:
334: testGP(size, 0, dhP.getG(), dhP.getP());
335: }
336:
337: private void testECDH(String algorithm) throws Exception {
338: KeyPairGenerator g = KeyPairGenerator.getInstance(algorithm,
339: "BC");
340:
341: EllipticCurve curve = new EllipticCurve(
342: new ECFieldFp(
343: new BigInteger(
344: "883423532389192164791648750360308885314476597252960362792450860609699839")), // q
345: new BigInteger(
346: "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc",
347: 16), // a
348: new BigInteger(
349: "6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a",
350: 16)); // b
351:
352: ECParameterSpec ecSpec = new ECParameterSpec(
353: curve,
354: ECPointUtil
355: .decodePoint(
356: curve,
357: Hex
358: .decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
359: new BigInteger(
360: "883423532389192164791648750360308884807550341691627752275345424702807307"), // n
361: 1); // h
362:
363: g.initialize(ecSpec, new SecureRandom());
364:
365: //
366: // a side
367: //
368: KeyPair aKeyPair = g.generateKeyPair();
369:
370: KeyAgreement aKeyAgree = KeyAgreement.getInstance(algorithm,
371: "BC");
372:
373: aKeyAgree.init(aKeyPair.getPrivate());
374:
375: //
376: // b side
377: //
378: KeyPair bKeyPair = g.generateKeyPair();
379:
380: KeyAgreement bKeyAgree = KeyAgreement.getInstance(algorithm,
381: "BC");
382:
383: bKeyAgree.init(bKeyPair.getPrivate());
384:
385: //
386: // agreement
387: //
388: aKeyAgree.doPhase(bKeyPair.getPublic(), true);
389: bKeyAgree.doPhase(aKeyPair.getPublic(), true);
390:
391: BigInteger k1 = new BigInteger(aKeyAgree.generateSecret());
392: BigInteger k2 = new BigInteger(bKeyAgree.generateSecret());
393:
394: if (!k1.equals(k2)) {
395: fail(algorithm + " 2-way test failed");
396: }
397:
398: //
399: // public key encoding test
400: //
401: byte[] pubEnc = aKeyPair.getPublic().getEncoded();
402: KeyFactory keyFac = KeyFactory.getInstance(algorithm, "BC");
403: X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc);
404: ECPublicKey pubKey = (ECPublicKey) keyFac
405: .generatePublic(pubX509);
406:
407: if (!pubKey.getW().equals(
408: ((ECPublicKey) aKeyPair.getPublic()).getW())) {
409: System.out.println(" expected "
410: + pubKey.getW().getAffineX()
411: + " got "
412: + ((ECPublicKey) aKeyPair.getPublic()).getW()
413: .getAffineX());
414: System.out.println(" expected "
415: + pubKey.getW().getAffineY()
416: + " got "
417: + ((ECPublicKey) aKeyPair.getPublic()).getW()
418: .getAffineY());
419: fail(algorithm + " public key encoding (W test) failed");
420: }
421:
422: if (!pubKey.getParams().getGenerator().equals(
423: ((ECPublicKey) aKeyPair.getPublic()).getParams()
424: .getGenerator())) {
425: fail(algorithm + " public key encoding (G test) failed");
426: }
427:
428: //
429: // private key encoding test
430: //
431: byte[] privEnc = aKeyPair.getPrivate().getEncoded();
432: PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc);
433: ECPrivateKey privKey = (ECPrivateKey) keyFac
434: .generatePrivate(privPKCS8);
435:
436: if (!privKey.getS().equals(
437: ((ECPrivateKey) aKeyPair.getPrivate()).getS())) {
438: fail(algorithm + " private key encoding (S test) failed");
439: }
440:
441: if (!privKey.getParams().getGenerator().equals(
442: ((ECPrivateKey) aKeyPair.getPrivate()).getParams()
443: .getGenerator())) {
444: fail(algorithm + " private key encoding (G test) failed");
445: }
446: }
447:
448: private void testExceptions() {
449: try {
450: KeyAgreement aKeyAgree = KeyAgreement.getInstance("DH",
451: "BC");
452:
453: aKeyAgree.generateSecret("DES");
454: } catch (IllegalStateException e) {
455: // okay
456: } catch (Exception e) {
457: fail("Unexpected exception: " + e, e);
458: }
459: }
460:
461: private void testDESAndDESede(BigInteger g, BigInteger p)
462: throws Exception {
463: DHParameterSpec dhParams = new DHParameterSpec(p, g, 256);
464:
465: KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH",
466: "BC");
467:
468: keyGen.initialize(dhParams);
469:
470: KeyPair kp = keyGen.generateKeyPair();
471:
472: KeyAgreement keyAgreement = KeyAgreement
473: .getInstance("DH", "BC");
474:
475: keyAgreement.init(kp.getPrivate());
476: keyAgreement.doPhase(kp.getPublic(), true);
477:
478: SecretKey key = keyAgreement.generateSecret("DES");
479:
480: if (key.getEncoded().length != 8) {
481: fail("DES length wrong");
482: }
483:
484: if (!DESKeySpec.isParityAdjusted(key.getEncoded(), 0)) {
485: fail("DES parity wrong");
486: }
487:
488: key = keyAgreement.generateSecret("DESEDE");
489:
490: if (key.getEncoded().length != 24) {
491: fail("DESEDE length wrong");
492: }
493:
494: if (!DESedeKeySpec.isParityAdjusted(key.getEncoded(), 0)) {
495: fail("DESEDE parity wrong");
496: }
497:
498: key = keyAgreement.generateSecret("Blowfish");
499:
500: if (key.getEncoded().length != 56) {
501: fail("Blowfish length wrong");
502: }
503: }
504:
505: public void performTest() throws Exception {
506: testGP(512, 0, g512, p512);
507: testGP(768, 0, g768, p768);
508: testGP(1024, 0, g1024, p1024);
509: testGP(512, 64, g512, p512);
510: testGP(768, 128, g768, p768);
511: testGP(1024, 256, g1024, p1024);
512: testExplicitWrapping(512, 0, g512, p512);
513: testRandom(256);
514: testECDH("ECDH");
515: testECDH("ECDHC");
516: testExceptions();
517: testDESAndDESede(g768, p768);
518: }
519:
520: public static void main(String[] args) {
521: Security.addProvider(new BouncyCastleProvider());
522:
523: runTest(new DHTest());
524: }
525: }
|