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