/** * Install constructor. * * @param \Twig_Environment $twig * @param array $data */ public function __construct(\Twig_Environment $twig, array $data = []) { if (!Halite::isLibsodiumSetupCorrectly()) { echo \file_get_contents(\dirname(__DIR__) . '/error_pages/old-libsodium.html'); exit(255); } $this->twig = $twig; $this->data = $data; $this->data['airship_version'] = \AIRSHIP_VERSION; $this->csrf = new CSRF(); // We do this to prevent someone from coming along and reading your // half-finished configuration settings (e.g. database passwords): if (empty($this->data['step'])) { $this->data['step'] = 1; } if (empty($this->data['token'])) { $this->data['token'] = Base64::encode(\random_bytes(33)); \setcookie('installer', $this->data['token'], \time() + 8640000, '/'); \Airship\redirect('/'); } elseif (empty($_COOKIE['installer'])) { echo 'No installer authorization token found.', "\n"; exit(255); } elseif (!\hash_equals($this->data['token'], $_COOKIE['installer'])) { // This effectively locks unauthorized users out of the system while installing echo 'Invalid installer authorization token.', "\n"; exit(255); } $dirs = ['comments', 'csp_hash', 'csp_static', 'hash', 'markdown', 'static', 'twig']; foreach ($dirs as $d) { if (!\is_dir(\dirname(__DIR__) . '/tmp/cache/' . $d)) { \mkdir(\dirname(__DIR__) . '/tmp/cache/' . $d, 0775, true); } } }
/** * Verify the authenticity of a message, given a shared MAC key * * @param string $message * @param AuthenticationKey $secretKey * @param string $mac * @param mixed $encoding * @param SymmetricConfig $config * @return bool */ public static function verify(string $message, AuthenticationKey $secretKey, string $mac, $encoding = Halite::ENCODE_BASE64URLSAFE, SymmetricConfig $config = null) : bool { $decoder = Halite::chooseEncoder($encoding, true); if ($decoder) { // We were given hex data: $mac = $decoder($mac); } if ($config === null) { // Default to the current version $config = SymmetricConfig::getConfig(Halite::HALITE_VERSION, 'auth'); } return self::verifyMAC($mac, $message, $secretKey->getRawKeyMaterial(), $config); }
/** * Verify a signed message with the correct public key * * @param string $message Message to verify * @param SignaturePublicKey $publicKey * @param string $signature * @param mixed $encoding Which encoding scheme to use? * @return bool * @throws InvalidSignature */ public static function verify(string $message, SignaturePublicKey $publicKey, string $signature, $encoding = Halite::ENCODE_BASE64URLSAFE) : bool { $decoder = Halite::chooseEncoder($encoding, true); if ($decoder) { // We were given hex data: $signature = $decoder($signature); } if (CryptoUtil::safeStrlen($signature) !== \Sodium\CRYPTO_SIGN_BYTES) { throw new InvalidSignature('Signature is not the correct length; is it encoded?'); } return \Sodium\crypto_sign_verify_detached($signature, $message, $publicKey->getRawKeyMaterial()); }
/** * Calculate the BLAKE2b checksum of the contents of a file * * @param StreamInterface $fileStream * @param Key $key * @param mixed $encoding Which encoding scheme to use for the checksum? * @return string * @throws InvalidKey */ protected static function checksumData(StreamInterface $fileStream, Key $key = null, $encoding = Halite::ENCODE_BASE64URLSAFE) : string { $config = self::getConfig(Halite::HALITE_VERSION_FILE, 'checksum'); // 1. Initialize the hash context if ($key instanceof AuthenticationKey) { // AuthenticationKey is for HMAC, but we can use it for keyed hashes too $state = \Sodium\crypto_generichash_init($key->getRawKeyMaterial(), $config->HASH_LEN); } elseif ($config->CHECKSUM_PUBKEY && $key instanceof SignaturePublicKey) { // In version 2, we use the public key as a hash key $state = \Sodium\crypto_generichash_init($key->getRawKeyMaterial(), $config->HASH_LEN); } elseif (isset($key)) { throw new InvalidKey('Argument 2: Expected an instance of AuthenticationKey or SignaturePublicKey'); } else { $state = \Sodium\crypto_generichash_init('', $config->HASH_LEN); } // 2. Calculate the hash $size = $fileStream->getSize(); while ($fileStream->remainingBytes() > 0) { // Don't go past the file size even if $config->BUFFER is not an even multiple of it: if ($fileStream->getPos() + $config->BUFFER > $size) { $amount_to_read = $size - $fileStream->getPos(); } else { $amount_to_read = $config->BUFFER; } $read = $fileStream->readBytes($amount_to_read); \Sodium\crypto_generichash_update($state, $read); } // 3. Do we want a raw checksum? $encoder = Halite::chooseEncoder($encoding); if ($encoder) { return $encoder(\Sodium\crypto_generichash_final($state, $config->HASH_LEN)); } return \Sodium\crypto_generichash_final($state, $config->HASH_LEN); }