Exemplo n.º 1
0
 /**
  * Creates new hex based on params.
  * @param array|string $data
  * @param boolean $hidden
  * @param string $owner player
  * @return Hex
  */
 public static function create($data, $hidden = false, $owner = null)
 {
     $hex = new Hex();
     if (is_array($data)) {
         $hex->setType(self::TYPE_SPACE);
         if (!empty($data['planets'])) {
             foreach ($data['planets'] as $name) {
                 $hex->getPlanets()->add(Planet::create($name, $owner));
             }
         }
         if (!empty($data['wormhole'])) {
             $hex->setWormhole($data['wormhole']);
         }
     } else {
         switch ($data) {
             case self::WORMHOLE_ALPHA:
             case self::WORMHOLE_BETA:
                 $hex->setType(self::TYPE_SPACE);
                 $hex->setWormhole($data);
                 break;
             case self::TYPE_SPACE:
             case self::TYPE_NEBULA:
             case self::TYPE_ASTEROID:
             case self::TYPE_NOVA:
                 $hex->setType($data);
         }
     }
     if ($hidden) {
         $hex->setHidden($hidden);
     }
     return $hex;
 }
Exemplo n.º 2
0
 static function pretty_print($str, $address_offset = 0)
 {
     $result = "";
     $address = 0;
     $length = strlen($str);
     while ($address < $length) {
         $first_block_raw = substr($str, $address, 8);
         $second_block_raw = substr($str, $address + 8, 8);
         $result .= sprintf("%08x  ", $address + $address_offset);
         $result .= Hex::dump($first_block_raw);
         $result .= "  ";
         $result .= Hex::dump($second_block_raw);
         $missing_chars = 0;
         if ($length - $address < 16) {
             $missing_chars = 16 - ($length - $address);
             $filler_length = $missing_chars * 3;
             if ($length - $address < 9) {
                 $filler_length -= 1;
             }
             $result .= str_repeat(' ', $filler_length);
         }
         $first_block = Hex::print_dump($first_block_raw);
         if ($length - $address > 8) {
             $second_block = Hex::print_dump($second_block_raw);
         } else {
             $second_block = '';
         }
         if ($missing_chars > 0) {
             $second_block .= str_repeat(' ', $missing_chars);
         }
         $result .= "  |{$first_block}{$second_block}|\n";
         $address += 16;
     }
     return $result;
 }
Exemplo n.º 3
0
 public function __construct($byteString)
 {
     $this->platformID = $this->getShort($byteString, self::HEADER_START);
     $this->flightGroupCount = $this->getShort($byteString, self::HEADER_FG);
     $this->messageCount = $this->getShort($byteString, self::HEADER_MSG);
     $this->unk1 = $this->getByte($byteString, self::HEADER_UNK);
     $this->unk2 = $this->getByte($byteString, self::HEADER_UNK + 2);
     $this->unk3 = $this->getBool($byteString, self::HEADER_UNK + 5);
     $this->unk4 = $this->getByte($byteString, 40);
     $this->unk5 = $this->getByte($byteString, 80);
     $this->missionType = $this->getByte($byteString, self::HEADER_MISSION);
     $this->unk6 = $this->getBool($byteString, self::HEADER_MISSION + 1);
     $this->timeLimitMinutes = $this->getByte($byteString, self::HEADER_TIME);
     $this->timeLiimitSeconds = $this->getByte($byteString, self::HEADER_TIME + 1);
     $this->hex = \Hex::hexToStr($byteString);
 }
Exemplo n.º 4
0
 public function __construct($byteString)
 {
     $this->platformID = getShort($byteString, self::HEADER_START);
     $this->flightGroupCount = getShort($byteString, self::HEADER_FG);
     $this->messageCount = getShort($byteString, self::HEADER_MSG);
     for ($i = 0; $i < self::IFF_COUNT; $i++) {
         $this->IFFNames[] = getString($byteString, self::HEADER_IFF + $i * self::IFF_LENGTH, self::IFF_LENGTH);
     }
     for ($r = 0; $r < self::REGION_COUNT; $r++) {
         $this->regionNames[] = getString($byteString, self::HEADER_REGION + $r * self::REGION_LENGTH, self::REGION_LENGTH);
     }
     for ($c = 0; $c < self::CARGO_COUNT; $c++) {
         $this->globalCargos[] = new GlobalCargo(substr($byteString, self::HEADER_CARGO + $c * GlobalCargo::LENGTH, GlobalCargo::LENGTH));
     }
     for ($g = 0; $g < self::GG_COUNT; $g++) {
         $this->globalGroupNames[] = getString($byteString, self::HEADER_GG + $g * self::GG_LENGTH, self::GG_LENGTH);
     }
     $this->hangar = getByte($byteString, self::HEADER_HANGAR);
     $this->timeLimitMinutes = getByte($byteString, self::HEADER_TIME);
     $this->endMissionWhenComplete = getBool($byteString, self::HEADER_END);
     $this->briefingOfficer = getByte($byteString, self::HEADER_OFFICER);
     $this->briefingLogo = getByte($byteString, self::HEADER_LOGO);
     $this->hex = \Hex::hexToStr($byteString);
 }
Exemplo n.º 5
0
 function readHeader($path)
 {
     $ehb = file_get_contents($path . DIRECTORY_SEPARATOR . self::EHB);
     $hex = $ehb;
     $ehb = array();
     $ehb['unk1'] = ord($hex[1]);
     $ehb['title'] = substr($hex, 2, 50);
     $ehb['#'] = ord($hex[53]);
     $ehb['unk2'] = ord($hex[54]);
     $ehb['missions'] = array();
     $remaining = substr($hex, 55);
     for ($m = 0; $m < $ehb['#']; $m++) {
         $ehb['missions'][] = substr($remaining, 20 * $m, 20);
     }
     $remaining = substr($remaining, 21 * $ehb['#']);
     $ehb['rem'] = \Hex::hexToStr($remaining);
     for ($r = 0; $r < strlen($remaining); $r++) {
         $ehb['r' . $r] = ord($remaining[$r]);
     }
     $this->header = $ehb;
     $this->header['path'] = $path;
     $this->rot = ord($hex[1]);
     $this->missions = $ehb['missions'];
 }
Exemplo n.º 6
0
function resultFor($board)
{
    $game = new Hex($board);
    return $game->results();
}
Exemplo n.º 7
0
 /**
  * Connect to an SSHv1 server
  *
  * @return bool
  * @throws \UnexpectedValueException on receipt of unexpected packets
  * @throws \RuntimeException on other errors
  * @access private
  */
 function _connect()
 {
     $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
     if (!$this->fsock) {
         throw new \RuntimeException(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"));
     }
     $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)) {
         throw new \RuntimeException('Can only connect to SSH servers');
     }
     if ($parts[1][0] != 1) {
         throw new \RuntimeException("Cannot connect to {$parts['1']} servers");
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         throw new \UnexpectedValueException('Expected SSH_SMSG_PUBLIC_KEY');
     }
     $anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
     $this->_string_shift($response[self::RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
     $server_key_public_exponent = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
     $server_key_public_modulus = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[self::RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
     $host_key_public_exponent = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
     $host_key_public_modulus = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[self::RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[self::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[self::RESPONSE_DATA], 4)));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = Hex::decode(md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = 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 : self::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)) {
         throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY');
     }
     switch ($cipher) {
         //case self::CIPHER_NONE:
         //    $this->crypto = new \phpseclib\Crypt\Null();
         //    break;
         case self::CIPHER_DES:
             $this->crypto = new DES(DES::MODE_CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             // "The iv (initialization vector) is initialized to all zeroes."
             $this->crypto->setIV(str_repeat("", 8));
             break;
         case self::CIPHER_3DES:
             $this->crypto = new TripleDES(TripleDES::MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             // "All three initialization vectors are initialized to zero."
             $this->crypto->setIV(str_repeat("", 8));
             break;
             //case self::CIPHER_RC4:
             //    $this->crypto = new RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
     }
     $this->bitmap = self::MASK_CONNECTED;
     return true;
 }
Exemplo n.º 8
0
echo "\n";
echo "\n";
echo $z;
?>
	/512
</pre>
</div>
<div style="float:left; width: 30%;">
<pre>
	MERGE ATTEMPT
	<?php 
echo Hex::hexToStr($ehmTIEfix);
echo "\n";
echo "\n";
echo strlen($ehmTIEfix);
?>
</pre>
</div>
<div style="float:left; width: 30%;">
<pre>
	RAW EHM
	<?php 
echo Hex::hexToStr($ehmTIE);
echo "\n";
echo "\n";
echo $e;
?>
	/512
</pre>
</div>
</body>
 public function ParseAndSaveWorldMap($world_response, $descriptor)
 {
     $log_seq = 0;
     $func_args = func_get_args();
     $func_args[0] = 'Removed Hex Array. See WS Request Log.';
     $func_log_id = DataLoadLogDAO::startFunction($this->db, $this->data_load_id, __CLASS__, __FUNCTION__, $func_args);
     DataLoadLogDAO::logEvent2($this->db, $func_log_id, $log_seq++, 'INFO', $descriptor);
     // Get the Hexes section of the world response
     $success = $world_response['responses'][0]['return_value']['success'];
     if ($success != 1) {
         $reason = $world_response['responses'][0]['return_value']['reason'];
         DataLoadLogDAO::completeFunction($this->db, $func_log_id, "Error Getting Map Data: {$reason}", 1);
         // Even though this is technically a failure, we return true because we don't want to retry this request
         return true;
     }
     $world = $world_response['responses'][0]['return_value']['hexes'];
     $hex_count = 0;
     // Sometimes this happens but I'm not sure why... so I created a return code to try again...
     if (empty($world)) {
         DataLoadLogDAO::completeFunction($this->db, $func_log_id, 'No Hexes Found', 1);
         echo "No hexes found.\r\n";
         return false;
     }
     // Parse and store each Hex
     foreach ($world as $key => $hex_arr) {
         $hex_count++;
         // Take the array and create the Hex object
         $hex = Hex::FromJson($hex_arr);
         $hex->data_load_id = $this->data_load_id;
         // Set the world ID
         $hex->world_id = $this->auth->world_id;
         // Recalculate the x coordinate.  Not sure why they store the data this way.
         $hex->hex_x = (int) self::convertToMapCoordinate($hex->hex_x, $hex->hex_y);
         // Check if this hex already exists so we know whether we're inserting or updating
         $hex_exists = WorldMapDAO::checkHexExists($this->db, $hex->world_id, $hex->hex_x, $hex->hex_y);
         if ($hex->building_id) {
             $hex->building_id = BuildingDAO::getLocalIdFromGameId($this->db, $hex->building_id);
         }
         // Determine whether we should use the player ID or NPC ID
         if (isset($hex->player_id)) {
             $game_player_id = $hex->player_id;
         } else {
             if (isset($hex->npc_player_id)) {
                 $game_player_id = $hex->npc_player_id;
             } else {
                 $game_player_id = null;
             }
         }
         // Get the local Player ID from our database
         $player_id = PlayerDAO::getLocalIdFromGameId($this->db, $game_player_id);
         // Start building a new player record
         $player = new Player();
         // Set the local Player ID if we found one
         if ($player_id) {
             $player->id = $player_id;
         }
         // Set the world ID and game player ID
         $player->world_id = $hex->world_id;
         $player->game_player_id = $game_player_id;
         // Initialize flags to NULL
         $hex->is_sb = null;
         $hex->is_npc = null;
         // Handle Alliance Base as a special case
         if ($hex->is_guild_town_center === 1) {
             $hex->town_name = $hex->guild_name;
             $hex->player_name = $hex->guild_name;
             $hex->player_level = $hex->guild_town_phase;
             $hex->building_id = 15;
         }
         // If this is a town tile then we have additional information, so let's process it
         if (isset($hex->town_name) || in_array($hex->building_id, array(14))) {
             $hex->command_center = true;
             // Set base properties
             $hex->is_sb = ($hex->town_radius == 2 and $hex->building_id == 1) ? 1 : 0;
             $hex->is_npc = $hex->town_name === 'Renegade Outpost' ? 1 : 0;
             // Set the player's name and level
             $player->player_name = $hex->player_name;
             $player->level = $hex->player_level;
             $player->data_load_id = $this->data_load_id;
             // Calculate the end of the player's bubble
             if ($hex->immune_until_ts > 0) {
                 $player->immune_until = date('Y-m-d H:i:s', $hex->immune_until_ts);
             } else {
                 $player->immune_until = null;
             }
             // If this player is in a guild, process that information
             if (isset($hex->guild_id)) {
                 // Get the local Guild ID from our database
                 $guild_id = GuildDAO::getLocalIdFromGameId($this->db, $hex->guild_id);
                 // If we didn't find this guild, then start building the record.
                 // Otherwise, don't bother because this information won't change frequently.
                 if (!$guild_id) {
                     $guild = new Guild();
                     $guild->world_id = $hex->world_id;
                     $guild->game_guild_id = $hex->guild_id;
                     $guild->guild_name = $hex->guild_name;
                     $guild->data_load_id = $this->data_load_id;
                     // Insert the guild record into our database and keep the new local ID for later
                     $guild_id = GuildDAO::insertGuild($this->db, $guild);
                     if ($this->db->hasError()) {
                         echo 'Error inserting Guild: ';
                         print_r($this->db->getError());
                         $log_msg = print_r($guild, true) . "\r\n\r\n" . print_r($this->db->getError(), true);
                         DataLoadLogDAO::logEvent2($this->db, $func_log_id, $log_seq++, 'ERROR', "Error inserting Guild [{$guild->guild_name}] into World [{$guild->world_id}]", $log_msg, 1);
                         echo "\r\n";
                     }
                 }
                 // Set the player's guild
                 $player->guild_id = $guild_id;
             }
         }
         // If this player didn't already exist in our database, create it.  Otherwise, update it.
         if (!$player_id) {
             if ($game_player_id) {
                 //DataLoadLogDAO::logEvent2($this->db, $func_log_id, $log_seq++, 'DEBUG', "Inserting Player [{$player->player_name}] into World [{$player->world_id}]", var_export($player, true));
                 $player_id = PlayerDAO::insertPlayer($this->db, $player);
                 if ($this->db->hasError()) {
                     echo 'Error inserting Player: ';
                     print_r($this->db->getError());
                     echo "\r\n";
                     $log_msg = print_r($player, true) . "\r\n\r\n" . print_r($this->db->getError(), true);
                     DataLoadLogDAO::logEvent2($this->db, $func_log_id, $log_seq++, 'ERROR', "Error inserting Player [{$player->player_name}] into World [{$player->world_id}]", $log_msg, 1);
                 }
             }
         } else {
             if ($player->player_name) {
                 //DataLoadLogDAO::logEvent2($this->db, $func_log_id, $log_seq++, 'DEBUG', "Updating Player [{$player->player_name}] in World [{$player->world_id}]", var_export($player, true));
                 // Update the player, but exclude battle points, power, and the number of bases because these aren't available in this case
                 $updateCount = PlayerDAO::updatePlayer($this->db, $player, array('battle_points', 'glory_points', 'bases'));
                 if ($this->db->hasError()) {
                     echo 'Error updating Player: ';
                     print_r($this->db->getError());
                     echo "\r\n";
                     $log_msg = var_export($player, true) . "\r\n\r\n" . print_r($this->db->getError(), true);
                     DataLoadLogDAO::logEvent2($this->db, $func_log_id, $log_seq++, 'ERROR', "Error updating Player [{$player->player_name}] in World [{$player->world_id}]", $log_msg, 1);
                 }
             }
         }
         // Set the player ID on the hex tile to the local database ID
         if (isset($hex->player_id) || isset($hex->npc_player_id)) {
             $hex->player_id = $player_id;
         }
         // Insert or update the hex record
         if ($hex_exists == false) {
             $hex_id = WorldMapDAO::insertHex($this->db, $hex);
             if ($this->db->hasError()) {
                 echo 'Error inserting Hex: ';
                 print_r($this->db->getError());
                 echo "\r\n";
                 $log_msg = var_export($hex, true) . "\r\n\r\n" . print_r($this->db->getError(), true);
                 DataLoadLogDAO::logEvent2($this->db, $func_log_id, $log_seq++, 'ERROR', "Error inserting hex into World {$hex->world_id}, X: {$hex->hex_x}, Y: {$hex->hex_y}", $log_msg);
             }
         } else {
             $hex_id = WorldMapDAO::updateHex($this->db, $hex);
             if ($this->db->hasError()) {
                 echo 'Error updating Hex: ';
                 print_r($this->db->getError());
                 echo "\r\n";
                 $log_msg = var_export($hex, true) . "\r\n\r\n" . print_r($this->db->getError(), true);
                 DataLoadLogDAO::logEvent2($this->db, $func_log_id, $log_seq++, 'ERROR', "Error updating hex in World {$hex->world_id}, X: {$hex->hex_x}, Y: {$hex->hex_y}", $log_msg, 1);
             }
         }
     }
     DataLoadLogDAO::completeFunction($this->db, $func_log_id, "Created {$hex_count} Hexes");
     echo "Created {$hex_count} Hexes\r\n";
     return true;
 }
Exemplo n.º 10
0
 /**
  * Places given hex on the board.
  * @param array|Hex $data
  * @param array $coords
  */
 public function placeHex($data, $coords)
 {
     if (is_array($data)) {
         $hex = Hex::create($data);
     } else {
         $hex = $data;
     }
     $hex->setXY($coords);
     $this->getHexes()->add($hex);
 }
Exemplo n.º 11
0
<?php

require_once "../ColorJizz.php";
$h = new Hex(0x0);
$g = new Hex(0x2491b5);
$range = $h->range($g, 10, TRUE);
foreach ($range as $col) {
    echo $col->toString() . "<br />";
}
Exemplo n.º 12
0
 /**
  * Convert a binary string into a hexadecimal string without cache-timing
  * leaks
  *
  * @param string $bin_string (raw binary)
  * @return string
  */
 public static function hexDecodeUpper(string $bin_string) : string
 {
     return Hex::decode($bin_string);
 }
Exemplo n.º 13
0
 private function hexes()
 {
     $class = get_class(new Hex());
     $this->log($this->verb . ' Hexes');
     $url = $this->baseUrl . "map_hex?c:limit=10000";
     $data = $this->getCensusData($url);
     if (!$data) {
         return false;
     }
     // Collection of Eloquent objects from API
     $apiCollection = new Collection();
     foreach ($data->map_hex_list as $hex) {
         $values = [];
         $values['region_id'] = isset($hex->map_region_id) ? $hex->map_region_id : null;
         $values['x'] = isset($hex->x) ? $hex->x : null;
         $values['y'] = isset($hex->y) ? $hex->y : null;
         $apiCollection->add(new Hex($values));
     }
     $regions = Hex::all();
     $this->addModels($class, $regions, $apiCollection);
     $this->deleteModels($class, $regions, $apiCollection);
 }
Exemplo n.º 14
0
 /**
  * RFC 4648 Base16 decoding
  *
  * "666F6F" -> "foo"
  *
  * @param string $str
  * @return string
  */
 public function base16Decode(string $str) : string
 {
     return Hex::decode($str, true);
 }
Exemplo n.º 15
-1
 public function testEncoding()
 {
     $random_bytes = \random_bytes(31);
     // Backwards compatibility:
     $encoder = Halite::chooseEncoder(false);
     $this->assertSame(Hex::encode($random_bytes), $encoder($random_bytes));
     $encoder = Halite::chooseEncoder(true);
     $this->assertSame(null, $encoder);
     // New encoding in version 3:
     $encoder = Halite::chooseEncoder(Halite::ENCODE_HEX);
     $this->assertSame(Hex::encode($random_bytes), $encoder($random_bytes));
     $encoder = Halite::chooseEncoder(Halite::ENCODE_BASE32);
     $this->assertSame(Base32::encode($random_bytes), $encoder($random_bytes));
     $encoder = Halite::chooseEncoder(Halite::ENCODE_BASE32HEX);
     $this->assertSame(Base32Hex::encode($random_bytes), $encoder($random_bytes));
     $encoder = Halite::chooseEncoder(Halite::ENCODE_BASE64);
     $this->assertSame(Base64::encode($random_bytes), $encoder($random_bytes));
     $encoder = Halite::chooseEncoder(Halite::ENCODE_BASE64URLSAFE);
     $this->assertSame(Base64UrlSafe::encode($random_bytes), $encoder($random_bytes));
 }