Merge pull request #117 from bantu/elliptic-curve-preparation

Preparation for ECDH in SSH
This commit is contained in:
terrafrost 2013-06-07 15:24:24 -07:00
commit 2ec8c8c925

View File

@ -1170,28 +1170,29 @@ class Net_SSH2 {
// see http://tools.ietf.org/html/rfc2409#section-6.2 and // see http://tools.ietf.org/html/rfc2409#section-6.2 and
// http://tools.ietf.org/html/rfc2412, appendex E // http://tools.ietf.org/html/rfc2412, appendex E
case 'diffie-hellman-group1-sha1': case 'diffie-hellman-group1-sha1':
$p = pack('H256', 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'); 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
$keyLength = $keyLength < 20 ? $keyLength : 20;
$hash = 'sha1';
break; break;
// see http://tools.ietf.org/html/rfc3526#section-3 // see http://tools.ietf.org/html/rfc3526#section-3
case 'diffie-hellman-group14-sha1': case 'diffie-hellman-group14-sha1':
$p = pack('H512', 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
'98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
'9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
'3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'); '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
$keyLength = $keyLength < 20 ? $keyLength : 20; break;
$hash = 'sha1';
} }
$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); //$q = $p->bitwise_rightShift(1);
/* To increase the speed of the key exchange, both client and server may /* To increase the speed of the key exchange, both client and server may
@ -1201,14 +1202,12 @@ class Net_SSH2 {
[VAN-OORSCHOT]. [VAN-OORSCHOT].
-- http://tools.ietf.org/html/rfc4419#section-6.2 */ -- http://tools.ietf.org/html/rfc4419#section-6.2 */
$q = new Math_BigInteger(1); $one = new Math_BigInteger(1);
$q = $q->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength $keyLength = min($keyLength, $kexHash->getLength());
$q = $q->subtract(new Math_BigInteger(1)); $max = $one->bitwise_leftShift(16 * $keyLength)->subtract($one); // 2 * 8 * $keyLength
$g = new Math_BigInteger(2); $x = $one->random($one, $max);
$x = new Math_BigInteger(); $e = $g->modPow($x, $prime);
$x = $x->random(new Math_BigInteger(1), $q);
$e = $g->modPow($x, $p);
$eBytes = $e->toBytes(true); $eBytes = $e->toBytes(true);
$data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes); $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)); $temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
$this->signature_format = $this->_string_shift($this->signature, $temp['length']); $this->signature_format = $this->_string_shift($this->signature, $temp['length']);
$key = $f->modPow($x, $p); $key = $f->modPow($x, $prime);
$keyBytes = $key->toBytes(true); $keyBytes = $key->toBytes(true);
$this->exchange_hash = pack('Na*Na*Na*Na*Na*Na*Na*Na*', $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 $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) { if ($this->session_id === false) {
$this->session_id = $this->exchange_hash; $this->session_id = $this->exchange_hash;
@ -1455,15 +1454,15 @@ class Net_SSH2 {
$this->encrypt->enableContinuousBuffer(); $this->encrypt->enableContinuousBuffer();
$this->encrypt->disablePadding(); $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)) { 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)); $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)) { 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)); $this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
} }
@ -1472,15 +1471,15 @@ class Net_SSH2 {
$this->decrypt->enableContinuousBuffer(); $this->decrypt->enableContinuousBuffer();
$this->decrypt->disablePadding(); $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)) { 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)); $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)) { 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)); $this->decrypt->setKey(substr($key, 0, $decryptKeyLength));
} }
@ -1554,15 +1553,15 @@ class Net_SSH2 {
$this->hmac_size = 12; $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)) { 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)); $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)) { 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)); $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));