/** * Generates a random BigInteger * * Byte length is equal to $length. Uses \Topxia\Service\Util\Phpsec\Crypt\Random if it's loaded and mt_rand if it's not. * * @access private * @param Integer $length * @return \Topxia\Service\Util\Phpsec\Math\BigInteger */ public function _random_number_helper($size) { if (class_exists('\\Topxia\\Service\\Util\\Phpsec\\Crypt\\Random')) { $random = Random::string($size); } else { $random = ''; if ($size & 1) { $random .= chr(mt_rand(0, 255)); } $blocks = $size >> 1; for ($i = 0; $i < $blocks; ++$i) { // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems $random .= pack('n', mt_rand(0, 0xffff)); } } return new static($random, 256); }
/** * RSA Encrypt * * Returns mod(pow($m, $e), $n), where $n should be the product of two (large) primes $p and $q and where $e * should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that * calls this call modexp, instead, but I think this makes things clearer, maybe... * * @access private * @see \Topxia\Service\Util\Phpsec\Net\SSH1::__construct() * * @param BigInteger $m * @param Array $key * @return BigInteger */ public function _rsa_crypt($m, $key) { /* $rsa = new RSA(); $rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW); $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1); return $rsa->encrypt($m); */ // To quote from protocol-1.5.txt: // The most significant byte (which is only partial as the value must be // less than the public modulus, which is never a power of two) is zero. // // The next byte contains the value 2 (which stands for public-key // encrypted data in the PKCS standard [PKCS#1]). Then, there are non- // zero random bytes to fill any unused space, a zero byte, and the data // to be encrypted in the least significant bytes, the last byte of the // data in the least significant byte. // Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation", // under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL: // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf $modulus = $key[1]->toBytes(); $length = strlen($modulus) - strlen($m) - 3; $random = ''; while (strlen($random) != $length) { $block = Random::string($length - strlen($random)); $block = str_replace("", '', $block); $random .= $block; } $temp = chr(0) . chr(2) . $random . chr(0) . $m; $m = new BigInteger($temp, 256); $m = $m->modPow($key[0], $key[1]); return $m->toBytes(); }
/** * Sends Binary Packets * * See '6. Binary Packet Protocol' of rfc4253 for more info. * * @access private * @see \Topxia\Service\Util\Phpsec\Net\SSH2::_get_binary_packet() * * @param String $data * @param optional String $logged * @return Boolean */ public function _send_binary_packet($data, $logged = null) { if (!is_resource($this->fsock) || feof($this->fsock)) { user_error('Connection closed prematurely'); $this->bitmap = 0; return false; } //if ($this->compress) { // // the -4 removes the checksum: // // http://php.net/function.gzcompress#57710 // $data = substr(gzcompress($data), 0, -4); //} // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9 $packet_length = strlen($data) + 9; // round up to the nearest $this->encrypt_block_size $packet_length += ($this->encrypt_block_size - 1) * $packet_length % $this->encrypt_block_size; // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length $padding_length = $packet_length - strlen($data) - 5; $padding = Random::string($padding_length); // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding); $hmac = $this->hmac_create !== false ? $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)) : ''; $this->send_seq_no++; if ($this->encrypt !== false) { $packet = $this->encrypt->encrypt($packet); } $packet .= $hmac; $start = microtime(true); $result = strlen($packet) == fputs($this->fsock, $packet); $stop = microtime(true); if (defined('NET_SSH2_LOGGING')) { $current = microtime(true); $message_number = isset($this->message_numbers[ord($data[0])]) ? $this->message_numbers[ord($data[0])] : 'UNKNOWN (' . ord($data[0]) . ')'; $message_number = '-> ' . $message_number . ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; $this->_append_log($message_number, isset($logged) ? $logged : $data); $this->last_packet = $current; } return $result; }