예제 #1
2
 /**
  * Attest to the legitimacy of a particular block
  * 
  * @param array $blocks
  */
 private function notarizeBlocks($blocks)
 {
     // We timebox our notary communications, just because
     $message = \json_encode(['datetime' => \date('c'), 'blocks' => $blocks]);
     // Load our signing key from the configuration
     $skey = \Sodium::crypto_sign_secretkey(\base64_decode($this->config['crypto']['signing_key']));
     // Grab a detached signature
     $signature = \Sodium::crypto_sign_detached($message, $skey);
     return \json_encode(['message' => \base64_encode($message), 'signature' => \base64_encode($signature)], JSON_PRETTY_PRINT);
 }
예제 #2
1
 public function validateSignature($orig, $sig, $pk)
 {
     // Bob verifies and removes the signature
     $msg_orig = \Sodium::crypto_sign_open($sig . $orig, $pk);
     $check = $msg_orig !== false;
     if (!$check) {
         var_dump($orig);
         var_dump(base64_encode($sig));
         var_dump(base64_encode($pk));
     }
     return $check;
 }
예제 #3
1
 /**
  * Decrypt a string
  * 
  * @param string $encoded
  * @return string
  */
 public function decrypt($encoded)
 {
     $decoded = \base64_decode($encoded);
     \Sodium::memzero($encoded);
     $nonce = \mb_substr($decoded, 0, \Sodium::CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
     $ciphertext = \mb_substr($decoded, \Sodium::CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
     $decrypted = \Sodium::crypto_secretbox_open($ciphertext, $nonce, $this->key->getKey());
     \Sodium::memzero($decoded);
     \Sodium::memzero($nonce);
     \Sodium::memzero($ciphertext);
     return $decrypted;
 }
예제 #4
1
 /**
  * @param \ParagonIE\AsgardClient\Structures\MerkleTree $tree
  * @param string $prevhash
  * @param string $nexthash
  */
 public function __construct(MerkleTree $tree, $prevhash = null, $nexthash = null)
 {
     $this->merkleTree = $tree;
     $this->currentHash = $tree->getRoot();
     $this->previousHash = $prevhash;
     $this->nextHash = $nexthash;
     if (empty($prevhash)) {
         $this->tailHash = $this->currentHash;
     } else {
         $this->tailHash = \Sodium::crypto_generichash(\bin2hex($this->previousHash) . \bin2hex($this->currentHash));
     }
 }
예제 #5
0
 public function post()
 {
     \header('Content-Type: application/json');
     if (!empty($_POST['message']) && !empty($_POST['signature']) && !empty($_POST['prevhash']) && !empty($_POST['merkleroot']) && !empty($_POST['block'])) {
         // Plausibly a message from the mother ship? Let's check our
         $signature = \base64_decode($_POST['signature']);
         $message = \base64_decode($_POST['message']);
         $pubkey = \base64_decode(\ParagonIE\AsgardClient\MetaData::AUTHORIZED_PUBLICKEY);
         if (\Sodium::crypto_sign_verify_detached($signature, $message, $pubkey)) {
             // Should be the same as a new message
             $re_encode = \json_encode(['signature' => $_POST['signature'], 'message' => $_POST['message']], JSON_PRETTY_PRINT);
             return $this->insertBlock($re_encode, $_POST['merkleroot'], $_POST['block'], $_POST['prevhash']);
         }
     }
     // Usual case: You are not l33t enough to grab our priv8 key
     echo \json_encode(['error' => 'Access denied.'], JSON_PRETTY_PRINT);
     exit;
 }
예제 #6
0
 /**
  * Verify new blocks with our peers
  * 
  * @param array $newBlocks
  * @param boolean $echo
  */
 private function peerPressure($newBlocks, $echo = false)
 {
     if ($echo) {
         echo "\n\tVerifying new blocks...\n";
     }
     // SELECT hash FROM blocks ORDER BY id DESC
     $lasthash = $this->bc->selectOne('blocks', ['hash'], [], [['id', 'DESC']], [], 0, 1);
     // SELECT * FROM notaries
     $notaries = $this->db->select('notaries');
     $consensus = ['fail' => 0, 'timeout' => 0, 'pass' => 0];
     foreach ($notaries as $peer) {
         $hostname = $peer['https'] > 0 ? 'https://' . $peer['host'] . ':' . $peer['port'] : 'http://' . $peer['host'] . ':' . $peer['port'];
         $net = new Base\HTTPS($hostname);
         $body = $net->get('/blockchain/hash/' . $lasthash);
         if (!empty($body)) {
             $response = \json_decode($body, true);
         } else {
             ++$consensus['timeout'];
             continue;
         }
         if (!empty($response['message']) && !empty($response['signature'])) {
             // Let's grab everything we need to verify the  detached signature
             $msg = \base64_decode($response['message']);
             $sig = \base64_decode($response['signature']);
             $pubkey = \base64_decode($peer['publickey']);
             if (\Sodium::crypto_sign_verify_detached($sig, $msg, $pubkey)) {
                 // At this point, we know the signature was valid.
                 $analysis = $this->analyzePeerResponse(\json_decode($msg, true), $newBlocks, $peer, $echo);
                 if ($analysis) {
                     ++$consensus['pass'];
                     // Don't run the last line of the loop
                     continue;
                 }
             } elseif ($echo) {
                 echo $this->c['red'], 'Peer signature failed: ', $peer['nickname'], $this->c[''], "\n";
             }
         } elseif ($echo) {
             echo $this->c['red'], 'Peer connection failed or response invalid: ', $peer['nickname'], $this->c[''], "\n";
         }
         // When something fails, increment it here.
         ++$consensus['fail'];
     }
     // After the foreach loop runs, decide whether or not to proceed.
     if ($consensus['fail'] === 0 && $consensus['pass'] > 0) {
         // No failures, at least 1 success
         return true;
     }
     if ($echo) {
         echo $this->c['red'], 'An error has occurred!', $this->c[''], "\n", 'Attempting to synchronize the distributed ledger failed!', "\n";
     }
     return false;
 }
예제 #7
0
 /**
  * Calculate the hash tree for a given dataset:
  *     0 => Merkle Root
  *     1 => Left Child
  *     2 => Right Child,
  *     3 => LL, 4 => LR
  *     5 => RL, 6 => RR,
  *     ...
  * 
  * @return array
  */
 public function getTree()
 {
     $numLeaves = count($this->leaves);
     // get the next 2^N larger than our dataset
     $baseIterate = (int) pow(2, ceil(log($numLeaves, 2)));
     $hashes = [];
     // Initial population
     for ($i = 0; $i < $baseIterate; ++$i) {
         if ($i >= $numLeaves) {
             // Following Bitcoin's lead; keep hashing the remainder
             $hashes[] = $this->leaves[$numLeaves - 1]['hash'];
         } else {
             $hashes[] = $this->leaves[$i]['hash'];
         }
     }
     $tree = $hashes;
     // Let's hash together until we have one node left
     do {
         $tmp = [];
         // Iterate through the first level of the tree
         $j = 0;
         for ($i = 0; $i < $baseIterate; $i += 2) {
             $tmp[$j] = \Sodium::crypto_generichash($hashes[$i] . $hashes[$i + 1]);
             \array_unshift($tree, $tmp[$j]);
             ++$j;
         }
         $hashes = $tmp;
         $baseIterate = $baseIterate >> 1;
     } while ($baseIterate > 1);
     return $tree;
 }
<?php

/**
 * @author rugk
 * @copyright Copyright (c) 2015-2016 rugk
 * @license MIT
 */
// check load state
if (extension_loaded('libsodium')) {
    echo 'libsodium is loaded<br/>';
} else {
    echo 'libsodium is not loaded<br/>';
    exit;
}
// check version
if (method_exists('Sodium', 'sodium_version_string')) {
    echo 'you use an old version of libsodium (<0.2.0)<br/>';
    echo 'Sodium version: ' . Sodium::sodium_version_string();
} else {
    echo 'you use a recent version of libsodium<br/>';
    echo 'Sodium version: ' . \Sodium\version_string();
}
예제 #9
0
 /**
  * Let's get the latest package information from the mirror
  * 
  * @param string $publickey Public key (base64 encoded)
  * @param string $secretkey Secret key (base64 encoded)
  * @param string $package (optional; defaults to grabbing all)
  * @return array
  */
 public function updatePackageInfo($publickey, $secretkey, $package = null)
 {
     $requesting = [];
     if (!empty($package)) {
         // We just need the one
         $requesting[] = $package;
     } else {
         // Let's grab all the names
         foreach (self::$userConfig->get(['packages']) as $pkg) {
             $requesting[] = $pkg['name'];
         }
     }
     // We send off our public key, and get an encrypted response back.
     $apiResponse = $this->http->post($this->basepath . self::$api['package']['latest'], ['packages' => $requesting, 'publickey' => $publickey]);
     $api = \json_decode($apiResponse, true);
     if (!empty($api['error']) || empty($api['packages']) || empty($api['nonce']) || empty($api['publickey'])) {
         return false;
     }
     // We need to decrypt the response
     // Server's public key (can rotate)
     $serverPublicKey = \base64_decode($api['publickey']);
     // A nonce used to decrypt
     $serverNonce = \base64_decode($api['nonce']);
     // What packages are there?
     $ciphertext = \base64_decode($api['packages']);
     // Calculate symmetric encryption key
     $eBoxKey = \Sodium::crypto_box_keypair_from_secretkey_and_publickey($secretkey, \base64_decode($serverPublicKey));
     // Let's grab our solution
     $updates = \Sodium::crypto_box_open($ciphertext, $serverNonce, $eBoxKey);
     // We want an array
     return \json_decode($updates, true);
 }
예제 #10
0
 /**
  * Verify the checksums on $tmp_file for the package we are verifying
  * 
  * @param array $blockdata
  * @param string $tmp_file
  * @return boolean
  */
 private function verifyChecksums($blockdata, $tmp_file)
 {
     $matches = 0;
     $filedata = \file_get_contents($tmp_file);
     // Now let's check all of the hashes
     foreach ($blockdata['checksums'] as $algo => $hash) {
         switch ($algo) {
             case 'BLAKE2b':
                 // We used libsodium
                 $line = \Sodium::crypto_generichash($filedata);
                 break;
             default:
                 // A simple hash (SHA256, etc)
                 $line = \hash($algo, $filedata, true);
         }
         if (\hash_equals($line, \Sodium::sodium_hex2bin($hash))) {
             ++$matches;
         } else {
             die("{$algo} hash did not match!");
         }
     }
     unset($filedata);
     // explicitly free
     return $matches > 0;
 }
예제 #11
0
 /**
  * Helper method to handle challenge-response authentication. Just returns
  * the decrypted response.
  * 
  * @param string $serverPublicKey
  * @param string $serverNonce
  * @param string $challenge
  * @param string $secretkey
  * @return string
  */
 public static function challengeResponse($serverPublicKey, $serverNonce, $challenge, $secretkey)
 {
     $_serverPublicKey = \base64_decode($serverPublicKey);
     $_serverNonce = \base64_decode($serverNonce);
     $_challenge = \base64_decode($challenge);
     // Calculate symmetric encryption key
     $eBoxKey = \Sodium::crypto_box_keypair_from_secretkey_and_publickey($secretkey, $_serverPublicKey);
     // Let's grab our solution
     $result = \Sodium::crypto_box_open($_challenge, $_serverNonce, $eBoxKey);
     \Sodium::sodium_memzero($eBoxKey);
     return $result;
 }
예제 #12
0
파일: SSH2.php 프로젝트: bitking/sysPass
 /**
  * Key Exchange
  *
  * @param string $kexinit_payload_server
  * @throws \UnexpectedValueException on receipt of unexpected packets
  * @throws \RuntimeException on other errors
  * @throws \phpseclib\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible
  * @access private
  */
 function _key_exchange($kexinit_payload_server)
 {
     $kex_algorithms = array('*****@*****.**', 'diffie-hellman-group1-sha1', 'diffie-hellman-group14-sha1', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group-exchange-sha256');
     if (!class_exists('\\Sodium')) {
         $kex_algorithms = array_diff($kex_algorithms, array('*****@*****.**'));
     }
     $server_host_key_algorithms = array('ssh-rsa', 'ssh-dss');
     $encryption_algorithms = array('arcfour256', 'arcfour128', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc', 'blowfish-ctr', 'blowfish-cbc', '3des-ctr', '3des-cbc');
     if (extension_loaded('openssl') && !extension_loaded('mcrypt')) {
         // OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to
         // instances that do not use continuous buffers
         $encryption_algorithms = array_diff($encryption_algorithms, array('arcfour256', 'arcfour128', 'arcfour'));
     }
     if (class_exists('\\phpseclib\\Crypt\\RC4') === false) {
         $encryption_algorithms = array_diff($encryption_algorithms, array('arcfour256', 'arcfour128', 'arcfour'));
     }
     if (class_exists('\\phpseclib\\Crypt\\Rijndael') === false) {
         $encryption_algorithms = array_diff($encryption_algorithms, array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc'));
     }
     if (class_exists('\\phpseclib\\Crypt\\Twofish') === false) {
         $encryption_algorithms = array_diff($encryption_algorithms, array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc'));
     }
     if (class_exists('\\phpseclib\\Crypt\\Blowfish') === false) {
         $encryption_algorithms = array_diff($encryption_algorithms, array('blowfish-ctr', 'blowfish-cbc'));
     }
     if (class_exists('\\phpseclib\\Crypt\\TripleDES') === false) {
         $encryption_algorithms = array_diff($encryption_algorithms, array('3des-ctr', '3des-cbc'));
     }
     $encryption_algorithms = array_values($encryption_algorithms);
     $mac_algorithms = array('hmac-sha2-256', 'hmac-sha1-96', 'hmac-sha1', 'hmac-md5-96', 'hmac-md5');
     $compression_algorithms = array('none');
     // some SSH servers have buggy implementations of some of the above algorithms
     switch ($this->server_identifier) {
         case 'SSH-2.0-SSHD':
             $mac_algorithms = array_values(array_diff($mac_algorithms, array('hmac-sha1-96', 'hmac-md5-96')));
     }
     $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 = Random::string(16);
     $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
     // 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 = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
     $decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
     if ($decryptKeyLength === null) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found');
     }
     $encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
     $encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
     if ($encryptKeyLength === null) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found');
     }
     // through diffie-hellman key exchange a symmetric key is obtained
     $kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
     if ($kex_algorithm === false) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found');
     }
     // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
     $exchange_hash_rfc4419 = '';
     if ($kex_algorithm === '*****@*****.**') {
         $x = Random::string(32);
         $eBytes = \Sodium::crypto_box_publickey_from_secretkey($x);
         $clientKexInitMessage = NET_SSH2_MSG_KEX_ECDH_INIT;
         $serverKexReplyMessage = NET_SSH2_MSG_KEX_ECDH_REPLY;
         $kexHash = new Hash('sha256');
     } else {
         if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
             $dh_group_sizes_packed = pack('NNN', $this->kex_dh_group_size_min, $this->kex_dh_group_size_preferred, $this->kex_dh_group_size_max);
             $packet = pack('Ca*', NET_SSH2_MSG_KEXDH_GEX_REQUEST, $dh_group_sizes_packed);
             if (!$this->_send_binary_packet($packet)) {
                 return false;
             }
             $response = $this->_get_binary_packet();
             if ($response === false) {
                 user_error('Connection closed by server');
                 return false;
             }
             extract(unpack('Ctype', $this->_string_shift($response, 1)));
             if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
                 user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP');
                 return false;
             }
             extract(unpack('NprimeLength', $this->_string_shift($response, 4)));
             $primeBytes = $this->_string_shift($response, $primeLength);
             $prime = new BigInteger($primeBytes, -256);
             extract(unpack('NgLength', $this->_string_shift($response, 4)));
             $gBytes = $this->_string_shift($response, $gLength);
             $g = new BigInteger($gBytes, -256);
             $exchange_hash_rfc4419 = pack('a*Na*Na*', $dh_group_sizes_packed, $primeLength, $primeBytes, $gLength, $gBytes);
             $clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT;
             $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY;
         } else {
             switch ($kex_algorithm) {
                 // see http://tools.ietf.org/html/rfc2409#section-6.2 and
                 // http://tools.ietf.org/html/rfc2412, appendex E
                 case 'diffie-hellman-group1-sha1':
                     $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
                     break;
                     // see http://tools.ietf.org/html/rfc3526#section-3
                 // see http://tools.ietf.org/html/rfc3526#section-3
                 case 'diffie-hellman-group14-sha1':
                     $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
                     break;
             }
             // For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1
             // the generator field element is 2 (decimal) and the hash function is sha1.
             $g = new BigInteger(2);
             $prime = new BigInteger($prime, 16);
             $clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT;
             $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY;
         }
         switch ($kex_algorithm) {
             case 'diffie-hellman-group-exchange-sha256':
                 $kexHash = new Hash('sha256');
                 break;
             default:
                 $kexHash = new Hash('sha1');
         }
         /* 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 */
         $one = new BigInteger(1);
         $keyLength = min($kexHash->getLength(), max($encryptKeyLength, $decryptKeyLength));
         $max = $one->bitwise_leftShift(16 * $keyLength);
         // 2 * 8 * $keyLength
         $max = $max->subtract($one);
         $x = $one->random($one, $max);
         $e = $g->modPow($x, $prime);
         $eBytes = $e->toBytes(true);
     }
     $data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
     if (!$this->_send_binary_packet($data)) {
         throw new \RuntimeException('Connection closed by server');
     }
     $response = $this->_get_binary_packet();
     if ($response === false) {
         throw new \RuntimeException('Connection closed by server');
     }
     extract(unpack('Ctype', $this->_string_shift($response, 1)));
     if ($type != $serverKexReplyMessage) {
         throw new \UnexpectedValueException('Expected SSH_MSG_KEXDH_REPLY');
     }
     $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']);
     $temp = unpack('Nlength', $this->_string_shift($response, 4));
     $this->signature = $this->_string_shift($response, $temp['length']);
     $temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
     $this->signature_format = $this->_string_shift($this->signature, $temp['length']);
     if ($kex_algorithm === '*****@*****.**') {
         if (strlen($fBytes) !== 32) {
             user_error('Received curve25519 public key of invalid length.');
             return false;
         }
         $key = new BigInteger(\Sodium::crypto_scalarmult($x, $fBytes), 256);
         \Sodium::sodium_memzero($x);
     } else {
         $f = new BigInteger($fBytes, -256);
         $key = $f->modPow($x, $prime);
     }
     $keyBytes = $key->toBytes(true);
     $this->exchange_hash = pack('Na*Na*Na*Na*Na*a*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, $exchange_hash_rfc4419, strlen($eBytes), $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes);
     $this->exchange_hash = $kexHash->hash($this->exchange_hash);
     if ($this->session_id === false) {
         $this->session_id = $this->exchange_hash;
     }
     $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
     if ($server_host_key_algorithm === false) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found');
     }
     if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new \RuntimeException('Server Host Key Algorithm Mismatch');
     }
     $packet = pack('C', NET_SSH2_MSG_NEWKEYS);
     if (!$this->_send_binary_packet($packet)) {
         return false;
     }
     $response = $this->_get_binary_packet();
     if ($response === false) {
         throw new \RuntimeException('Connection closed by server');
     }
     extract(unpack('Ctype', $this->_string_shift($response, 1)));
     if ($type != NET_SSH2_MSG_NEWKEYS) {
         throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS');
     }
     $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
     $this->encrypt = $this->_encryption_algorithm_to_crypt_instance($encrypt);
     if ($this->encrypt) {
         if ($this->crypto_engine) {
             $this->encrypt->setEngine($this->crypto_engine);
         }
         if ($this->encrypt->block_size) {
             $this->encrypt_block_size = $this->encrypt->block_size;
         }
         $this->encrypt->enableContinuousBuffer();
         $this->encrypt->disablePadding();
         $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
         while ($this->encrypt_block_size > strlen($iv)) {
             $iv .= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
         }
         $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
         $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id);
         while ($encryptKeyLength > strlen($key)) {
             $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
         }
         $this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
     }
     $this->decrypt = $this->_encryption_algorithm_to_crypt_instance($decrypt);
     if ($this->decrypt) {
         if ($this->crypto_engine) {
             $this->decrypt->setEngine($this->crypto_engine);
         }
         if ($this->decrypt->block_size) {
             $this->decrypt_block_size = $this->decrypt->block_size;
         }
         $this->decrypt->enableContinuousBuffer();
         $this->decrypt->disablePadding();
         $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
         while ($this->decrypt_block_size > strlen($iv)) {
             $iv .= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
         }
         $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
         $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id);
         while ($decryptKeyLength > strlen($key)) {
             $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
         }
         $this->decrypt->setKey(substr($key, 0, $decryptKeyLength));
     }
     /* The "arcfour128" algorithm is the RC4 cipher, as described in
                [SCHNEIER], using a 128-bit key.  The first 1536 bytes of keystream
                generated by the cipher MUST be discarded, and the first byte of the
                first encrypted packet MUST be encrypted using the 1537th byte of
                keystream.
     
                -- http://tools.ietf.org/html/rfc4345#section-4 */
     if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') {
         $this->encrypt->encrypt(str_repeat("", 1536));
     }
     if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') {
         $this->decrypt->decrypt(str_repeat("", 1536));
     }
     $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
     if ($mac_algorithm === false) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found');
     }
     $createKeyLength = 0;
     // ie. $mac_algorithm == 'none'
     switch ($mac_algorithm) {
         case 'hmac-sha2-256':
             $this->hmac_create = new Hash('sha256');
             $createKeyLength = 32;
             break;
         case 'hmac-sha1':
             $this->hmac_create = new Hash('sha1');
             $createKeyLength = 20;
             break;
         case 'hmac-sha1-96':
             $this->hmac_create = new Hash('sha1-96');
             $createKeyLength = 20;
             break;
         case 'hmac-md5':
             $this->hmac_create = new Hash('md5');
             $createKeyLength = 16;
             break;
         case 'hmac-md5-96':
             $this->hmac_create = new Hash('md5-96');
             $createKeyLength = 16;
     }
     $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
     if ($mac_algorithm === false) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found');
     }
     $checkKeyLength = 0;
     $this->hmac_size = 0;
     switch ($mac_algorithm) {
         case 'hmac-sha2-256':
             $this->hmac_check = new Hash('sha256');
             $checkKeyLength = 32;
             $this->hmac_size = 32;
             break;
         case 'hmac-sha1':
             $this->hmac_check = new Hash('sha1');
             $checkKeyLength = 20;
             $this->hmac_size = 20;
             break;
         case 'hmac-sha1-96':
             $this->hmac_check = new Hash('sha1-96');
             $checkKeyLength = 20;
             $this->hmac_size = 12;
             break;
         case 'hmac-md5':
             $this->hmac_check = new Hash('md5');
             $checkKeyLength = 16;
             $this->hmac_size = 16;
             break;
         case 'hmac-md5-96':
             $this->hmac_check = new Hash('md5-96');
             $checkKeyLength = 16;
             $this->hmac_size = 12;
     }
     $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id);
     while ($createKeyLength > strlen($key)) {
         $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
     }
     $this->hmac_create->setKey(substr($key, 0, $createKeyLength));
     $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id);
     while ($checkKeyLength > strlen($key)) {
         $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
     }
     $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
     $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
     if ($compression_algorithm === false) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found');
     }
     $this->decompress = $compression_algorithm == 'zlib';
     $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
     if ($compression_algorithm === false) {
         $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
         throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found');
     }
     $this->compress = $compression_algorithm == 'zlib';
     return true;
 }
예제 #13
0
 public function getTag()
 {
     if (empty($this->server_config['crypto']['signing_key'])) {
         echo "No keypair found. Keys are generated when you first start your notary.\n";
         echo "\nTry running this first:\n\tasgard notary start\n";
         exit;
     }
     $pubkey = \Sodium::crypto_sign_publickey(\base64_decode($this->server_config['crypto']['signing_key']));
     $tag = 'http';
     if ($this->server_config['tls']['enabled']) {
         $tag .= 's';
     }
     $tag .= '://' . $this->server_config['host'];
     $tag .= ':' . $this->server_config['port'];
     $tag .= '/#';
     $tag .= \urlencode(\base64_encode($pubkey));
     echo $tag . "\n";
 }
예제 #14
0
    include_once FILENAME_PRIVKEY;
    if (!defined('MSGAPI_PRIVATE_KEY')) {
        $errCol->registerError('files', 'privKey', 'Not all constants are defined.');
    } else {
        if (MSGAPI_PRIVATE_KEY == '' || !KeyCheck(MSGAPI_PRIVATE_KEY, 'private:')) {
            $errCol->registerError('files', 'privKey', '\'MSGAPI_PRIVATE_KEY\' is invalid.');
        }
    }
}
//libsodium: private key
$errCol->registerGenericMessages('libsodium', 'state', 'Libsodium is loaded.', 'Libsodium is not loaded.');
$errCol->registerGenericMessages('libsodium', 'version', 'You use a recent version of libsodium.', 'You use an old outdated version of libsodium. It is very much recommend to update it.');
if (extension_loaded('libsodium')) {
    $errCol->registerSuccess('libsodium', 'state');
    if (method_exists('Sodium', 'sodium_version_string')) {
        $errCol->registerWarning('libsodium', 'version', 'Sodium version: ' . Sodium::sodium_version_string());
    } else {
        $errCol->registerSuccess('libsodium', 'version', 'Sodium version: ' . \Sodium\version_string());
    }
} else {
    $errCol->registerWarning('libsodium', 'state', 'It is very much recommend to install and load it.');
    if (PHP_INT_SIZE < 8) {
        $errCol->registerError('libsodium', '64bit', 'To use the SDK without libsodium you have to use a 64bit version of PHP.');
    }
}
//evaluate checks and prepare for an output of the results
$fileCheckResults = $errCol->evaluateChecks('files');
$libsodiumCheckResults = $errCol->evaluateChecks('libsodium', false);
?>

<!DOCTYPE html>
예제 #15
0
 /**
  * Get a new salt for use with 
  * 
  * @return string
  */
 public static function newPasswordSalt()
 {
     return \Sodium::randombytes_buf(\Sodium::CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES);
 }
/**
 * If the libsodium PHP extension is loaded, we'll use it above any other
 * solution.
 *
 * libsodium-php project:
 * @ref https://github.com/jedisct1/libsodium-php
 *
 * @param int $bytes
 *
 * @throws Exception
 *
 * @return string
 */
function random_bytes($bytes)
{
    try {
        $bytes = RandomCompat_intval($bytes);
    } catch (TypeError $ex) {
        throw new TypeError('random_bytes(): $bytes must be an integer');
    }
    if ($bytes < 1) {
        throw new Error('Length must be greater than 0');
    }
    /**
     * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
     * generated in one invocation.
     */
    if ($bytes > 2147483647) {
        $buf = '';
        for ($i = 0; $i < $bytes; $i += 1073741824) {
            $n = $bytes - $i > 1073741824 ? 1073741824 : $bytes - $i;
            $buf .= Sodium::randombytes_buf($n);
        }
    } else {
        $buf = Sodium::randombytes_buf($bytes);
    }
    if ($buf !== false) {
        if (RandomCompat_strlen($buf) === $bytes) {
            return $buf;
        }
    }
    /**
     * If we reach here, PHP has failed us.
     */
    throw new Exception('Could not gather sufficient random data');
}
예제 #17
-1
function ShowLibsodiumVersion()
{
    if (method_exists('Sodium', 'sodium_version_string')) {
        echo Sodium::sodium_version_string();
    } else {
        echo \Sodium\version_string();
    }
}
예제 #18
-1
 /**
  * Get a randomly selected mirror from our database
  * 
  * @return array
  */
 public function getRandomMirror()
 {
     $iCount = $this->db->selectOne('mirrors', 'count(id)');
     if ($iCount < 0) {
         throw new \Exception("There are no mirrors in the database.");
     }
     $iRandom = \Sodium::randombytes_uniform($iCount);
     return $this->db->selectRow('mirrors', [], [], [], [], $iRandom);
 }