001: package ch.ethz.ssh2.crypto.dh;
002:
003: import java.math.BigInteger;
004: import java.security.SecureRandom;
005:
006: import ch.ethz.ssh2.DHGexParameters;
007: import ch.ethz.ssh2.crypto.digest.HashForSSH2Types;
008:
009: /**
010: * DhGroupExchange.
011: *
012: * @author Christian Plattner, plattner@inf.ethz.ch
013: * @version $Id: DhGroupExchange.java,v 1.6 2006/09/20 12:51:37 cplattne Exp $
014: */
015: public class DhGroupExchange {
016: /* Given by the standard */
017:
018: private BigInteger p;
019: private BigInteger g;
020:
021: /* Client public and private */
022:
023: private BigInteger e;
024: private BigInteger x;
025:
026: /* Server public */
027:
028: private BigInteger f;
029:
030: /* Shared secret */
031:
032: private BigInteger k;
033:
034: public DhGroupExchange(BigInteger p, BigInteger g) {
035: this .p = p;
036: this .g = g;
037: }
038:
039: public void init(SecureRandom rnd) {
040: k = null;
041:
042: x = new BigInteger(p.bitLength() - 1, rnd);
043: e = g.modPow(x, p);
044: }
045:
046: /**
047: * @return Returns the e.
048: */
049: public BigInteger getE() {
050: if (e == null)
051: throw new IllegalStateException("Not initialized!");
052:
053: return e;
054: }
055:
056: /**
057: * @return Returns the shared secret k.
058: */
059: public BigInteger getK() {
060: if (k == null)
061: throw new IllegalStateException(
062: "Shared secret not yet known, need f first!");
063:
064: return k;
065: }
066:
067: /**
068: * Sets f and calculates the shared secret.
069: */
070: public void setF(BigInteger f) {
071: if (e == null)
072: throw new IllegalStateException("Not initialized!");
073:
074: BigInteger zero = BigInteger.valueOf(0);
075:
076: if (zero.compareTo(f) >= 0 || p.compareTo(f) <= 0)
077: throw new IllegalArgumentException("Invalid f specified!");
078:
079: this .f = f;
080: this .k = f.modPow(x, p);
081: }
082:
083: public byte[] calculateH(byte[] clientversion,
084: byte[] serverversion, byte[] clientKexPayload,
085: byte[] serverKexPayload, byte[] hostKey,
086: DHGexParameters para) {
087: HashForSSH2Types hash = new HashForSSH2Types("SHA1");
088:
089: hash.updateByteString(clientversion);
090: hash.updateByteString(serverversion);
091: hash.updateByteString(clientKexPayload);
092: hash.updateByteString(serverKexPayload);
093: hash.updateByteString(hostKey);
094: if (para.getMin_group_len() > 0)
095: hash.updateUINT32(para.getMin_group_len());
096: hash.updateUINT32(para.getPref_group_len());
097: if (para.getMax_group_len() > 0)
098: hash.updateUINT32(para.getMax_group_len());
099: hash.updateBigInt(p);
100: hash.updateBigInt(g);
101: hash.updateBigInt(e);
102: hash.updateBigInt(f);
103: hash.updateBigInt(k);
104:
105: return hash.getDigest();
106: }
107: }
|