01: package org.bouncycastle.crypto.agreement;
02:
03: import java.math.BigInteger;
04: import java.security.SecureRandom;
05:
06: import org.bouncycastle.crypto.CipherParameters;
07: import org.bouncycastle.crypto.params.DHParameters;
08: import org.bouncycastle.crypto.params.DHPublicKeyParameters;
09: import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
10: import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
11: import org.bouncycastle.crypto.params.ParametersWithRandom;
12:
13: /**
14: * a Diffie-Hellman key exchange engine.
15: * <p>
16: * note: This uses MTI/A0 key agreement in order to make the key agreement
17: * secure against passive attacks. If you're doing Diffie-Hellman and both
18: * parties have long term public keys you should look at using this. For
19: * further information have a look at RFC 2631.
20: * <p>
21: * It's possible to extend this to more than two parties as well, for the moment
22: * that is left as an exercise for the reader.
23: */
24: public class DHAgreement {
25: private DHPrivateKeyParameters key;
26: private DHParameters dhParams;
27: private BigInteger privateValue;
28: private SecureRandom random;
29:
30: public void init(CipherParameters param) {
31: AsymmetricKeyParameter kParam;
32:
33: if (param instanceof ParametersWithRandom) {
34: ParametersWithRandom rParam = (ParametersWithRandom) param;
35:
36: this .random = rParam.getRandom();
37: kParam = (AsymmetricKeyParameter) rParam.getParameters();
38: } else {
39: this .random = new SecureRandom();
40: kParam = (AsymmetricKeyParameter) param;
41: }
42:
43: if (!(kParam instanceof DHPrivateKeyParameters)) {
44: throw new IllegalArgumentException(
45: "DHEngine expects DHPrivateKeyParameters");
46: }
47:
48: this .key = (DHPrivateKeyParameters) kParam;
49: this .dhParams = key.getParameters();
50: }
51:
52: /**
53: * calculate our initial message.
54: */
55: public BigInteger calculateMessage() {
56: int bits = dhParams.getP().bitLength() - 1;
57:
58: // TODO Should the generated numbers always have length 'p.bitLength() - 1'?
59: this .privateValue = new BigInteger(bits, random)
60: .setBit(bits - 1);
61:
62: return dhParams.getG().modPow(privateValue, dhParams.getP());
63: }
64:
65: /**
66: * given a message from a given party and the corresponding public key,
67: * calculate the next message in the agreement sequence. In this case
68: * this will represent the shared secret.
69: */
70: public BigInteger calculateAgreement(DHPublicKeyParameters pub,
71: BigInteger message) {
72: if (!pub.getParameters().equals(dhParams)) {
73: throw new IllegalArgumentException(
74: "Diffie-Hellman public key has wrong parameters.");
75: }
76:
77: return message.modPow(key.getX(), dhParams.getP()).multiply(
78: pub.getY().modPow(privateValue, dhParams.getP())).mod(
79: dhParams.getP());
80: }
81: }
|