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
// 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));