diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 2b881ac6..c82d4d81 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -1170,28 +1170,29 @@ class Net_SSH2 { // see http://tools.ietf.org/html/rfc2409#section-6.2 and // http://tools.ietf.org/html/rfc2412, appendex E case 'diffie-hellman-group1-sha1': - $p = pack('H256', 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'); - $keyLength = $keyLength < 20 ? $keyLength : 20; - $hash = 'sha1'; + $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . + '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . + '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . + 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'; break; // see http://tools.ietf.org/html/rfc3526#section-3 case 'diffie-hellman-group14-sha1': - $p = pack('H512', 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . - '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'); - $keyLength = $keyLength < 20 ? $keyLength : 20; - $hash = 'sha1'; + $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . + '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . + '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . + 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . + '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . + '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . + 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . + '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'; + break; } - $p = new Math_BigInteger($p, 256); + // For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1 + // the generator field element is 2 (decimal) and the hash function is sha1. + $g = new Math_BigInteger(2); + $prime = new Math_BigInteger($prime, 16); + $kexHash = new Crypt_Hash('sha1'); //$q = $p->bitwise_rightShift(1); /* To increase the speed of the key exchange, both client and server may @@ -1201,14 +1202,12 @@ class Net_SSH2 { [VAN-OORSCHOT]. -- http://tools.ietf.org/html/rfc4419#section-6.2 */ - $q = new Math_BigInteger(1); - $q = $q->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength - $q = $q->subtract(new Math_BigInteger(1)); + $one = new Math_BigInteger(1); + $keyLength = min($keyLength, $kexHash->getLength()); + $max = $one->bitwise_leftShift(16 * $keyLength)->subtract($one); // 2 * 8 * $keyLength - $g = new Math_BigInteger(2); - $x = new Math_BigInteger(); - $x = $x->random(new Math_BigInteger(1), $q); - $e = $g->modPow($x, $p); + $x = $one->random($one, $max); + $e = $g->modPow($x, $prime); $eBytes = $e->toBytes(true); $data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes); @@ -1246,7 +1245,7 @@ class Net_SSH2 { $temp = unpack('Nlength', $this->_string_shift($this->signature, 4)); $this->signature_format = $this->_string_shift($this->signature, $temp['length']); - $key = $f->modPow($x, $p); + $key = $f->modPow($x, $prime); $keyBytes = $key->toBytes(true); $this->exchange_hash = pack('Na*Na*Na*Na*Na*Na*Na*Na*', @@ -1256,7 +1255,7 @@ class Net_SSH2 { $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes ); - $this->exchange_hash = pack('H*', $hash($this->exchange_hash)); + $this->exchange_hash = $kexHash->hash($this->exchange_hash); if ($this->session_id === false) { $this->session_id = $this->exchange_hash; @@ -1455,15 +1454,15 @@ class Net_SSH2 { $this->encrypt->enableContinuousBuffer(); $this->encrypt->disablePadding(); - $iv = pack('H*', $hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id)); + $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id); while ($this->encrypt_block_size > strlen($iv)) { - $iv.= pack('H*', $hash($keyBytes . $this->exchange_hash . $iv)); + $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); } $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size)); - $key = pack('H*', $hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id)); + $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id); while ($encryptKeyLength > strlen($key)) { - $key.= pack('H*', $hash($keyBytes . $this->exchange_hash . $key)); + $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); } $this->encrypt->setKey(substr($key, 0, $encryptKeyLength)); } @@ -1472,15 +1471,15 @@ class Net_SSH2 { $this->decrypt->enableContinuousBuffer(); $this->decrypt->disablePadding(); - $iv = pack('H*', $hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id)); + $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id); while ($this->decrypt_block_size > strlen($iv)) { - $iv.= pack('H*', $hash($keyBytes . $this->exchange_hash . $iv)); + $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); } $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size)); - $key = pack('H*', $hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id)); + $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id); while ($decryptKeyLength > strlen($key)) { - $key.= pack('H*', $hash($keyBytes . $this->exchange_hash . $key)); + $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); } $this->decrypt->setKey(substr($key, 0, $decryptKeyLength)); } @@ -1554,15 +1553,15 @@ class Net_SSH2 { $this->hmac_size = 12; } - $key = pack('H*', $hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id)); + $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id); while ($createKeyLength > strlen($key)) { - $key.= pack('H*', $hash($keyBytes . $this->exchange_hash . $key)); + $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); } $this->hmac_create->setKey(substr($key, 0, $createKeyLength)); - $key = pack('H*', $hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id)); + $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id); while ($checkKeyLength > strlen($key)) { - $key.= pack('H*', $hash($keyBytes . $this->exchange_hash . $key)); + $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); } $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));