• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.crypto.digest.HashForSSH2Types;
11 import ch.ethz.ssh2.log.Logger;
12 import ch.ethz.ssh2.util.StringEncoder;
13 
14 /**
15  * @author Christian Plattner
16  * @version $Id: DhExchange.java 41 2011-06-02 10:36:41Z dkocher@sudo.ch $
17  */
18 public class DhExchange
19 {
20 	private static final Logger log = Logger.getLogger(DhExchange.class);
21 
22 	/* Given by the standard */
23 
24 	static final BigInteger p1, p14;
25 	static final BigInteger g;
26 
27 	BigInteger p;
28 
29 	/* Client public and private */
30 
31 	BigInteger e;
32 	BigInteger x;
33 
34 	/* Server public */
35 
36 	BigInteger f;
37 
38 	/* Shared secret */
39 
40 	BigInteger k;
41 
42 	static
43 	{
44 		final String p1_string = "17976931348623159077083915679378745319786029604875"
45 				+ "60117064444236841971802161585193689478337958649255415021805654859805036464"
46 				+ "40548199239100050792877003355816639229553136239076508735759914822574862575"
47 				+ "00742530207744771258955095793777842444242661733472762929938766870920560605"
48 				+ "0270810842907692932019128194467627007";
49 
50 		final String p14_string = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129"
51 				+ "024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0"
52 				+ "A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB"
53 				+ "6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A"
54 				+ "163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208"
55 				+ "552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36C"
56 				+ "E3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF69558171"
57 				+ "83995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF";
58 
59 		p1 = new BigInteger(p1_string);
60 		p14 = new BigInteger(p14_string, 16);
61 		g = new BigInteger("2");
62 	}
63 
DhExchange()64 	public DhExchange()
65 	{
66 	}
67 
init(int group, SecureRandom rnd)68 	public void init(int group, SecureRandom rnd)
69 	{
70 		k = null;
71 
72 		if (group == 1)
73 			p = p1;
74 		else if (group == 14)
75 			p = p14;
76 		else
77 			throw new IllegalArgumentException("Unknown DH group " + group);
78 
79 		x = new BigInteger(p.bitLength() - 1, rnd);
80 
81 		e = g.modPow(x, p);
82 	}
83 
84 	/**
85 	 * @return Returns the e.
86 	 * @throws IllegalStateException
87 	 */
getE()88 	public BigInteger getE()
89 	{
90 		if (e == null)
91 			throw new IllegalStateException("DhDsaExchange not initialized!");
92 
93 		return e;
94 	}
95 
96 	/**
97 	 * @return Returns the shared secret k.
98 	 * @throws IllegalStateException
99 	 */
getK()100 	public BigInteger getK()
101 	{
102 		if (k == null)
103 			throw new IllegalStateException("Shared secret not yet known, need f first!");
104 
105 		return k;
106 	}
107 
108 	/**
109 	 * @param f
110 	 */
setF(BigInteger f)111 	public void setF(BigInteger f)
112 	{
113 		if (e == null)
114 			throw new IllegalStateException("DhDsaExchange not initialized!");
115 
116 		BigInteger zero = BigInteger.valueOf(0);
117 
118 		if (zero.compareTo(f) >= 0 || p.compareTo(f) <= 0)
119 			throw new IllegalArgumentException("Invalid f specified!");
120 
121 		this.f = f;
122 		this.k = f.modPow(x, p);
123 	}
124 
calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload, byte[] serverKexPayload, byte[] hostKey)125 	public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload,
126 							 byte[] serverKexPayload, byte[] hostKey)
127 	{
128 		HashForSSH2Types hash = new HashForSSH2Types("SHA1");
129 
130 		if (log.isInfoEnabled())
131 		{
132 			log.info("Client: '" + StringEncoder.GetString(clientversion) + "'");
133 		    log.info("Server: '" + StringEncoder.GetString(serverversion) + "'");
134 		}
135 		hash.updateByteString(clientversion);
136 		hash.updateByteString(serverversion);
137 		hash.updateByteString(clientKexPayload);
138 		hash.updateByteString(serverKexPayload);
139 		hash.updateByteString(hostKey);
140 		hash.updateBigInt(e);
141 		hash.updateBigInt(f);
142 		hash.updateBigInt(k);
143 
144 		return hash.getDigest();
145 	}
146 }
147