예제 #1
0
파일: crypt.php 프로젝트: ppschweiz/vvvote
 static function verifySigKey($hash, $sig, $pubkey)
 {
     $rsa = new rsaMyExts();
     $rsa->loadKey($pubkey);
     $hashBI = new Math_BigInteger($hash, 16);
     $sigBI = new Math_BigInteger($sig, 16);
     if ($sigBI->compare($rsa->zero) < 0 || $sigBI->compare($rsa->modulus) > 0) {
         return false;
     }
     // the signature has more bits than the modulus --> the signature cannot has been created by the given key and the exponentiation cannot be performed.
     $verify = $rsa->_rsaep($sigBI);
     if ($hashBI->equals($verify)) {
         return true;
     }
     WrongRequestException::throwException(1001, "Error: signature verifcation failed", "verifySig: given hash: {$hash}, calculated hash: " . $verify->toHex());
 }
예제 #2
0
 public function compareTo($id)
 {
     $logid = $id;
     $val1 = new Math_BigInteger($this->mInt);
     $val2 = new Math_BigInteger($logid->mInt);
     if ($val1->compare($val2) < 0) {
         return -1;
     } else {
         if ($val1->compare($val2) > 0) {
             return 1;
         } else {
             if (strcmp($this->mSessionId, $logid->mSessionId) < 0) {
                 return -1;
             } else {
                 if (strcmp($this->mSessionId, $logid->mSessionId) > 0) {
                     return 1;
                 }
             }
         }
     }
     return 0;
 }
예제 #3
0
function ssh1_connect($host, $port)
{
    $identifier = 'SSH-1.5-' . basename(__FILE__);
    $fsock = fsockopen($host, $port, $errno, $errstr, 10);
    if (!$fsock) {
        die("Error {$errno}: {$errstr}");
    }
    $init_line = fgets($fsock, 255);
    if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
        die('Not an SSH server on the other side.');
    }
    if ($parts[1][0] != 1) {
        die("SSH version {$parts[1]} is not supported!");
    }
    echo "Connecting to {$init_line}\r\n";
    fputs($fsock, "{$identifier}\n");
    $packet = get_binary_packet($fsock);
    if ($packet['type'] != SSH_SMSG_PUBLIC_KEY) {
        die('Expected SSH_SMSG_PUBLIC_KEY!');
    }
    $anti_spoofing_cookie = string_shift($packet['data'], 8);
    string_shift($packet['data'], 4);
    $temp = unpack('nlen', string_shift($packet['data'], 2));
    $server_key_public_exponent = new Math_BigInteger(string_shift($packet['data'], ceil($temp['len'] / 8)), 256);
    $temp = unpack('nlen', string_shift($packet['data'], 2));
    $server_key_public_modulus = new Math_BigInteger(string_shift($packet['data'], ceil($temp['len'] / 8)), 256);
    $temp = unpack('nlen', string_shift($packet['data'], 2));
    $host_key_public_exponent = new Math_BigInteger(string_shift($packet['data'], ceil($temp['len'] / 8)), 256);
    $temp = unpack('nlen', string_shift($packet['data'], 2));
    $host_key_public_modulus = new Math_BigInteger(string_shift($packet['data'], ceil($temp['len'] / 8)), 256);
    $session_id = pack('H*', md5($host_key_public_modulus . $server_key_public_modulus . $anti_spoofing_cookie));
    // ought to use a cryptographically secure random number generator (which mt_srand is not)
    list($sec, $usec) = explode(' ', microtime());
    mt_srand((double) $sec + (double) $usec * 100000);
    $session_key = '';
    for ($i = 0; $i < 32; $i++) {
        $session_key .= chr(mt_rand(0, 255));
    }
    $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
    echo "starting rsa encryption\r\n\r\n";
    if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
        $prepped_key = prep_session_key($double_encrypted_session_key, $server_key_public_modulus);
        rsa_crypt($prepped_key, array($server_key_public_exponent, $server_key_public_modulus));
        rsa_crypt2($prepped_key, array($server_key_public_exponent, $server_key_public_modulus));
    } else {
        $prepped_key = prep_session_key($double_encrypted_session_key, $host_key_public_modulus);
        rsa_crypt($prepped_key, array($host_key_public_exponent, $host_key_public_modulus));
        rsa_crypt2($prepped_key, array($host_key_public_exponent, $host_key_public_modulus));
    }
}
예제 #4
0
 /**
  * Generate a random prime number.
  *
  * If there's not a prime within the given range, false will be returned.  If more than $timeout seconds have elapsed,
  * give up and return false.
  *
  * @param optional Integer $min
  * @param optional Integer $max
  * @param optional Integer $timeout
  * @return Math_BigInteger
  * @access public
  * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
  */
 function randomPrime($min = false, $max = false, $timeout = false)
 {
     if ($min === false) {
         $min = new Math_BigInteger(0);
     }
     if ($max === false) {
         $max = new Math_BigInteger(0x7fffffff);
     }
     $compare = $max->compare($min);
     if (!$compare) {
         return $min->isPrime() ? $min : false;
     } else {
         if ($compare < 0) {
             // if $min is bigger then $max, swap $min and $max
             $temp = $max;
             $max = $min;
             $min = $temp;
         }
     }
     static $one, $two;
     if (!isset($one)) {
         $one = new Math_BigInteger(1);
         $two = new Math_BigInteger(2);
     }
     $start = time();
     $x = $this->random($min, $max);
     if ($x->equals($two)) {
         return $x;
     }
     $x->_make_odd();
     if ($x->compare($max) > 0) {
         // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range
         if ($min->equals($max)) {
             return false;
         }
         $x = $min->copy();
         $x->_make_odd();
     }
     $initial_x = $x->copy();
     while (true) {
         if ($timeout !== false && time() - $start > $timeout) {
             return false;
         }
         if ($x->isPrime()) {
             return $x;
         }
         $x = $x->add($two);
         if ($x->compare($max) > 0) {
             $x = $min->copy();
             if ($x->equals($two)) {
                 return $x;
             }
             $x->_make_odd();
         }
         if ($x->equals($initial_x)) {
             return false;
         }
     }
 }
예제 #5
0
 /**
  * generation of a position, logoot algorithm
  * @param <Object> $start is the previous logootPosition
  * @param <Object> $end is the next logootPosition
  * @param <Integer> $N number of positions generated (should be 1 in our case)
  * @param <Object> $sid session id
  * @return <Object> a logootPosition between $start and $end
  */
 private function getLogootPosition($start, $end, $N, $sid)
 {
     $result = array();
     $Id_Max = LogootId::IdMax();
     $Id_Min = LogootId::IdMin();
     $i = 0;
     $pos = array();
     $currentPosition = new LogootPosition($pos);
     // voir constructeur
     $inf = new Math_BigInteger("0");
     $sup = new Math_BigInteger("0");
     $isInf = false;
     while (true) {
         $inf = new Math_BigInteger($start->get($i)->getInt());
         if ($isInf == true) {
             $sup = new Math_BigInteger(INT_MAX);
         } else {
             $sup = new Math_BigInteger($end->get($i)->getInt());
         }
         $tmpVal = $sup->subtract($inf);
         $tmpVal1 = $tmpVal->subtract(new Math_BigInteger("1"));
         if ($tmpVal1->compare($N) > 0) {
             //				inf = start.get(i).getInteger();
             //				sup = end.get(i).getInteger();
             break;
         }
         $currentPosition->add($start->get($i));
         $i++;
         if ($i == $start->size()) {
             $start->add($Id_Min);
         }
         if ($i == $end->size()) {
             $end->add($Id_Max);
         }
         if ($inf->compare($sup) < 0) {
             $isInf = true;
         }
     }
     $binf = $inf->add(new Math_BigInteger("1"));
     $bsup = $sup->subtract(new Math_BigInteger("1"));
     $slot = $bsup->subtract($binf);
     $stepTmp = $slot->divide($N);
     $step = $stepTmp[0];
     // quotient, [1] is the remainder
     $old = clone $currentPosition;
     if ($step->compare(new Math_BigInteger(INT_MAX)) > 0) {
         $lstep = new Math_BigInteger(INT_MAX);
         $r = clone $currentPosition;
         $tmpVal2 = $inf->random($inf, $sup);
         $r->set($i, $tmpVal2->toString(), $sid);
         $result[] = $r;
         // result est une arraylist<Position>
         return $result;
     } else {
         $lstep = $step;
     }
     if ($lstep->compare(new Math_BigInteger("0")) == 0) {
         $lstep = new Math_BigInteger("1");
     }
     $p = clone $currentPosition;
     $p->set($i, $inf->toString(), $sid);
     $tmpVal3 = (int) $N->toString();
     for ($j = 0; $j < $tmpVal3; $j++) {
         $r = clone $p;
         if (!($lstep->compare(new Math_BigInteger("1")) == 0)) {
             $tmpVal4 = new Math_BigInteger($p->get($i)->getInt());
             $tmpVal5 = $tmpVal4->add($lstep);
             // max
             $tmpVal6 = new Math_BigInteger($p->get($i)->getInt());
             // min
             $add = $tmpVal6->random($tmpVal6, $tmpVal5);
             $r->set($i, $add->toString(), $sid);
         } else {
             $r->add1($i, new Math_BigInteger("1"), $sid);
         }
         $result[] = clone $r;
         // voir
         $old = clone $r;
         $tmpVal7 = new Math_BigInteger($p->get($i)->getInt());
         $tmpVal7 = $tmpVal7->add($lstep);
         $p->set($i, $tmpVal7->toString(), $sid);
     }
     return $result;
 }
예제 #6
0
파일: BigInteger.php 프로젝트: hala54/DSMW
 /**
  * Generate a random number
  *
  * $generator should be the name of a random number generating function whose first parameter is the minimum
  * value and whose second parameter is the maximum value.  If this function needs to be seeded, it should be
  * done before this function is called.
  *
  * @param optional Integer $min
  * @param optional Integer $max
  * @param optional String $generator
  * @return Math_BigInteger
  * @access public
  */
 function random(Math_BigInteger $min = NULL, Math_BigInteger $max = NULL, $generator = 'mt_rand')
 {
     if ($min === NULL) {
         $min = new Math_BigInteger(0);
     }
     /*
      * @author muller jean-philippe
      * This condition is used to exclude the min value from the possible
      *values returned by this random
      */
     /*else {
           $min = $min->add(new Math_BigInteger(1));
       }*/
     // end of modification
     if ($max === NULL) {
         $max = new Math_BigInteger(0x7fffffff);
     }
     $compare = $max->compare($min);
     if (!$compare) {
         return $min;
     } else {
         if ($compare < 0) {
             // if $min is bigger then $max, swap $min and $max
             $temp = $max;
             $max = $min;
             $min = $temp;
         }
     }
     $max = $max->subtract($min);
     $max = ltrim($max->toBytes(), chr(0));
     $size = strlen($max) - 1;
     $random = '';
     $bytes = $size & 3;
     for ($i = 0; $i < $bytes; $i++) {
         $random .= chr($generator(0, 255));
     }
     $blocks = $size >> 2;
     for ($i = 0; $i < $blocks; $i++) {
         $random .= pack('N', $generator(-2147483648.0, 0x7fffffff));
     }
     $temp = new Math_BigInteger($random, 256);
     if ($temp->compare(new Math_BigInteger(substr($max, 1), 256)) > 0) {
         $random = chr($generator(0, ord($max[0]) - 1)) . $random;
     } else {
         $random = chr($generator(0, ord($max[0]))) . $random;
     }
     $random = new Math_BigInteger($random, 256);
     return $random->add($min);
 }
예제 #7
0
 /**
  * Generate a random prime number.
  *
  * If there's not a prime within the given range, false will be returned.
  * If more than $timeout seconds have elapsed, give up and return false.
  *
  * @param Math_BigInteger $arg1
  * @param Math_BigInteger $arg2
  * @param int $timeout
  * @return Math_BigInteger|false
  * @access public
  * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
  */
 function randomPrime($arg1, $arg2 = false, $timeout = false)
 {
     if ($arg1 === false) {
         return false;
     }
     if ($arg2 === false) {
         $max = $arg1;
         $min = $this;
     } else {
         $min = $arg1;
         $max = $arg2;
     }
     $compare = $max->compare($min);
     if (!$compare) {
         return $min->isPrime() ? $min : false;
     } elseif ($compare < 0) {
         // if $min is bigger then $max, swap $min and $max
         $temp = $max;
         $max = $min;
         $min = $temp;
     }
     static $one, $two;
     if (!isset($one)) {
         $one = new Math_BigInteger(1);
         $two = new Math_BigInteger(2);
     }
     $start = time();
     $x = $this->random($min, $max);
     // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
     if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && extension_loaded('gmp') && version_compare(PHP_VERSION, '5.2.0', '>=')) {
         $p = new Math_BigInteger();
         $p->value = gmp_nextprime($x->value);
         if ($p->compare($max) <= 0) {
             return $p;
         }
         if (!$min->equals($x)) {
             $x = $x->subtract($one);
         }
         return $x->randomPrime($min, $x);
     }
     if ($x->equals($two)) {
         return $x;
     }
     $x->_make_odd();
     if ($x->compare($max) > 0) {
         // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range
         if ($min->equals($max)) {
             return false;
         }
         $x = $min->copy();
         $x->_make_odd();
     }
     $initial_x = $x->copy();
     while (true) {
         if ($timeout !== false && time() - $start > $timeout) {
             return false;
         }
         if ($x->isPrime()) {
             return $x;
         }
         $x = $x->add($two);
         if ($x->compare($max) > 0) {
             $x = $min->copy();
             if ($x->equals($two)) {
                 return $x;
             }
             $x->_make_odd();
         }
         if ($x->equals($initial_x)) {
             return false;
         }
     }
 }
예제 #8
0
 /**
  * Connect to an SSHv1 server
  *
  * @return Boolean
  * @access private
  */
 function _connect()
 {
     $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
     if (!$this->fsock) {
         user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error {$errno}. {$errstr}"));
         return false;
     }
     $this->server_identification = $init_line = fgets($this->fsock, 255);
     if (defined('NET_SSH1_LOGGING')) {
         $this->_append_log('<-', $this->server_identification);
         $this->_append_log('->', $this->identifier . "\r\n");
     }
     if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
         user_error('Can only connect to SSH servers');
         return false;
     }
     if ($parts[1][0] != 1) {
         user_error("Cannot connect to SSH {$parts['1']} servers");
         return false;
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         user_error('Expected SSH_SMSG_PUBLIC_KEY');
         return false;
     }
     $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_ciphers as $mask => $name) {
         if (($supported_ciphers_mask & 1 << $mask) == 0) {
             unset($this->supported_ciphers[$mask]);
         }
     }
     // get a list of the supported authentications
     extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = crypt_random_string(32);
     $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
     if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
     } else {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
     }
     $cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : NET_SSH1_CIPHER_3DES;
     $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
     if (!$this->_send_binary_packet($data)) {
         user_error('Error sending SSH_CMSG_SESSION_KEY');
         return false;
     }
     switch ($cipher) {
         //case NET_SSH1_CIPHER_NONE:
         //    $this->crypto = new Crypt_Null();
         //    break;
         case NET_SSH1_CIPHER_DES:
             if (!class_exists('Crypt_DES')) {
                 include_once 'Crypt/DES.php';
             }
             $this->crypto = new Crypt_DES();
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             break;
         case NET_SSH1_CIPHER_3DES:
             if (!class_exists('Crypt_TripleDES')) {
                 include_once 'Crypt/TripleDES.php';
             }
             $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             break;
             //case NET_SSH1_CIPHER_RC4:
             //    if (!class_exists('Crypt_RC4')) {
             //        include_once 'Crypt/RC4.php';
             //    }
             //    $this->crypto = new Crypt_RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         user_error('Expected SSH_SMSG_SUCCESS');
         return false;
     }
     $this->bitmap = NET_SSH1_MASK_CONNECTED;
     return true;
 }
예제 #9
0
파일: biginteger.php 프로젝트: thu0ng91/jmc
 /**
  * Barrett Modular Reduction
  *
  * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
  * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information.  Modified slightly,
  * so as not to require negative numbers (initially, this script didn't support negative numbers).
  *
  * @see _slidingWindow()
  * @access private
  * @param Math_BigInteger
  * @return Math_BigInteger
  */
 function _barrett($n)
 {
     static $cache;
     $n_length = count($n->value);
     if (!isset($cache[MATH_BIGINTEGER_VARIABLE]) || $n->compare($cache[MATH_BIGINTEGER_VARIABLE])) {
         $cache[MATH_BIGINTEGER_VARIABLE] = $n;
         $temp = new Math_BigInteger();
         $temp->value = $this->_array_repeat(0, 2 * $n_length);
         $temp->value[] = 1;
         list($cache[MATH_BIGINTEGER_DATA], ) = $temp->divide($n);
     }
     $temp = new Math_BigInteger();
     $temp->value = array_slice($this->value, $n_length - 1);
     $temp = $temp->multiply($cache[MATH_BIGINTEGER_DATA]);
     $temp->value = array_slice($temp->value, $n_length + 1);
     $result = new Math_BigInteger();
     $result->value = array_slice($this->value, 0, $n_length + 1);
     $temp = $temp->multiply($n);
     $temp->value = array_slice($temp->value, 0, $n_length + 1);
     if ($result->compare($temp) < 0) {
         $corrector = new Math_BigInteger();
         $corrector->value = $this->_array_repeat(0, $n_length + 1);
         $corrector->value[] = 1;
         $result = $result->add($corrector);
     }
     $result = $result->subtract($temp);
     while ($result->compare($n) > 0) {
         $result = $result->subtract($n);
     }
     return $result;
 }
예제 #10
0
 /**
  * Get the index of a revoked certificate.
  *
  * @param array $rclist        	
  * @param String $serial        	
  * @param Boolean $create
  *        	optional
  * @access private
  * @return Integer or false
  */
 function _revokedCertificate(&$rclist, $serial, $create = false)
 {
     $serial = new Math_BigInteger($serial);
     foreach ($rclist as $i => $rc) {
         if (!$serial->compare($rc['userCertificate'])) {
             return $i;
         }
     }
     if (!$create) {
         return false;
     }
     $i = count($rclist);
     $rclist[] = array('userCertificate' => $serial, 'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O')));
     return $i;
 }
예제 #11
0
파일: SSH1.php 프로젝트: heliopsis/eZCopy
 /**
  * Default Constructor.
  *
  * Connects to an SSHv1 server
  *
  * @param String $host
  * @param optional Integer $port
  * @param optional Integer $timeout
  * @param optional Integer $cipher
  * @return Net_SSH1
  * @access public
  */
 function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
 {
     $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
     if (!$this->fsock) {
         user_error(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"), E_USER_NOTICE);
         return;
     }
     $this->server_identification = $init_line = fgets($this->fsock, 255);
     if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
         user_error('Can only connect to SSH servers', E_USER_NOTICE);
         return;
     }
     if ($parts[1][0] != 1) {
         user_error("Cannot connect to SSH {$parts['1']} servers", E_USER_NOTICE);
         return;
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         user_error('Expected SSH_SMSG_PUBLIC_KEY', E_USER_NOTICE);
         return;
     }
     $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     list(, $supported_ciphers_mask) = unpack('N', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4));
     foreach ($this->supported_ciphers as $mask => $name) {
         if (($supported_ciphers_mask & 1 << $mask) == 0) {
             unset($this->supported_ciphers[$mask]);
         }
     }
     // get a list of the supported authentications
     list(, $supported_authentications_mask) = unpack('N', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = '';
     for ($i = 0; $i < 32; $i++) {
         $session_key .= chr(crypt_random(0, 255));
     }
     $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
     if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
     } else {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
     }
     $cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;
     $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
     if (!$this->_send_binary_packet($data)) {
         user_error('Error sending SSH_CMSG_SESSION_KEY', E_USER_NOTICE);
         return;
     }
     switch ($cipher) {
         //case NET_SSH1_CIPHER_NONE:
         //    $this->crypto = new Crypt_Null();
         //    break;
         case NET_SSH1_CIPHER_DES:
             $this->crypto = new Crypt_DES();
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             break;
         case NET_SSH1_CIPHER_3DES:
             $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             break;
             //case NET_SSH1_CIPHER_RC4:
             //    $this->crypto = new Crypt_RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);
         return;
     }
     $this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;
 }
예제 #12
0
 /**
  * Default Constructor.
  *
  * Connects to an SSHv1 server
  *
  * @param String $host
  * @param optional Integer $port
  * @param optional Integer $timeout
  * @param optional Integer $cipher
  * @return Net_SSH1
  * @access public
  */
 function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
 {
     if (!class_exists('Math_BigInteger')) {
         include_once EASYWIDIR . '/third_party/phpseclib/Math/BigInteger.php';
     }
     // Include Crypt_Random
     // the class_exists() will only be called if the crypt_random_string function hasn't been defined and
     // will trigger a call to __autoload() if you're wanting to auto-load classes
     // call function_exists() a second time to stop the include_once from being called outside
     // of the auto loader
     if (!function_exists('crypt_random_string') && !class_exists('Crypt_Random') && !function_exists('crypt_random_string')) {
         include_once EASYWIDIR . '/third_party/phpseclib/Crypt/Random.php';
     }
     $this->protocol_flags = array(1 => 'NET_SSH1_MSG_DISCONNECT', 2 => 'NET_SSH1_SMSG_PUBLIC_KEY', 3 => 'NET_SSH1_CMSG_SESSION_KEY', 4 => 'NET_SSH1_CMSG_USER', 9 => 'NET_SSH1_CMSG_AUTH_PASSWORD', 10 => 'NET_SSH1_CMSG_REQUEST_PTY', 12 => 'NET_SSH1_CMSG_EXEC_SHELL', 13 => 'NET_SSH1_CMSG_EXEC_CMD', 14 => 'NET_SSH1_SMSG_SUCCESS', 15 => 'NET_SSH1_SMSG_FAILURE', 16 => 'NET_SSH1_CMSG_STDIN_DATA', 17 => 'NET_SSH1_SMSG_STDOUT_DATA', 18 => 'NET_SSH1_SMSG_STDERR_DATA', 19 => 'NET_SSH1_CMSG_EOF', 20 => 'NET_SSH1_SMSG_EXITSTATUS', 33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION');
     $this->_define_array($this->protocol_flags);
     $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
     if (!$this->fsock) {
         user_error(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"));
         return;
     }
     $this->server_identification = $init_line = fgets($this->fsock, 255);
     if (defined('NET_SSH1_LOGGING')) {
         $this->_append_log('<-', $this->server_identification);
         $this->_append_log('->', $this->identifier . "\r\n");
     }
     if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
         user_error('Can only connect to SSH servers');
         return;
     }
     if ($parts[1][0] != 1) {
         user_error("Cannot connect to SSH {$parts['1']} servers");
         return;
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         user_error('Expected SSH_SMSG_PUBLIC_KEY');
         return;
     }
     $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_ciphers as $mask => $name) {
         if (($supported_ciphers_mask & 1 << $mask) == 0) {
             unset($this->supported_ciphers[$mask]);
         }
     }
     // get a list of the supported authentications
     extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = crypt_random_string(32);
     $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
     if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
     } else {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
     }
     $cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;
     $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
     if (!$this->_send_binary_packet($data)) {
         user_error('Error sending SSH_CMSG_SESSION_KEY');
         return;
     }
     switch ($cipher) {
         //case NET_SSH1_CIPHER_NONE:
         //    $this->crypto = new Crypt_Null();
         //    break;
         case NET_SSH1_CIPHER_DES:
             if (!class_exists('Crypt_DES')) {
                 include_once EASYWIDIR . '/third_party/phpseclib/Crypt/DES.php';
             }
             $this->crypto = new Crypt_DES();
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             break;
         case NET_SSH1_CIPHER_3DES:
             if (!class_exists('Crypt_TripleDES')) {
                 include_once EASYWIDIR . '/third_party/phpseclib/Crypt/TripleDES.php';
             }
             $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             break;
             //case NET_SSH1_CIPHER_RC4:
             //    if (!class_exists('Crypt_RC4')) {
             //        include_once('Crypt/RC4.php');
             //    }
             //    $this->crypto = new Crypt_RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         user_error('Expected SSH_SMSG_SUCCESS');
         return;
     }
     $this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;
 }
 /**
  * Compares abs($num1) to abs($num2).
  * Returns:
  *   -1, if abs($num1) < abs($num2)
  *   0, if abs($num1) == abs($num2)
  *   1, if abs($num1) > abs($num2)
  *
  * @param string $num1
  * @param string $num2
  * @return int
  * @access public
  */
 function cmpAbs($num1, $num2)
 {
     //strip minus
     $num1 = $this->strip_minus($num1);
     $num2 = $this->strip_minus($num2);
     $num1 = new Math_BigInteger($num1, 10);
     $num2 = new Math_BigInteger($num2, 10);
     return $num1->compare($num2);
     /*        $this->strip_minus($num1);
             $num2 = $this->strip_minus($num2);
             $strlen1 = _byte_strlen($num1);
             $strlen2 = _byte_strlen($num2);
             if($strlen1 < $strlen2)
             {
                 return -1;
             }
             else if($strlen1 > $strlen2)
             {
                 return 1;
             }
             else
             {
                 for($i =0; $i < $strlen1; $i+)
                 {
                     if($num1[$i] < $num2[$i])
                     {
                         return -1;
                     }
                     else if($num1[$i] > $num2[$i])
                     {
                         return 1;
                     }
                 }
                 return 0;
             }
     */
 }
예제 #14
0
 public function randomPrime($min = false, $max = false, $timeout = false)
 {
     if ($min === false) {
         $min = new Math_BigInteger(0);
     }
     if ($max === false) {
         $max = new Math_BigInteger(2147483647);
     }
     $compare = $max->compare($min);
     if (!$compare) {
         return $min->isPrime() ? $min : false;
     } else {
         if ($compare < 0) {
             $temp = $max;
             $max = $min;
             $min = $temp;
         }
     }
     static $one;
     static $two;
     if (!isset($one)) {
         $one = new Math_BigInteger(1);
         $two = new Math_BigInteger(2);
     }
     $start = time();
     $x = $this->random($min, $max);
     if ($x->equals($two)) {
         return $x;
     }
     $x->_make_odd();
     if (0 < $x->compare($max)) {
         if ($min->equals($max)) {
             return false;
         }
         $x = $min->copy();
         $x->_make_odd();
     }
     $initial_x = $x->copy();
     while (true) {
         if ($timeout !== false && $timeout < time() - $start) {
             return false;
         }
         if ($x->isPrime()) {
             return $x;
         }
         $x = $x->add($two);
         if (0 < $x->compare($max)) {
             $x = $min->copy();
             if ($x->equals($two)) {
                 return $x;
             }
             $x->_make_odd();
         }
         if ($x->equals($initial_x)) {
             return false;
         }
     }
 }
예제 #15
0
 /**
  * Compare two arbitrary precision numbers
  *
  * @param string $a The left operand, as a string.
  * @param string $b The right operand, as a string.
  * @access public
  * @return int Returns 0 if the two operands are equal, 1 if the left_operand is larger than the right_operand, -1 otherwise.
  */
 public function cmp($a, $b)
 {
     $a = new Math_BigInteger($a);
     $b = new Math_BigInteger($b);
     $c = $a->compare($b);
     return $c;
 }
예제 #16
0
 /**
  * RSAVP1
  *
  * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
  *
  * @access private
  * @param Math_BigInteger $s
  * @return Math_BigInteger
  */
 function _rsavp1($s)
 {
     if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) {
         throw new VerificationException('Signature representative out of range');
         return false;
     }
     return $this->_exponentiate($s);
 }
예제 #17
0
 /**
  * Default Constructor.
  *
  * Connects to an SSHv1 server
  *
  * @param String $host
  * @param optional Integer $port
  * @param optional Integer $timeout
  * @param optional Integer $cipher
  * @return Net_SSH1
  * @access public
  */
 function __construct($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
 {
     $this->protocol_flags = array(1 => 'NET_SSH1_MSG_DISCONNECT', 2 => 'NET_SSH1_SMSG_PUBLIC_KEY', 3 => 'NET_SSH1_CMSG_SESSION_KEY', 4 => 'NET_SSH1_CMSG_USER', 9 => 'NET_SSH1_CMSG_AUTH_PASSWORD', 10 => 'NET_SSH1_CMSG_REQUEST_PTY', 12 => 'NET_SSH1_CMSG_EXEC_SHELL', 13 => 'NET_SSH1_CMSG_EXEC_CMD', 14 => 'NET_SSH1_SMSG_SUCCESS', 15 => 'NET_SSH1_SMSG_FAILURE', 16 => 'NET_SSH1_CMSG_STDIN_DATA', 17 => 'NET_SSH1_SMSG_STDOUT_DATA', 18 => 'NET_SSH1_SMSG_STDERR_DATA', 19 => 'NET_SSH1_CMSG_EOF', 20 => 'NET_SSH1_SMSG_EXITSTATUS', 33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION');
     $this->_define_array($this->protocol_flags);
     $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
     if (!$this->fsock) {
         user_error(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"), E_USER_NOTICE);
         return;
     }
     $this->server_identification = $init_line = fgets($this->fsock, 255);
     if (defined('NET_SSH1_LOGGING')) {
         $this->protocol_flags_log[] = '<-';
         $this->protocol_flags_log[] = '->';
         if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
             $this->message_log[] = $this->server_identification;
             $this->message_log[] = $this->identifier . "\r\n";
         }
     }
     if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
         user_error('Can only connect to SSH servers', E_USER_NOTICE);
         return;
     }
     if ($parts[1][0] != 1) {
         user_error("Cannot connect to SSH {$parts['1']} servers", E_USER_NOTICE);
         return;
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         user_error('Expected SSH_SMSG_PUBLIC_KEY', E_USER_NOTICE);
         return;
     }
     $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_ciphers as $mask => $name) {
         if (($supported_ciphers_mask & 1 << $mask) == 0) {
             unset($this->supported_ciphers[$mask]);
         }
     }
     // get a list of the supported authentications
     extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = '';
     for ($i = 0; $i < 32; $i++) {
         $session_key .= chr(crypt_random(0, 255));
     }
     $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
     if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
     } else {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
     }
     $cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;
     $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
     if (!$this->_send_binary_packet($data)) {
         user_error('Error sending SSH_CMSG_SESSION_KEY', E_USER_NOTICE);
         return;
     }
     switch ($cipher) {
         //case NET_SSH1_CIPHER_NONE:
         //    $this->crypto = new Crypt_Null();
         //    break;
         case NET_SSH1_CIPHER_DES:
             $this->crypto = new Crypt_DES();
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             break;
         case NET_SSH1_CIPHER_3DES:
             $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             break;
             //case NET_SSH1_CIPHER_RC4:
             //    $this->crypto = new Crypt_RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);
         return;
     }
     $this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;
 }
예제 #18
0
 /**
  * Generate a random number
  *
  * @param optional Integer $min
  * @param optional Integer $max
  * @return Math_BigInteger
  * @access public
  */
 function random($min = false, $max = false)
 {
     if ($min === false) {
         $min = new Math_BigInteger(0);
     }
     if ($max === false) {
         $max = new Math_BigInteger(0x7fffffff);
     }
     $compare = $max->compare($min);
     if (!$compare) {
         return $this->_normalize($min);
     } else {
         if ($compare < 0) {
             // if $min is bigger then $max, swap $min and $max
             $temp = $max;
             $max = $min;
             $min = $temp;
         }
     }
     $generator = $this->generator;
     $max = $max->subtract($min);
     $max = ltrim($max->toBytes(), chr(0));
     $size = strlen($max) - 1;
     $crypt_random = function_exists('crypt_random_string') || !class_exists('Crypt_Random') && function_exists('crypt_random_string');
     if ($crypt_random) {
         $random = crypt_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));
         }
     }
     $fragment = new Math_BigInteger($random, 256);
     $leading = $fragment->compare(new Math_BigInteger(substr($max, 1), 256)) > 0 ? ord($max[0]) - 1 : ord($max[0]);
     if (!$crypt_random) {
         $msb = chr(mt_rand(0, $leading));
     } else {
         $cutoff = floor(0xff / $leading) * $leading;
         while (true) {
             $msb = ord(crypt_random_string(1));
             if ($msb <= $cutoff) {
                 $msb %= $leading;
                 break;
             }
         }
         $msb = chr($msb);
     }
     $random = new Math_BigInteger($msb . $random, 256);
     return $this->_normalize($random->add($min));
 }
예제 #19
0
 /**
  * Performs modular exponentiation.
  *
  * Here's an example:
  * <code>
  * <?php
  *    include('Math/BigInteger.php');
  *
  *    $a = new BigInteger('10');
  *    $b = new BigInteger('20');
  *    $c = new BigInteger('30');
  *
  *    $c = $a->modPow($b, $c);
  *
  *    echo $c->toString(); // outputs 10
  * ?>
  * </code>
  *
  * @param Math_BigInteger $e
  * @param Math_BigInteger $n
  * @return Math_BigInteger
  * @access public
  * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and
  *    and although the approach involving repeated squaring does vastly better, it, too, is impractical
  *    for our purposes.  The reason being that division - by far the most complicated and time-consuming
  *    of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
  *
  *    Modular reductions resolve this issue.  Although an individual modular reduction takes more time
  *    then an individual division, when performed in succession (with the same modulo), they're a lot faster.
  *
  *    The two most commonly used modular reductions are Barrett and Montgomery reduction.  Montgomery reduction,
  *    although faster, only works when the gcd of the modulo and of the base being used is 1.  In RSA, when the
  *    base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
  *    the product of two odd numbers is odd), but what about when RSA isn't used?
  *
  *    In contrast, Barrett reduction has no such constraint.  As such, some bigint implementations perform a
  *    Barrett reduction after every operation in the modpow function.  Others perform Barrett reductions when the
  *    modulo is even and Montgomery reductions when the modulo is odd.  BigInteger.java's modPow method, however,
  *    uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
  *    the other, a power of two - and recombine them, later.  This is the method that this modPow function uses.
  *    {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
  */
 function modPow($e, $n)
 {
     $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
     if ($e->compare(new BigInteger()) < 0) {
         $e = $e->abs();
         $temp = $this->modInverse($n);
         if ($temp === false) {
             return false;
         }
         return $this->_normalize($temp->modPow($e, $n));
     }
     if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP) {
         $temp = new BigInteger();
         $temp->value = gmp_powm($this->value, $e->value, $n->value);
         return $this->_normalize($temp);
     }
     if ($this->compare(new BigInteger()) < 0 || $this->compare($n) > 0) {
         list(, $temp) = $this->divide($n);
         return $temp->modPow($e, $n);
     }
     if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
         $components = array('modulus' => $n->toBytes(true), 'publicExponent' => $e->toBytes(true));
         $components = array('modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']), 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent']));
         $RSAPublicKey = pack('Ca*a*a*', 48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), $components['modulus'], $components['publicExponent']);
         $rsaOID = pack('H*', '300d06092a864886f70d0101010500');
         // hex version of MA0GCSqGSIb3DQEBAQUA
         $RSAPublicKey = chr(0) . $RSAPublicKey;
         $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
         $encapsulated = pack('Ca*a*', 48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey);
         $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($encapsulated)) . '-----END PUBLIC KEY-----';
         $plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "", STR_PAD_LEFT);
         if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) {
             return new BigInteger($result, 256);
         }
     }
     if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) {
         $temp = new BigInteger();
         $temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
         return $this->_normalize($temp);
     }
     if (empty($e->value)) {
         $temp = new BigInteger();
         $temp->value = array(1);
         return $this->_normalize($temp);
     }
     if ($e->value == array(1)) {
         list(, $temp) = $this->divide($n);
         return $this->_normalize($temp);
     }
     if ($e->value == array(2)) {
         $temp = new BigInteger();
         $temp->value = $this->_square($this->value);
         list(, $temp) = $temp->divide($n);
         return $this->_normalize($temp);
     }
     return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_BARRETT));
     // is the modulo odd?
     if ($n->value[0] & 1) {
         return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));
     }
     // if it's not, it's even
     // find the lowest set bit (eg. the max pow of 2 that divides $n)
     for ($i = 0; $i < count($n->value); ++$i) {
         if ($n->value[$i]) {
             $temp = decbin($n->value[$i]);
             $j = strlen($temp) - strrpos($temp, '1') - 1;
             $j += 26 * $i;
             break;
         }
     }
     // at this point, 2^$j * $n/(2^$j) == $n
     $mod1 = $n->copy();
     $mod1->_rshift($j);
     $mod2 = new BigInteger();
     $mod2->value = array(1);
     $mod2->_lshift($j);
     $part1 = $mod1->value != array(1) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new BigInteger();
     $part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2);
     $y1 = $mod2->modInverse($mod1);
     $y2 = $mod1->modInverse($mod2);
     $result = $part1->multiply($mod2);
     $result = $result->multiply($y1);
     $temp = $part2->multiply($mod1);
     $temp = $temp->multiply($y2);
     $result = $result->add($temp);
     list(, $result) = $result->divide($n);
     return $this->_normalize($result);
 }
예제 #20
0
 /**
  * Generate a random prime number.
  *
  * If there's not a prime within the given range, false will be returned.  If more than $timeout seconds have elapsed,
  * give up and return false.
  *
  * @param optional Integer $min
  * @param optional Integer $max
  * @param optional Integer $timeout
  * @return Math_BigInteger
  * @access public
  * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
  */
 function randomPrime($min = false, $max = false, $timeout = false)
 {
     // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
     if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime')) {
         // we don't rely on Math_BigInteger::random()'s min / max when gmp_nextprime() is being used since this function
         // does its own checks on $max / $min when gmp_nextprime() is used.  When gmp_nextprime() is not used, however,
         // the same $max / $min checks are not performed.
         if ($min === false) {
             $min = new Math_BigInteger(0);
         }
         if ($max === false) {
             $max = new Math_BigInteger(0x7fffffff);
         }
         $compare = $max->compare($min);
         if (!$compare) {
             return $min;
         } else {
             if ($compare < 0) {
                 // if $min is bigger then $max, swap $min and $max
                 $temp = $max;
                 $max = $min;
                 $min = $temp;
             }
         }
         $x = $this->random($min, $max);
         $x->value = gmp_nextprime($x->value);
         if ($x->compare($max) <= 0) {
             return $x;
         }
         $x->value = gmp_nextprime($min->value);
         if ($x->compare($max) <= 0) {
             return $x;
         }
         return false;
     }
     $repeat1 = $repeat2 = array();
     $one = new Math_BigInteger(1);
     $two = new Math_BigInteger(2);
     $start = time();
     do {
         if ($timeout !== false && time() - $start > $timeout) {
             return false;
         }
         $x = $this->random($min, $max);
         if ($x->equals($two)) {
             return $x;
         }
         // make the number odd
         switch (MATH_BIGINTEGER_MODE) {
             case MATH_BIGINTEGER_MODE_GMP:
                 gmp_setbit($x->value, 0);
                 break;
             case MATH_BIGINTEGER_MODE_BCMATH:
                 if ($x->value[strlen($x->value) - 1] % 2 == 0) {
                     $x = $x->add($one);
                 }
                 break;
             default:
                 $x->value[0] |= 1;
         }
         // if we've seen this number twice before, assume there are no prime numbers within the given range
         if (in_array($x->value, $repeat1)) {
             if (in_array($x->value, $repeat2)) {
                 return false;
             } else {
                 $repeat2[] = $x->value;
             }
         } else {
             $repeat1[] = $x->value;
         }
     } while (!$x->isPrime());
     return $x;
 }
예제 #21
0
 /**
  * Key Exchange
  *
  * @param String $kexinit_payload_server
  * @access private
  */
 function _key_exchange($kexinit_payload_server)
 {
     static $kex_algorithms = array('diffie-hellman-group1-sha1', 'diffie-hellman-group14-sha1');
     static $server_host_key_algorithms = array('ssh-rsa', 'ssh-dss');
     static $encryption_algorithms = array('arcfour', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc', '3des-cbc', 'none');
     static $mac_algorithms = array('hmac-sha1-96', 'hmac-sha1', 'hmac-md5-96', 'hmac-md5', 'none');
     static $compression_algorithms = array('none');
     static $str_kex_algorithms, $str_server_host_key_algorithms, $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client, $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server;
     if (empty($str_kex_algorithms)) {
         $str_kex_algorithms = implode(',', $kex_algorithms);
         $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
         $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
         $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
         $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
     }
     $client_cookie = '';
     for ($i = 0; $i < 16; $i++) {
         $client_cookie .= chr(crypt_random(0, 255));
     }
     $response = $kexinit_payload_server;
     $this->_string_shift($response, 1);
     // skip past the message number (it should be SSH_MSG_KEXINIT)
     list(, $server_cookie) = unpack('a16', $this->_string_shift($response, 16));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
     list(, $first_kex_packet_follows) = unpack('C', $this->_string_shift($response, 1));
     $first_kex_packet_follows = $first_kex_packet_follows != 0;
     // the sending of SSH2_MSG_KEXINIT could go in one of two places.  this is the second place.
     $kexinit_payload_client = pack('Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN', NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms, strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server), $encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client, strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client), $mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server, strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '', 0, 0);
     if (!$this->_send_binary_packet($kexinit_payload_client)) {
         return false;
     }
     // here ends the second place.
     // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
     for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++) {
     }
     if ($i == count($encryption_algorithms)) {
         user_error('No compatible server to client encryption algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
     // diffie-hellman key exchange as fast as possible
     $decrypt = $encryption_algorithms[$i];
     switch ($decrypt) {
         case '3des-cbc':
             $decryptKeyLength = 24;
             // eg. 192 / 8
             break;
         case 'aes256-cbc':
             $decryptKeyLength = 32;
             // eg. 256 / 8
             break;
         case 'aes192-cbc':
             $decryptKeyLength = 24;
             // eg. 192 / 8
             break;
         case 'aes128-cbc':
             $decryptKeyLength = 16;
             // eg. 128 / 8
             break;
         case 'arcfour':
             $decryptKeyLength = 16;
             // eg. 128 / 8
             break;
         case 'none':
             $decryptKeyLength = 0;
     }
     for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++) {
     }
     if ($i == count($encryption_algorithms)) {
         user_error('No compatible client to server encryption algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $encrypt = $encryption_algorithms[$i];
     switch ($encrypt) {
         case '3des-cbc':
             $encryptKeyLength = 24;
             break;
         case 'aes256-cbc':
             $encryptKeyLength = 32;
             break;
         case 'aes192-cbc':
             $encryptKeyLength = 24;
             break;
         case 'aes128-cbc':
             $encryptKeyLength = 16;
             break;
         case 'arcfour':
             $encryptKeyLength = 16;
             break;
         case 'none':
             $encryptKeyLength = 0;
     }
     $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
     // through diffie-hellman key exchange a symmetric key is obtained
     for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++) {
     }
     if ($i == count($kex_algorithms)) {
         user_error('No compatible key exchange algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     switch ($kex_algorithms[$i]) {
         // 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('N32', 4294967295.0, 4294967295.0, 3373259426.0, 0x2168c234, 3301335691.0, 2161908945.0, 0x29024e08, 2322058356.0, 0x20bbea6, 0x3b139b22, 0x514a0879, 0.0, 0.0, 3443147547.0, 0x302b0a6d, 4066317367.0, 0x4fe1356d, 0x6d51c245, 0.0, 0x625e7ec6, 0.0, 0.0, 0xbff5cb6, 0.0, 0.0, 0x5a899fa5, 0.0, 0x7c4b1fe6, 0x49286651, 0.0, 4294967295.0, 4294967295.0);
             $keyLength = $keyLength < 160 ? $keyLength : 160;
             $hash = 'sha1';
             break;
             // see http://tools.ietf.org/html/rfc3526#section-3
         // see http://tools.ietf.org/html/rfc3526#section-3
         case 'diffie-hellman-group14-sha1':
             $p = pack('N64', 4294967295.0, 4294967295.0, 3373259426.0, 0x2168c234, 3301335691.0, 2161908945.0, 0x29024e08, 2322058356.0, 0x20bbea6, 0x3b139b22, 0x514a0879, 0.0, 0.0, 3443147547.0, 0x302b0a6d, 4066317367.0, 0x4fe1356d, 0x6d51c245, 0.0, 0x625e7ec6, 0.0, 0.0, 0xbff5cb6, 0.0, 0.0, 0x5a899fa5, 0.0, 0x7c4b1fe6, 0x49286651, 0.0, 3254811832.0, 2707668741.0, 2564442166.0, 0x1c55d39a, 0x69163fa8, 4247048031.0, 2204458275.0, 3701714326.0, 0x1c62f356, 0x208552bb, 0.0, 0x7096966d, 0x670c354e, 0x4abc9804, 4050938888.0, 3390579068.0, 0x32905e46, 0x2e36ce3b, 0.0, 0x180e8603, 2603058082.0, 0.0, 3049610736.0, 0x6f4c52c9, 0.0, 2505578264.0, 0x3995497c, 0.0, 0x15d22618, 2566522128.0, 0x15728e5a, 2326571624.0, 4294967295.0, 4294967295.0);
             $keyLength = $keyLength < 160 ? $keyLength : 160;
             $hash = 'sha1';
     }
     $p = new Math_BigInteger($p, 256);
     //$q = $p->bitwise_rightShift(1);
     /* To increase the speed of the key exchange, both client and server may
                reduce the size of their private exponents.  It should be at least
                twice as long as the key material that is generated from the shared
                secret.  For more details, see the paper by van Oorschot and Wiener
                [VAN-OORSCHOT].
     
                -- http://tools.ietf.org/html/rfc4419#section-6.2 */
     $q = new Math_BigInteger(1);
     $q = $q->bitwise_leftShift(2 * $keyLength);
     $q = $q->subtract(new Math_BigInteger(1));
     $g = new Math_BigInteger(2);
     $x = new Math_BigInteger();
     $x = $x->random(new Math_BigInteger(1), $q, 'crypt_random');
     $e = $g->modPow($x, $p);
     $eBytes = $e->toBytes(true);
     $data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes);
     if (!$this->_send_binary_packet($data)) {
         user_error('Connection closed by server', E_USER_NOTICE);
         return false;
     }
     $response = $this->_get_binary_packet();
     if ($response === false) {
         user_error('Connection closed by server', E_USER_NOTICE);
         return false;
     }
     list(, $type) = unpack('C', $this->_string_shift($response, 1));
     if ($type != NET_SSH2_MSG_KEXDH_REPLY) {
         user_error('Expected SSH_MSG_KEXDH_REPLY', E_USER_NOTICE);
         return false;
     }
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
     $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
     $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $fBytes = $this->_string_shift($response, $temp['length']);
     $f = new Math_BigInteger($fBytes, -256);
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $signature = $this->_string_shift($response, $temp['length']);
     $temp = unpack('Nlength', $this->_string_shift($signature, 4));
     $signature_format = $this->_string_shift($signature, $temp['length']);
     $key = $f->modPow($x, $p);
     $keyBytes = $key->toBytes(true);
     $source = pack('Na*Na*Na*Na*Na*Na*Na*Na*', strlen($this->identifier), $this->identifier, strlen($this->server_identifier), $this->server_identifier, strlen($kexinit_payload_client), $kexinit_payload_client, strlen($kexinit_payload_server), $kexinit_payload_server, strlen($this->server_public_host_key), $this->server_public_host_key, strlen($eBytes), $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes);
     $source = pack('H*', $hash($source));
     if ($this->session_id === false) {
         $this->session_id = $source;
     }
     // if you the server's assymetric key matches the one you have on file, then you should be able to decrypt the
     // "signature" and get something that should equal the "exchange hash", as defined in the SSH-2 specs.
     // here, we just check to see if the "signature" is good.  you can verify whether or not the assymetric key is good,
     // later, with the getServerHostKeyAlgorithm() function
     for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++) {
     }
     if ($i == count($server_host_key_algorithms)) {
         user_error('No compatible server host key algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     if ($public_key_format != $server_host_key_algorithms[$i] || $signature_format != $server_host_key_algorithms[$i]) {
         user_error('Sever Host Key Algorithm Mismatch', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     switch ($server_host_key_algorithms[$i]) {
         case 'ssh-dss':
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $p = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $q = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $g = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $y = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             /* The value for 'dss_signature_blob' is encoded as a string containing
                r, followed by s (which are 160-bit integers, without lengths or
                padding, unsigned, and in network byte order). */
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             if ($temp['length'] != 40) {
                 user_error('Invalid signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $r = new Math_BigInteger($this->_string_shift($signature, 20), 256);
             $s = new Math_BigInteger($this->_string_shift($signature, 20), 256);
             if ($r->compare($q) >= 0 || $s->compare($q) >= 0) {
                 user_error('Invalid signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $w = $s->modInverse($q);
             $u1 = $w->multiply(new Math_BigInteger(sha1($source), 16));
             list(, $u1) = $u1->divide($q);
             $u2 = $w->multiply($r);
             list(, $u2) = $u2->divide($q);
             $g = $g->modPow($u1, $p);
             $y = $y->modPow($u2, $p);
             $v = $g->multiply($y);
             list(, $v) = $v->divide($p);
             list(, $v) = $v->divide($q);
             if ($v->compare($r) != 0) {
                 user_error('Invalid signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
             }
             break;
         case 'ssh-rsa':
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $n = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $nLength = $temp['length'];
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             $s = new Math_BigInteger($this->_string_shift($signature, $temp['length']), 256);
             // validate an RSA signature per "8.2 RSASSA-PKCS1-v1_5", "5.2.2 RSAVP1", and "9.1 EMSA-PSS" in the
             // following URL:
             // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
             // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
             if ($s->compare(new Math_BigInteger()) < 0 || $s->compare($n->subtract(new Math_BigInteger(1))) > 0) {
                 user_error('Invalid signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $s = $s->modPow($e, $n);
             $s = $s->toBytes();
             $h = pack('N4H*', 0x302130, 0x906052b, 0xe03021a, 0x5000414, sha1($source));
             $h = chr(0x1) . str_repeat(chr(0xff), $nLength - 3 - strlen($h)) . $h;
             if ($s != $h) {
                 user_error('Bad server signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
             }
     }
     $packet = pack('C', NET_SSH2_MSG_NEWKEYS);
     if (!$this->_send_binary_packet($packet)) {
         return false;
     }
     $response = $this->_get_binary_packet();
     if ($response === false) {
         user_error('Connection closed by server', E_USER_NOTICE);
         return false;
     }
     list(, $type) = unpack('C', $this->_string_shift($response, 1));
     if ($type != NET_SSH2_MSG_NEWKEYS) {
         user_error('Expected SSH_MSG_NEWKEYS', E_USER_NOTICE);
         return false;
     }
     switch ($encrypt) {
         case '3des-cbc':
             $this->encrypt = new Crypt_TripleDES();
             // $this->encrypt_block_size = 64 / 8 == the default
             break;
         case 'aes256-cbc':
             $this->encrypt = new Crypt_AES();
             $this->encrypt_block_size = 16;
             // eg. 128 / 8
             break;
         case 'aes192-cbc':
             $this->encrypt = new Crypt_AES();
             $this->encrypt_block_size = 16;
             break;
         case 'aes128-cbc':
             $this->encrypt = new Crypt_AES();
             $this->encrypt_block_size = 16;
             break;
         case 'arcfour':
             $this->encrypt = new Crypt_RC4();
             break;
         case 'none':
             //$this->encrypt = new Crypt_Null();
     }
     switch ($decrypt) {
         case '3des-cbc':
             $this->decrypt = new Crypt_TripleDES();
             break;
         case 'aes256-cbc':
             $this->decrypt = new Crypt_AES();
             $this->decrypt_block_size = 16;
             break;
         case 'aes192-cbc':
             $this->decrypt = new Crypt_AES();
             $this->decrypt_block_size = 16;
             break;
         case 'aes128-cbc':
             $this->decrypt = new Crypt_AES();
             $this->decrypt_block_size = 16;
             break;
         case 'arcfour':
             $this->decrypt = new Crypt_RC4();
             break;
         case 'none':
             //$this->decrypt = new Crypt_Null();
     }
     $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
     if ($this->encrypt) {
         $this->encrypt->enableContinuousBuffer();
         $this->encrypt->disablePadding();
         $iv = pack('H*', $hash($keyBytes . $source . 'A' . $this->session_id));
         while ($this->encrypt_block_size > strlen($iv)) {
             $iv .= pack('H*', $hash($keyBytes . $source . $iv));
         }
         $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
         $key = pack('H*', $hash($keyBytes . $source . 'C' . $this->session_id));
         while ($encryptKeyLength > strlen($key)) {
             $key .= pack('H*', $hash($keyBytes . $source . $key));
         }
         $this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
     }
     if ($this->decrypt) {
         $this->decrypt->enableContinuousBuffer();
         $this->decrypt->disablePadding();
         $iv = pack('H*', $hash($keyBytes . $source . 'B' . $this->session_id));
         while ($this->decrypt_block_size > strlen($iv)) {
             $iv .= pack('H*', $hash($keyBytes . $source . $iv));
         }
         $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
         $key = pack('H*', $hash($keyBytes . $source . 'D' . $this->session_id));
         while ($decryptKeyLength > strlen($key)) {
             $key .= pack('H*', $hash($keyBytes . $source . $key));
         }
         $this->decrypt->setKey(substr($key, 0, $decryptKeyLength));
     }
     for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++) {
     }
     if ($i == count($mac_algorithms)) {
         user_error('No compatible client to server message authentication algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $createKeyLength = 0;
     // ie. $mac_algorithms[$i] == 'none'
     switch ($mac_algorithms[$i]) {
         case 'hmac-sha1':
             $this->hmac_create = new Crypt_Hash('sha1');
             $createKeyLength = 20;
             break;
         case 'hmac-sha1-96':
             $this->hmac_create = new Crypt_Hash('sha1-96');
             $createKeyLength = 20;
             break;
         case 'hmac-md5':
             $this->hmac_create = new Crypt_Hash('md5');
             $createKeyLength = 16;
             break;
         case 'hmac-md5-96':
             $this->hmac_create = new Crypt_Hash('md5-96');
             $createKeyLength = 16;
     }
     for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++) {
     }
     if ($i == count($mac_algorithms)) {
         user_error('No compatible server to client message authentication algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $checkKeyLength = 0;
     $this->hmac_size = 0;
     switch ($mac_algorithms[$i]) {
         case 'hmac-sha1':
             $this->hmac_check = new Crypt_Hash('sha1');
             $checkKeyLength = 20;
             $this->hmac_size = 20;
             break;
         case 'hmac-sha1-96':
             $this->hmac_check = new Crypt_Hash('sha1-96');
             $checkKeyLength = 20;
             $this->hmac_size = 12;
             break;
         case 'hmac-md5':
             $this->hmac_check = new Crypt_Hash('md5');
             $checkKeyLength = 16;
             $this->hmac_size = 16;
             break;
         case 'hmac-md5-96':
             $this->hmac_check = new Crypt_Hash('md5-96');
             $checkKeyLength = 16;
             $this->hmac_size = 12;
     }
     $key = pack('H*', $hash($keyBytes . $source . 'E' . $this->session_id));
     while ($createKeyLength > strlen($key)) {
         $key .= pack('H*', $hash($keyBytes . $source . $key));
     }
     $this->hmac_create->setKey(substr($key, 0, $createKeyLength));
     $key = pack('H*', $hash($keyBytes . $source . 'F' . $this->session_id));
     while ($checkKeyLength > strlen($key)) {
         $key .= pack('H*', $hash($keyBytes . $source . $key));
     }
     $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
     for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++) {
     }
     if ($i == count($compression_algorithms)) {
         user_error('No compatible server to client compression algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $this->decompress = $compression_algorithms[$i] == 'zlib';
     for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++) {
     }
     if ($i == count($compression_algorithms)) {
         user_error('No compatible client to server compression algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $this->compress = $compression_algorithms[$i] == 'zlib';
     return true;
 }
예제 #22
0
 /**
  * Generate a random number
  *
  * @param optional Integer $min
  * @param optional Integer $max
  * @return Math_BigInteger
  * @access public
  */
 function random($min = false, $max = false)
 {
     if ($min === false) {
         $min = new Math_BigInteger(0);
     }
     if ($max === false) {
         $max = new Math_BigInteger(0x7fffffff);
     }
     $compare = $max->compare($min);
     if (!$compare) {
         return $this->_normalize($min);
     } else {
         if ($compare < 0) {
             // if $min is bigger then $max, swap $min and $max
             $temp = $max;
             $max = $min;
             $min = $temp;
         }
     }
     $generator = $this->generator;
     $max = $max->subtract($min);
     $max = ltrim($max->toBytes(), chr(0));
     $size = strlen($max) - 1;
     $random = '';
     $bytes = $size & 1;
     for ($i = 0; $i < $bytes; ++$i) {
         $random .= chr($generator(0, 255));
     }
     $blocks = $size >> 1;
     for ($i = 0; $i < $blocks; ++$i) {
         // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
         $random .= pack('n', $generator(0, 0xffff));
     }
     $temp = new Math_BigInteger($random, 256);
     if ($temp->compare(new Math_BigInteger(substr($max, 1), 256)) > 0) {
         $random = chr($generator(0, ord($max[0]) - 1)) . $random;
     } else {
         $random = chr($generator(0, ord($max[0]))) . $random;
     }
     $random = new Math_BigInteger($random, 256);
     return $this->_normalize($random->add($min));
 }
예제 #23
0
 /**
  * Key Exchange
  *
  * @param String $kexinit_payload_server
  * @access private
  */
 function _key_exchange($kexinit_payload_server)
 {
     static $kex_algorithms = array('diffie-hellman-group1-sha1', 'diffie-hellman-group14-sha1');
     static $server_host_key_algorithms = array('ssh-rsa', 'ssh-dss');
     static $encryption_algorithms = array('arcfour', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc', '3des-cbc', 'none');
     static $mac_algorithms = array('hmac-sha1-96', 'hmac-sha1', 'hmac-md5-96', 'hmac-md5', 'none');
     static $compression_algorithms = array('none');
     static $str_kex_algorithms, $str_server_host_key_algorithms, $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client, $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server;
     if (empty($str_kex_algorithms)) {
         $str_kex_algorithms = implode(',', $kex_algorithms);
         $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
         $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
         $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
         $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
     }
     $client_cookie = '';
     for ($i = 0; $i < 16; $i++) {
         $client_cookie .= chr(crypt_random(0, 255));
     }
     $response = $kexinit_payload_server;
     $this->_string_shift($response, 1);
     // skip past the message number (it should be SSH_MSG_KEXINIT)
     $server_cookie = $this->_string_shift($response, 16);
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
     extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
     $first_kex_packet_follows = $first_kex_packet_follows != 0;
     // the sending of SSH2_MSG_KEXINIT could go in one of two places.  this is the second place.
     $kexinit_payload_client = pack('Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN', NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms, strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server), $encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client, strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client), $mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server, strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '', 0, 0);
     if (!$this->_send_binary_packet($kexinit_payload_client)) {
         return false;
     }
     // here ends the second place.
     // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
     for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++) {
     }
     if ($i == count($encryption_algorithms)) {
         user_error('No compatible server to client encryption algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
     // diffie-hellman key exchange as fast as possible
     $decrypt = $encryption_algorithms[$i];
     switch ($decrypt) {
         case '3des-cbc':
             $decryptKeyLength = 24;
             // eg. 192 / 8
             break;
         case 'aes256-cbc':
             $decryptKeyLength = 32;
             // eg. 256 / 8
             break;
         case 'aes192-cbc':
             $decryptKeyLength = 24;
             // eg. 192 / 8
             break;
         case 'aes128-cbc':
             $decryptKeyLength = 16;
             // eg. 128 / 8
             break;
         case 'arcfour':
             $decryptKeyLength = 16;
             // eg. 128 / 8
             break;
         case 'none':
             $decryptKeyLength = 0;
     }
     for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++) {
     }
     if ($i == count($encryption_algorithms)) {
         user_error('No compatible client to server encryption algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $encrypt = $encryption_algorithms[$i];
     switch ($encrypt) {
         case '3des-cbc':
             $encryptKeyLength = 24;
             break;
         case 'aes256-cbc':
             $encryptKeyLength = 32;
             break;
         case 'aes192-cbc':
             $encryptKeyLength = 24;
             break;
         case 'aes128-cbc':
             $encryptKeyLength = 16;
             break;
         case 'arcfour':
             $encryptKeyLength = 16;
             break;
         case 'none':
             $encryptKeyLength = 0;
     }
     $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
     // through diffie-hellman key exchange a symmetric key is obtained
     for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++) {
     }
     if ($i == count($kex_algorithms)) {
         user_error('No compatible key exchange algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     switch ($kex_algorithms[$i]) {
         // 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 < 160 ? $keyLength : 160;
             $hash = 'sha1';
             break;
             // see http://tools.ietf.org/html/rfc3526#section-3
         // 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 < 160 ? $keyLength : 160;
             $hash = 'sha1';
     }
     $p = new Math_BigInteger($p, 256);
     //$q = $p->bitwise_rightShift(1);
     /* To increase the speed of the key exchange, both client and server may
                reduce the size of their private exponents.  It should be at least
                twice as long as the key material that is generated from the shared
                secret.  For more details, see the paper by van Oorschot and Wiener
                [VAN-OORSCHOT].
     
                -- http://tools.ietf.org/html/rfc4419#section-6.2 */
     $q = new Math_BigInteger(1);
     $q = $q->bitwise_leftShift(2 * $keyLength);
     $q = $q->subtract(new Math_BigInteger(1));
     $g = new Math_BigInteger(2);
     $x = new Math_BigInteger();
     $x->setRandomGenerator('crypt_random');
     $x = $x->random(new Math_BigInteger(1), $q);
     $e = $g->modPow($x, $p);
     $eBytes = $e->toBytes(true);
     $data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes);
     if (!$this->_send_binary_packet($data)) {
         user_error('Connection closed by server', E_USER_NOTICE);
         return false;
     }
     $response = $this->_get_binary_packet();
     if ($response === false) {
         user_error('Connection closed by server', E_USER_NOTICE);
         return false;
     }
     extract(unpack('Ctype', $this->_string_shift($response, 1)));
     if ($type != NET_SSH2_MSG_KEXDH_REPLY) {
         user_error('Expected SSH_MSG_KEXDH_REPLY', E_USER_NOTICE);
         return false;
     }
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
     $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
     $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $fBytes = $this->_string_shift($response, $temp['length']);
     $f = new Math_BigInteger($fBytes, -256);
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $signature = $this->_string_shift($response, $temp['length']);
     $temp = unpack('Nlength', $this->_string_shift($signature, 4));
     $signature_format = $this->_string_shift($signature, $temp['length']);
     $key = $f->modPow($x, $p);
     $keyBytes = $key->toBytes(true);
     $source = pack('Na*Na*Na*Na*Na*Na*Na*Na*', strlen($this->identifier), $this->identifier, strlen($this->server_identifier), $this->server_identifier, strlen($kexinit_payload_client), $kexinit_payload_client, strlen($kexinit_payload_server), $kexinit_payload_server, strlen($this->server_public_host_key), $this->server_public_host_key, strlen($eBytes), $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes);
     $source = pack('H*', $hash($source));
     if ($this->session_id === false) {
         $this->session_id = $source;
     }
     // if you the server's assymetric key matches the one you have on file, then you should be able to decrypt the
     // "signature" and get something that should equal the "exchange hash", as defined in the SSH-2 specs.
     // here, we just check to see if the "signature" is good.  you can verify whether or not the assymetric key is good,
     // later, with the getServerHostKeyAlgorithm() function
     for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++) {
     }
     if ($i == count($server_host_key_algorithms)) {
         user_error('No compatible server host key algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     if ($public_key_format != $server_host_key_algorithms[$i] || $signature_format != $server_host_key_algorithms[$i]) {
         user_error('Sever Host Key Algorithm Mismatch', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     switch ($server_host_key_algorithms[$i]) {
         case 'ssh-dss':
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $p = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $q = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $g = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $y = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             /* The value for 'dss_signature_blob' is encoded as a string containing
                r, followed by s (which are 160-bit integers, without lengths or
                padding, unsigned, and in network byte order). */
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             if ($temp['length'] != 40) {
                 user_error('Invalid signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $r = new Math_BigInteger($this->_string_shift($signature, 20), 256);
             $s = new Math_BigInteger($this->_string_shift($signature, 20), 256);
             if ($r->compare($q) >= 0 || $s->compare($q) >= 0) {
                 user_error('Invalid signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $w = $s->modInverse($q);
             $u1 = $w->multiply(new Math_BigInteger(sha1($source), 16));
             list(, $u1) = $u1->divide($q);
             $u2 = $w->multiply($r);
             list(, $u2) = $u2->divide($q);
             $g = $g->modPow($u1, $p);
             $y = $y->modPow($u2, $p);
             $v = $g->multiply($y);
             list(, $v) = $v->divide($p);
             list(, $v) = $v->divide($q);
             if (!$v->equals($r)) {
                 user_error('Invalid signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
             }
             break;
         case 'ssh-rsa':
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $n = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $nLength = $temp['length'];
             /*
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             $signature = $this->_string_shift($signature, $temp['length']);
             
             if (!class_exists('Crypt_RSA')) {
                 require_once('Crypt/RSA.php');
             }
             
             $rsa = new Crypt_RSA();
             $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
             $rsa->loadKey(array('e' => $e, 'n' => $n), CRYPT_RSA_PUBLIC_FORMAT_RAW);
             if (!$rsa->verify($source, $signature)) {
                 user_error('Bad server signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
             }
             */
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             $s = new Math_BigInteger($this->_string_shift($signature, $temp['length']), 256);
             // validate an RSA signature per "8.2 RSASSA-PKCS1-v1_5", "5.2.2 RSAVP1", and "9.1 EMSA-PSS" in the
             // following URL:
             // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
             // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
             if ($s->compare(new Math_BigInteger()) < 0 || $s->compare($n->subtract(new Math_BigInteger(1))) > 0) {
                 user_error('Invalid signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $s = $s->modPow($e, $n);
             $s = $s->toBytes();
             $h = pack('N4H*', 0x302130, 0x906052b, 0xe03021a, 0x5000414, sha1($source));
             $h = chr(0x1) . str_repeat(chr(0xff), $nLength - 3 - strlen($h)) . $h;
             if ($s != $h) {
                 user_error('Bad server signature', E_USER_NOTICE);
                 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
             }
     }
     $packet = pack('C', NET_SSH2_MSG_NEWKEYS);
     if (!$this->_send_binary_packet($packet)) {
         return false;
     }
     $response = $this->_get_binary_packet();
     if ($response === false) {
         user_error('Connection closed by server', E_USER_NOTICE);
         return false;
     }
     extract(unpack('Ctype', $this->_string_shift($response, 1)));
     if ($type != NET_SSH2_MSG_NEWKEYS) {
         user_error('Expected SSH_MSG_NEWKEYS', E_USER_NOTICE);
         return false;
     }
     switch ($encrypt) {
         case '3des-cbc':
             $this->encrypt = new Crypt_TripleDES();
             // $this->encrypt_block_size = 64 / 8 == the default
             break;
         case 'aes256-cbc':
             $this->encrypt = new Crypt_AES();
             $this->encrypt_block_size = 16;
             // eg. 128 / 8
             break;
         case 'aes192-cbc':
             $this->encrypt = new Crypt_AES();
             $this->encrypt_block_size = 16;
             break;
         case 'aes128-cbc':
             $this->encrypt = new Crypt_AES();
             $this->encrypt_block_size = 16;
             break;
         case 'arcfour':
             $this->encrypt = new Crypt_RC4();
             break;
         case 'none':
             //$this->encrypt = new Crypt_Null();
     }
     switch ($decrypt) {
         case '3des-cbc':
             $this->decrypt = new Crypt_TripleDES();
             break;
         case 'aes256-cbc':
             $this->decrypt = new Crypt_AES();
             $this->decrypt_block_size = 16;
             break;
         case 'aes192-cbc':
             $this->decrypt = new Crypt_AES();
             $this->decrypt_block_size = 16;
             break;
         case 'aes128-cbc':
             $this->decrypt = new Crypt_AES();
             $this->decrypt_block_size = 16;
             break;
         case 'arcfour':
             $this->decrypt = new Crypt_RC4();
             break;
         case 'none':
             //$this->decrypt = new Crypt_Null();
     }
     $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
     if ($this->encrypt) {
         $this->encrypt->enableContinuousBuffer();
         $this->encrypt->disablePadding();
         $iv = pack('H*', $hash($keyBytes . $source . 'A' . $this->session_id));
         while ($this->encrypt_block_size > strlen($iv)) {
             $iv .= pack('H*', $hash($keyBytes . $source . $iv));
         }
         $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
         $key = pack('H*', $hash($keyBytes . $source . 'C' . $this->session_id));
         while ($encryptKeyLength > strlen($key)) {
             $key .= pack('H*', $hash($keyBytes . $source . $key));
         }
         $this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
     }
     if ($this->decrypt) {
         $this->decrypt->enableContinuousBuffer();
         $this->decrypt->disablePadding();
         $iv = pack('H*', $hash($keyBytes . $source . 'B' . $this->session_id));
         while ($this->decrypt_block_size > strlen($iv)) {
             $iv .= pack('H*', $hash($keyBytes . $source . $iv));
         }
         $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
         $key = pack('H*', $hash($keyBytes . $source . 'D' . $this->session_id));
         while ($decryptKeyLength > strlen($key)) {
             $key .= pack('H*', $hash($keyBytes . $source . $key));
         }
         $this->decrypt->setKey(substr($key, 0, $decryptKeyLength));
     }
     for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++) {
     }
     if ($i == count($mac_algorithms)) {
         user_error('No compatible client to server message authentication algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $createKeyLength = 0;
     // ie. $mac_algorithms[$i] == 'none'
     switch ($mac_algorithms[$i]) {
         case 'hmac-sha1':
             $this->hmac_create = new Crypt_Hash('sha1');
             $createKeyLength = 20;
             break;
         case 'hmac-sha1-96':
             $this->hmac_create = new Crypt_Hash('sha1-96');
             $createKeyLength = 20;
             break;
         case 'hmac-md5':
             $this->hmac_create = new Crypt_Hash('md5');
             $createKeyLength = 16;
             break;
         case 'hmac-md5-96':
             $this->hmac_create = new Crypt_Hash('md5-96');
             $createKeyLength = 16;
     }
     for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++) {
     }
     if ($i == count($mac_algorithms)) {
         user_error('No compatible server to client message authentication algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $checkKeyLength = 0;
     $this->hmac_size = 0;
     switch ($mac_algorithms[$i]) {
         case 'hmac-sha1':
             $this->hmac_check = new Crypt_Hash('sha1');
             $checkKeyLength = 20;
             $this->hmac_size = 20;
             break;
         case 'hmac-sha1-96':
             $this->hmac_check = new Crypt_Hash('sha1-96');
             $checkKeyLength = 20;
             $this->hmac_size = 12;
             break;
         case 'hmac-md5':
             $this->hmac_check = new Crypt_Hash('md5');
             $checkKeyLength = 16;
             $this->hmac_size = 16;
             break;
         case 'hmac-md5-96':
             $this->hmac_check = new Crypt_Hash('md5-96');
             $checkKeyLength = 16;
             $this->hmac_size = 12;
     }
     $key = pack('H*', $hash($keyBytes . $source . 'E' . $this->session_id));
     while ($createKeyLength > strlen($key)) {
         $key .= pack('H*', $hash($keyBytes . $source . $key));
     }
     $this->hmac_create->setKey(substr($key, 0, $createKeyLength));
     $key = pack('H*', $hash($keyBytes . $source . 'F' . $this->session_id));
     while ($checkKeyLength > strlen($key)) {
         $key .= pack('H*', $hash($keyBytes . $source . $key));
     }
     $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
     for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++) {
     }
     if ($i == count($compression_algorithms)) {
         user_error('No compatible server to client compression algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $this->decompress = $compression_algorithms[$i] == 'zlib';
     for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++) {
     }
     if ($i == count($compression_algorithms)) {
         user_error('No compatible client to server compression algorithms found', E_USER_NOTICE);
         return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
     }
     $this->compress = $compression_algorithms[$i] == 'zlib';
     return true;
 }
예제 #24
0
 /**
  * RSAVP1
  *
  * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
  *
  * @access private
  * @param Math_BigInteger $s
  * @return Math_BigInteger
  */
 function _rsavp1($s)
 {
     if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) {
         user_error('Signature representative out of range', E_USER_NOTICE);
         return false;
     }
     return $this->_exponentiate($s);
 }
예제 #25
0
 /**
  * RSAVP1
  *
  * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
  *
  * @access private
  * @param Math_BigInteger $s
  * @return Math_BigInteger
  */
 function _rsavp1($s)
 {
     if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) {
         return false;
     }
     return $this->_exponentiate($s);
 }
예제 #26
0
 /**
  * Get the index of a revoked certificate.
  *
  * @param array $rclist
  * @param String $serial
  * @param Boolean $create optional
  * @access private
  * @return Integer or false
  */
 function _revokedCertificate(&$rclist, $serial, $create = false)
 {
     $serial = new Math_BigInteger($serial);
     foreach ($rclist as $i => $rc) {
         if (!$serial->compare($rc['userCertificate'])) {
             return $i;
         }
     }
     if (!$create) {
         return false;
     }
     $i = count($rclist);
     $rclist[] = array('userCertificate' => $serial, 'revocationDate' => array('generalTime' => @date('M j H:i:s Y T')));
     return $i;
 }
예제 #27
0
파일: SGArchive.php 프로젝트: Finzy/stageDB
 private function extractFiles($destinationPath)
 {
     $zero = new Math_BigInteger(0);
     $blockSize = new Math_BigInteger(self::CHUNK_SIZE);
     $inflate = sgfun('zlib.inflate');
     fseek($this->fileHandle, 0, SEEK_SET);
     $i = 0;
     $getNewOffset = true;
     $offsetAvailable = true;
     $offset = null;
     $fp = null;
     foreach ($this->cdr as $row) {
         $path = $destinationPath . $row[0];
         if (!is_writable(dirname($path))) {
             $this->delegate->didFindExtractError('Destination path is not writable: ' . dirname($path));
         }
         $zlen = $row[1];
         $rl = self::CHUNK_SIZE;
         if ($zlen->compare(new Math_BigInteger($rl)) <= 0) {
             $rl = (int) $zlen->toString();
         }
         if ($offsetAvailable && $offset && $offset->compare(new Math_BigInteger($rl)) <= 0) {
             $rl = (int) $offset->toString();
             $data = $this->read($rl);
             $data = $inflate($data) . $inflate();
             if (is_resource($fp) && strlen($data)) {
                 fwrite($fp, $data);
                 fflush($fp);
             }
             $inflate = sgfun('zlib.inflate');
             $getNewOffset = true;
         }
         $fp = @fopen($path, 'wb');
         while ($zlen->compare($zero) > 0) {
             if ($getNewOffset && $offsetAvailable) {
                 $offsetAvailable = isset($this->zoffsets[$i]);
                 if ($offsetAvailable) {
                     $offset = $this->zoffsets[$i];
                     $offset = new Math_BigInteger($offset);
                     $i++;
                 }
             }
             $readlen = self::CHUNK_SIZE;
             $close = false;
             $getNewOffset = false;
             if ($zlen->compare(new Math_BigInteger($readlen)) <= 0) {
                 $readlen = (int) $zlen->toString();
                 $close = true;
             }
             if ($offsetAvailable && $offset->compare(new Math_BigInteger($readlen)) <= 0) {
                 $readlen = (int) $offset->toString();
                 $close = true;
                 $getNewOffset = true;
             }
             if ($readlen) {
                 $data = $this->read($readlen);
                 $data = $inflate($data);
                 if (is_resource($fp)) {
                     fwrite($fp, $data);
                     fflush($fp);
                 }
             }
             if ($close) {
                 $data = $inflate();
                 if (is_resource($fp)) {
                     fwrite($fp, $data);
                     fflush($fp);
                 }
                 $inflate = sgfun('zlib.inflate');
             }
             $zlen = $zlen->subtract(new Math_BigInteger($readlen));
             if ($offsetAvailable) {
                 $offset = $offset->subtract(new Math_BigInteger($readlen));
             }
         }
         if (is_resource($fp)) {
             fclose($fp);
         }
         $this->delegate->didExtractFile($path);
     }
     fclose($this->fileHandle);
 }
예제 #28
0
 /**
  * Returns the server public host key.
  *
  * Caching this the first time you connect to a server and checking the result on subsequent connections
  * is recommended.  Returns false if the server signature is not signed correctly with the public host key.
  *
  * @return Mixed
  * @access public
  */
 function getServerPublicHostKey()
 {
     if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
         $this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
         if (!$this->_connect()) {
             return false;
         }
     }
     $signature = $this->signature;
     $server_public_host_key = $this->server_public_host_key;
     extract(unpack('Nlength', $this->_string_shift($server_public_host_key, 4)));
     $this->_string_shift($server_public_host_key, $length);
     if ($this->signature_validated) {
         return $this->bitmap ? $this->signature_format . ' ' . base64_encode($this->server_public_host_key) : false;
     }
     $this->signature_validated = true;
     switch ($this->signature_format) {
         case 'ssh-dss':
             $zero = new Math_BigInteger();
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $p = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $q = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $g = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $y = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             /* The value for 'dss_signature_blob' is encoded as a string containing
                r, followed by s (which are 160-bit integers, without lengths or
                padding, unsigned, and in network byte order). */
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             if ($temp['length'] != 40) {
                 user_error('Invalid signature');
                 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $r = new Math_BigInteger($this->_string_shift($signature, 20), 256);
             $s = new Math_BigInteger($this->_string_shift($signature, 20), 256);
             switch (true) {
                 case $r->equals($zero):
                 case $r->compare($q) >= 0:
                 case $s->equals($zero):
                 case $s->compare($q) >= 0:
                     user_error('Invalid signature');
                     return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $w = $s->modInverse($q);
             $u1 = $w->multiply(new Math_BigInteger(sha1($this->exchange_hash), 16));
             list(, $u1) = $u1->divide($q);
             $u2 = $w->multiply($r);
             list(, $u2) = $u2->divide($q);
             $g = $g->modPow($u1, $p);
             $y = $y->modPow($u2, $p);
             $v = $g->multiply($y);
             list(, $v) = $v->divide($p);
             list(, $v) = $v->divide($q);
             if (!$v->equals($r)) {
                 user_error('Bad server signature');
                 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
             }
             break;
         case 'ssh-rsa':
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $n = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $nLength = $temp['length'];
             /*
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             $signature = $this->_string_shift($signature, $temp['length']);
             
             if (!class_exists('Crypt_RSA')) {
                 include_once 'Crypt/RSA.php';
             }
             
             $rsa = new Crypt_RSA();
             $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
             $rsa->loadKey(array('e' => $e, 'n' => $n), CRYPT_RSA_PUBLIC_FORMAT_RAW);
             if (!$rsa->verify($this->exchange_hash, $signature)) {
                 user_error('Bad server signature');
                 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
             }
             */
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             $s = new Math_BigInteger($this->_string_shift($signature, $temp['length']), 256);
             // validate an RSA signature per "8.2 RSASSA-PKCS1-v1_5", "5.2.2 RSAVP1", and "9.1 EMSA-PSS" in the
             // following URL:
             // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
             // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
             if ($s->compare(new Math_BigInteger()) < 0 || $s->compare($n->subtract(new Math_BigInteger(1))) > 0) {
                 user_error('Invalid signature');
                 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
             }
             $s = $s->modPow($e, $n);
             $s = $s->toBytes();
             $h = pack('N4H*', 0x302130, 0x906052b, 0xe03021a, 0x5000414, sha1($this->exchange_hash));
             $h = chr(0x1) . str_repeat(chr(0xff), $nLength - 3 - strlen($h)) . $h;
             if ($s != $h) {
                 user_error('Bad server signature');
                 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
             }
             break;
         default:
             user_error('Unsupported signature format');
             return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
     }
     return $this->signature_format . ' ' . base64_encode($this->server_public_host_key);
 }
예제 #29
0
 /**
  * Generate a random number
  *
  * $generator should be the name of a random number generating function whose first parameter is the minimum
  * value and whose second parameter is the maximum value.  If this function needs to be seeded, it should be
  * done before this function is called.
  *
  * @param optional Integer $min
  * @param optional Integer $max
  * @param optional String $generator
  * @return Math_BigInteger
  * @access public
  */
 function random($min = false, $max = false, $generator = 'mt_rand')
 {
     if ($min === false) {
         $min = new Math_BigInteger(0);
     }
     if ($max === false) {
         $max = new Math_BigInteger(0x7fffffff);
     }
     $compare = $max->compare($min);
     if (!$compare) {
         return $min;
     } else {
         if ($compare < 0) {
             // if $min is bigger then $max, swap $min and $max
             $temp = $max;
             $max = $min;
             $min = $temp;
         }
     }
     $max = $max->subtract($min);
     $max = ltrim($max->toBytes(), chr(0));
     $size = strlen($max) - 1;
     $random = '';
     $bytes = $size & 3;
     for ($i = 0; $i < $bytes; $i++) {
         $random .= chr($generator(0, 255));
     }
     $blocks = $size >> 2;
     for ($i = 0; $i < $blocks; $i++) {
         $random .= pack('N', $generator(-2147483648.0, 0x7fffffff));
     }
     $temp = new Math_BigInteger($random, 256);
     if ($temp->compare(new Math_BigInteger(substr($max, 1), 256)) > 0) {
         $random = chr($generator(0, ord($max[0]) - 1)) . $random;
     } else {
         $random = chr($generator(0, ord($max[0]))) . $random;
     }
     $random = new Math_BigInteger($random, 256);
     return $random->add($min);
 }