>= 5; } return $encoded; } /** * 80 bits of randomness as the trailing 16 characters, from * random_bytes(): the id is public, so it is minted from a CSPRNG rather * than from mt_rand(). */ private static function encodeRandomness(): string { $encoded = ''; $accumulator = 0; $pending = 0; // 80 bits in, five at a time out. 80 divides by 5, so the accumulator // is empty at the end and there is no padding character to strip. foreach (str_split(random_bytes(10)) as $byte) { $accumulator = ($accumulator << 8) | ord($byte); $pending += 8; while ($pending >= 5) { $pending -= 5; $encoded .= self::ALPHABET[($accumulator >> $pending) & 31]; } } return $encoded; } }