/** * Stream decryption - Do not call directly * * @param ReadOnlyFile $input * @param MutableFile $output * @param Key $encKey * @param string $nonce * @param resource $mac (hash context) * @param Config $config * @throws FileAlert\AccessDenied */ private static final function streamDecrypt(ReadOnlyFile $input, MutableFile $output, KeyInterface $encKey, $nonce, $mac, Config $config, array &$chunk_macs) { if (!$encKey instanceof EncryptionKey) { throw new \ParagonIE\Halite\Alerts\InvalidKey('Argument 3: Expected an instance of EncryptionKey'); } $start = $input->getPos(); $cipher_end = $input->getSize() - $config->MAC_SIZE; // Begin the streaming decryption $input->reset($start); while ($input->remainingBytes() > $config->MAC_SIZE) { if ($input->getPos() + $config->BUFFER > $cipher_end) { $read = $input->readBytes($cipher_end - $input->getPos()); } else { $read = $input->readBytes($config->BUFFER); } \hash_update($mac, $read); $calcMAC = \hash_copy($mac); if ($calcMAC === false) { throw new CryptoException\CannotPerformOperation('An unknown error has occurred'); } $calc = \hash_final($calcMAC, true); if (empty($chunk_macs)) { throw new CryptoException\InvalidMessage('Invalid message authentication code'); } else { $chkmac = \array_shift($chunk_macs); if (!\hash_equals($chkmac, $calc)) { throw new CryptoException\InvalidMessage('Invalid message authentication code'); } } $decrypted = \Sodium\crypto_stream_xor($read, $nonce, $encKey->get()); $output->writeBytes($decrypted); \Sodium\increment($nonce); } \Sodium\memzero($nonce); return true; }
/** * Verify a MAC, given a MAC key * * @param string $message * @param AuthenticationKey $secretKey * @param string $mac * @param boolean $raw * @return boolean */ public static function verify($message, Contract\KeyInterface $secretKey, $mac, $raw = false) { if (!$secretKey instanceof AuthenticationKey) { throw new CryptoException\InvalidKey('Expected an instance of AuthenticationKey'); } if (!$raw) { $mac = \Sodium\hex2bin($mac); } return self::verifyMAC($mac, $message, $secretKey->get()); }
/** * Verify a signed message with the correct public key * * @param string $message Message to verify * @param SignaturePublicKey $publicKey * @param string $signature * @param boolean $raw Don't hex decode the input? * * @return boolean * * @throws CryptoException\InvalidKey * @throws CryptoException\CannotPerformOperation */ public static function verify($message, Contract\KeyInterface $publicKey, $signature, $raw = false) { if (!$publicKey instanceof SignaturePublicKey) { throw new CryptoException\InvalidKey('Argument 2: Expected an instance of SignaturePublicKey'); } if (!$raw) { $signature = \Sodium\hex2bin($signature); } return \Sodium\crypto_sign_verify_detached($signature, $message, $publicKey->get()); }