Exemplo n.º 1
0
 public function setPublicKey($key = false, $type = 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;
 }
Exemplo n.º 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 & 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);
 }
Exemplo n.º 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.
  *
  * 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
  * @param Integer $type optional
  * @return Boolean
  */
 function setPublicKey($key, $type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
 {
     $components = $this->_parseKey($key, $type);
     if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) {
         return false;
     }
     $this->publicExponent = $components['publicExponent'];
 }
Exemplo n.º 4
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
  * @param Integer $type optional
  * @return Boolean
  */
 function setPublicKey($key, $type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
 {
     $components = $this->_parseKey($key, $type);
     if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) {
         user_error('Trying to load a public key?  Use loadKey() instead.  It\'s called loadKey() and not loadPrivateKey() for a reason.', E_USER_NOTICE);
         return false;
     }
     $this->publicExponent = $components['publicExponent'];
     return true;
 }
Exemplo n.º 5
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 ($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) {
             try {
                 $components = $this->_parseKey($key, $type);
                 break;
             } catch (FormatNotSupportedException $e) {
             }
         }
         if (!isset($components)) {
             throw new FormatNotSupportedException('Unable to find matching format');
         }
     } else {
         $components = $this->_parseKey($key, $type);
     }
     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;
 }
Exemplo n.º 6
0
 /**
  * 
  * @param unknown $text string
  * @param unknown $unblindf string: hex encoded bigInt
  * @param unknown $blindedHash string: hex encoded bigInt
  */
 function verifyBlindedHash($text, $unblindf, $blindedHash)
 {
     $hashByMe = hash('sha256', $text);
     $hashByMeBigInt = new Math_BigInteger($hashByMe, 16);
     $blindedHashBigInt = new Math_BigInteger($blindedHash, 16);
     $signedblindedHash = $this->myPrivateKey['privRsa']->_rsasp1($blindedHashBigInt);
     $unblindf = new Math_BigInteger($unblindf, 16);
     $unblindedSignedHash = $this->myPrivateKey['privRsa']->rsaUnblind($signedblindedHash, $unblindf);
     $verifyHash = $this->myPrivateKey['pubRsa']->_rsasp1($unblindedSignedHash);
     $hashOk = $hashByMeBigInt->equals($verifyHash);
     if ($hashOk !== true) {
         WrongRequestException::throwException(1002, "Error: blinded hash verification failed", "expected hash: {$hashByMe}, got unblinded hash: {$verifyHash}, blinded Hash {$blindedHash}, unblinding factor {$unblindf}");
     }
     return $hashOk;
 }