148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/*
248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Please refer to the LICENSE.txt for licensing details.
448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */
548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpackage ch.ethz.ssh2.crypto.dh;
648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.math.BigInteger;
848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.security.SecureRandom;
948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
1048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.DHGexParameters;
1148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.digest.HashForSSH2Types;
1248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
1348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/**
1448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * DhGroupExchange.
1548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood *
1648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @author Christian Plattner
1748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @version 2.50, 03/15/10
1848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */
1948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpublic class DhGroupExchange
2048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood{
2148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	/* Given by the standard */
2248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
2348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	private BigInteger p;
2448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	private BigInteger g;
2548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
2648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	/* Client public and private */
2748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
2848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	private BigInteger e;
2948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	private BigInteger x;
3048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
3148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	/* Server public */
3248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
3348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	private BigInteger f;
3448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
3548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	/* Shared secret */
3648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
3748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	private BigInteger k;
3848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
3948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	public DhGroupExchange(BigInteger p, BigInteger g)
4048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	{
4148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		this.p = p;
4248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		this.g = g;
4348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	}
4448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
4548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	public void init(SecureRandom rnd)
4648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	{
4748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		k = null;
4848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
4948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		x = new BigInteger(p.bitLength() - 1, rnd);
5048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		e = g.modPow(x, p);
5148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	}
5248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
5348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	/**
5448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	 * @return Returns the e.
5548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	 */
5648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	public BigInteger getE()
5748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	{
5848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		if (e == null)
5948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood			throw new IllegalStateException("Not initialized!");
6048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
6148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		return e;
6248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	}
6348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
6448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	/**
6548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	 * @return Returns the shared secret k.
6648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	 */
6748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	public BigInteger getK()
6848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	{
6948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		if (k == null)
7048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood			throw new IllegalStateException("Shared secret not yet known, need f first!");
7148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
7248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		return k;
7348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	}
7448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
7548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	/**
7648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	 * Sets f and calculates the shared secret.
7748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	 */
7848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	public void setF(BigInteger f)
7948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	{
8048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		if (e == null)
8148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood			throw new IllegalStateException("Not initialized!");
8248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
8348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		BigInteger zero = BigInteger.valueOf(0);
8448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
8548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		if (zero.compareTo(f) >= 0 || p.compareTo(f) <= 0)
8648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood			throw new IllegalArgumentException("Invalid f specified!");
8748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
8848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		this.f = f;
8948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		this.k = f.modPow(x, p);
9048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	}
9148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
9248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload,
9348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood			byte[] serverKexPayload, byte[] hostKey, DHGexParameters para)
9448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	{
9548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		HashForSSH2Types hash = new HashForSSH2Types("SHA1");
9648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
9748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateByteString(clientversion);
9848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateByteString(serverversion);
9948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateByteString(clientKexPayload);
10048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateByteString(serverKexPayload);
10148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateByteString(hostKey);
10248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		if (para.getMin_group_len() > 0)
10348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood			hash.updateUINT32(para.getMin_group_len());
10448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateUINT32(para.getPref_group_len());
10548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		if (para.getMax_group_len() > 0)
10648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood			hash.updateUINT32(para.getMax_group_len());
10748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateBigInt(p);
10848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateBigInt(g);
10948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateBigInt(e);
11048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateBigInt(f);
11148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		hash.updateBigInt(k);
11248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
11348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood		return hash.getDigest();
11448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood	}
11548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood}
116