Пример #1
0
 /**
  * Defines the public key
  *
  * Some private key formats define the public exponent and some don't. Those that don't define it are problematic when
  * used in certain contexts. For example, in SSH-2, RSA authentication works by sending the public key along with a
  * message signed by the private key to the server. The SSH-2 server looks the public key up in an index of public keys
  * and if it's present then proceeds to verify the signature. Problem is, if your private key doesn't include the public
  * exponent this won't work unless you manually add the public exponent.
  *
  * Do note that when a new key is loaded the index will be cleared.
  *
  * Returns true on success, false on failure
  *
  * @see getPublicKey()
  * @access public
  * @param String $key
  *        	optional
  * @param Integer $type
  *        	optional
  * @return Boolean
  */
 function setPublicKey($key = false, $type = false)
 {
     // if a public key has already been loaded return false
     if (!empty($this->publicExponent)) {
         return false;
     }
     if ($key === false && !empty($this->modulus)) {
         $this->publicExponent = $this->exponent;
         return true;
     }
     if ($type === false) {
         $types = array(CRYPT_RSA_PUBLIC_FORMAT_RAW, CRYPT_RSA_PUBLIC_FORMAT_PKCS1, CRYPT_RSA_PUBLIC_FORMAT_XML, CRYPT_RSA_PUBLIC_FORMAT_OPENSSH);
         foreach ($types as $type) {
             $components = $this->_parseKey($key, $type);
             if ($components !== false) {
                 break;
             }
         }
     } else {
         $components = $this->_parseKey($key, $type);
     }
     if ($components === false) {
         return false;
     }
     if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) {
         $this->modulus = $components['modulus'];
         $this->exponent = $this->publicExponent = $components['publicExponent'];
         return true;
     }
     $this->publicExponent = $components['publicExponent'];
     return true;
 }
Пример #2
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 & self::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 BigInteger();
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $p = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $q = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $g = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $y = new 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 BigInteger($this->_string_shift($signature, 20), 256);
             $s = new 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 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 BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
             $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
             $rawN = $this->_string_shift($server_public_host_key, $temp['length']);
             $n = new BigInteger($rawN, -256);
             $nLength = strlen(ltrim($rawN, ""));
             /*
             $temp = unpack('Nlength', $this->_string_shift($signature, 4));
             $signature = $this->_string_shift($signature, $temp['length']);
             
             $rsa = new RSA();
             $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
             $rsa->loadKey(array('e' => $e, 'n' => $n), 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 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 BigInteger()) < 0 || $s->compare($n->subtract(new 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 - 2 - 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);
 }
Пример #3
0
 /**
  * Defines the public key
  *
  * Some private key formats define the public exponent and some don't.  Those that don't define it are problematic when
  * used in certain contexts.  For example, in SSH-2, RSA authentication works by sending the public key along with a
  * message signed by the private key to the server.  The SSH-2 server looks the public key up in an index of public keys
  * and if it's present then proceeds to verify the signature.  Problem is, if your private key doesn't include the public
  * exponent this won't work unless you manually add the public exponent. phpseclib tries to guess if the key being used
  * is the public key but in the event that it guesses incorrectly you might still want to explicitly set the key as being
  * public.
  *
  * Do note that when a new key is loaded the index will be cleared.
  *
  * Returns true on success, false on failure
  *
  * @see self::getPublicKey()
  * @access public
  * @param string $key optional
  * @param int $type optional
  * @return bool
  */
 function setPublicKey($key = false, $type = false)
 {
     // if a public key has already been loaded return false
     if (!empty($this->publicExponent)) {
         return false;
     }
     if ($key === false && !empty($this->modulus)) {
         $this->publicExponent = $this->exponent;
         return true;
     }
     $components = false;
     if ($type === false) {
         foreach (self::$fileFormats as $format) {
             if (!method_exists($format, 'savePublicKey')) {
                 continue;
             }
             try {
                 $components = $format::load($key, $this->password);
             } catch (\Exception $e) {
                 $components = false;
             }
             if ($components !== false) {
                 break;
             }
         }
     } else {
         $format = strtolower($type);
         if (isset(self::$fileFormats[$format])) {
             $format = self::$fileFormats[$format];
             try {
                 $components = $format::load($key, $this->password);
             } catch (\Exception $e) {
                 $components = false;
             }
         }
     }
     if ($components === false) {
         $this->format = false;
         return false;
     }
     $this->format = $format;
     if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) {
         $this->modulus = $components['modulus'];
         $this->exponent = $this->publicExponent = $components['publicExponent'];
         return true;
     }
     $this->publicExponent = $components['publicExponent'];
     return true;
 }