Home | History | Annotate | Download | only in dh
      1 /*
      2  * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
      3  * Please refer to the LICENSE.txt for licensing details.
      4  */
      5 package ch.ethz.ssh2.crypto.dh;
      6 
      7 import java.math.BigInteger;
      8 import java.security.SecureRandom;
      9 
     10 import ch.ethz.ssh2.DHGexParameters;
     11 import ch.ethz.ssh2.crypto.digest.HashForSSH2Types;
     12 
     13 /**
     14  * DhGroupExchange.
     15  *
     16  * @author Christian Plattner
     17  * @version 2.50, 03/15/10
     18  */
     19 public class DhGroupExchange
     20 {
     21 	/* Given by the standard */
     22 
     23 	private BigInteger p;
     24 	private BigInteger g;
     25 
     26 	/* Client public and private */
     27 
     28 	private BigInteger e;
     29 	private BigInteger x;
     30 
     31 	/* Server public */
     32 
     33 	private BigInteger f;
     34 
     35 	/* Shared secret */
     36 
     37 	private BigInteger k;
     38 
     39 	public DhGroupExchange(BigInteger p, BigInteger g)
     40 	{
     41 		this.p = p;
     42 		this.g = g;
     43 	}
     44 
     45 	public void init(SecureRandom rnd)
     46 	{
     47 		k = null;
     48 
     49 		x = new BigInteger(p.bitLength() - 1, rnd);
     50 		e = g.modPow(x, p);
     51 	}
     52 
     53 	/**
     54 	 * @return Returns the e.
     55 	 */
     56 	public BigInteger getE()
     57 	{
     58 		if (e == null)
     59 			throw new IllegalStateException("Not initialized!");
     60 
     61 		return e;
     62 	}
     63 
     64 	/**
     65 	 * @return Returns the shared secret k.
     66 	 */
     67 	public BigInteger getK()
     68 	{
     69 		if (k == null)
     70 			throw new IllegalStateException("Shared secret not yet known, need f first!");
     71 
     72 		return k;
     73 	}
     74 
     75 	/**
     76 	 * Sets f and calculates the shared secret.
     77 	 */
     78 	public void setF(BigInteger f)
     79 	{
     80 		if (e == null)
     81 			throw new IllegalStateException("Not initialized!");
     82 
     83 		BigInteger zero = BigInteger.valueOf(0);
     84 
     85 		if (zero.compareTo(f) >= 0 || p.compareTo(f) <= 0)
     86 			throw new IllegalArgumentException("Invalid f specified!");
     87 
     88 		this.f = f;
     89 		this.k = f.modPow(x, p);
     90 	}
     91 
     92 	public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload,
     93 			byte[] serverKexPayload, byte[] hostKey, DHGexParameters para)
     94 	{
     95 		HashForSSH2Types hash = new HashForSSH2Types("SHA1");
     96 
     97 		hash.updateByteString(clientversion);
     98 		hash.updateByteString(serverversion);
     99 		hash.updateByteString(clientKexPayload);
    100 		hash.updateByteString(serverKexPayload);
    101 		hash.updateByteString(hostKey);
    102 		if (para.getMin_group_len() > 0)
    103 			hash.updateUINT32(para.getMin_group_len());
    104 		hash.updateUINT32(para.getPref_group_len());
    105 		if (para.getMax_group_len() > 0)
    106 			hash.updateUINT32(para.getMax_group_len());
    107 		hash.updateBigInt(p);
    108 		hash.updateBigInt(g);
    109 		hash.updateBigInt(e);
    110 		hash.updateBigInt(f);
    111 		hash.updateBigInt(k);
    112 
    113 		return hash.getDigest();
    114 	}
    115 }
    116