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