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