Esempio n. 1
0
 /**
  * Unseal a (file handle)
  *
  * @param ReadOnlyFile $input
  * @param MutableFile $output
  * @param EncryptionSecretKey $secretkey
  *
  * @return bool
  * @throws CryptoException\CannotPerformOperation
  * @throws CryptoException\InvalidMessage
  */
 protected static function unsealData(ReadOnlyFile $input, MutableFile $output, EncryptionSecretKey $secretkey) : bool
 {
     $secret_key = $secretkey->getRawKeyMaterial();
     $public_key = \Sodium\crypto_box_publickey_from_secretkey($secret_key);
     if ($input->getSize() < Halite::VERSION_TAG_LEN) {
         throw new CryptoException\InvalidMessage("File is too small to have been encrypted by Halite.");
     }
     // Parse the header, ensuring we get 4 bytes
     $header = $input->readBytes(Halite::VERSION_TAG_LEN);
     // Load the config
     $config = self::getConfig($header, 'seal');
     if ($input->getSize() < $config->SHORTEST_CIPHERTEXT_LENGTH) {
         throw new CryptoException\InvalidMessage("File is too small to have been encrypted by Halite.");
     }
     // Let's grab the public key and salt
     $eph_public = $input->readBytes($config->PUBLICKEY_BYTES);
     $hkdfsalt = $input->readBytes($config->HKDF_SALT_LEN);
     $nonce = \Sodium\crypto_generichash($eph_public . $public_key, '', \Sodium\CRYPTO_STREAM_NONCEBYTES);
     $ephemeral = new EncryptionPublicKey($eph_public);
     $key = AsymmetricCrypto::getSharedSecret($secretkey, $ephemeral, true);
     list($encKey, $authKey) = self::splitKeys($key, $hkdfsalt, $config);
     // We no longer need the original key after we split it
     unset($key);
     if ($config->USE_BLAKE2B) {
         $mac = \Sodium\crypto_generichash_init($authKey);
         \Sodium\crypto_generichash_update($mac, $header);
         \Sodium\crypto_generichash_update($mac, $eph_public);
         \Sodium\crypto_generichash_update($mac, $hkdfsalt);
         $old_macs = self::streamVerify($input, '' . $mac, $config);
     } else {
         $mac = \hash_init('sha256', HASH_HMAC, $authKey);
         \hash_update($mac, $header);
         \hash_update($mac, $eph_public);
         \hash_update($mac, $hkdfsalt);
         // This will throw an exception if it fails.
         $old_macs = self::streamVerify($input, \hash_copy($mac), $config);
     }
     $ret = self::streamDecrypt($input, $output, new EncryptionKey($encKey), $nonce, $mac, $config, $old_macs);
     unset($encKey);
     unset($authKey);
     unset($nonce);
     unset($mac);
     unset($config);
     unset($old_macs);
     return $ret;
 }
Esempio n. 2
0
 /**
  * Calculate a BLAHE2b checksum of a file
  * 
  * @param string $fileHandle The file you'd like to checksum
  * @param string $key An optional BLAKE2b key
  * @param bool $raw Set to true if you don't want hex
  * 
  * @return string
  */
 public static function checksumResource($fileHandle, \ParagonIE\Halite\Contract\CryptoKeyInterface $key = null, $raw = false)
 {
     // Input validation
     if (!\is_resource($fileHandle)) {
         throw new \ParagonIE\Halite\Alerts\InvalidType('Expected input handle to be a resource');
     }
     $config = self::getConfig(Halite::HALITE_VERSION, 'checksum');
     if ($key) {
         $state = \Sodium\crypto_generichash_init($key->get(), $config['HASH_LEN']);
     } else {
         $state = \Sodium\crypto_generichash_init(null, $config['HASH_LEN']);
     }
     while (!\feof($fileHandle)) {
         $read = \fread($fileHandle, $config['BUFFER']);
         if ($read === false) {
             throw new CryptoException\FileAccessDenied('Could not read from the file');
         }
         \Sodium\crypto_generichash_update($state, $read);
     }
     if ($raw) {
         return \Sodium\crypto_generichash_final($state, $config['HASH_LEN']);
     }
     return \Sodium\bin2hex(\Sodium\crypto_generichash_final($state, $config['HASH_LEN']));
 }
Esempio n. 3
0
 /**
  * 
  * @param \ParagonIE\Halite\Contract\StreamInterface $fileStream
  * @param AuthenticationKey $key
  * @param type $raw
  * @return type
  */
 public static function checksumStream(StreamInterface $fileStream, KeyInterface $key = null, $raw = false)
 {
     $config = self::getConfig(Halite::HALITE_VERSION_FILE, 'checksum');
     if ($key) {
         if (!$key instanceof AuthenticationKey) {
             throw new \ParagonIE\Halite\Alerts\InvalidKey('Argument 2: Expected an instance of AuthenticationKey');
         }
         $state = \Sodium\crypto_generichash_init($key->get(), $config->HASH_LEN);
     } else {
         $state = \Sodium\crypto_generichash_init(null, $config->HASH_LEN);
     }
     $size = $fileStream->getSize();
     while ($fileStream->remainingBytes() > 0) {
         $read = $fileStream->readBytes($fileStream->getPos() + $config->BUFFER > $size ? $size - $fileStream->getPos() : $config->BUFFER);
         \Sodium\crypto_generichash_update($state, $read);
     }
     if ($raw) {
         return \Sodium\crypto_generichash_final($state, $config->HASH_LEN);
     }
     return \Sodium\bin2hex(\Sodium\crypto_generichash_final($state, $config->HASH_LEN));
 }
Esempio n. 4
0
 /**
  * Calculate a BLAKE2b hash of a file
  * 
  * @return string
  */
 public function getHash()
 {
     $init = $this->pos;
     \fseek($this->fp, 0, SEEK_SET);
     // Create a hash context:
     $h = \Sodium\crypto_generichash_init(null, \Sodium\CRYPTO_GENERICHASH_BYTES_MAX);
     for ($i = 0; $i < $this->stat['size']; $i += self::CHUNK) {
         if ($i + self::CHUNK > $this->stat['size']) {
             $c = \fread($this->fp, $this->stat['size'] - $i);
         } else {
             $c = \fread($this->fp, self::CHUNK);
         }
         \Sodium\crypto_generichash_update($h, $c);
     }
     // Reset the file pointer's internal cursor to where it was:
     \fseek($this->fp, $init, SEEK_SET);
     return \Sodium\crypto_generichash_final($h);
 }
Esempio n. 5
0
 /**
  * Unseal the contents of a file.
  *
  * @param ReadOnlyFile $input
  * @param MutableFile $output
  * @param EncryptionSecretKey $secretKey
  * @return bool
  * @throws CannotPerformOperation
  * @throws InvalidMessage
  */
 protected static function unsealData(ReadOnlyFile $input, MutableFile $output, EncryptionSecretKey $secretKey) : bool
 {
     $publicKey = $secretKey->derivePublicKey();
     // Is the file at least as long as a header?
     if ($input->getSize() < Halite::VERSION_TAG_LEN) {
         throw new InvalidMessage("Input file is too small to have been encrypted by Halite.");
     }
     // Parse the header, ensuring we get 4 bytes
     $header = $input->readBytes(Halite::VERSION_TAG_LEN);
     // Load the config
     $config = self::getConfig($header, 'seal');
     if ($input->getSize() < $config->SHORTEST_CIPHERTEXT_LENGTH) {
         throw new InvalidMessage("Input file is too small to have been encrypted by Halite.");
     }
     // Let's grab the public key and salt
     $ephPublic = $input->readBytes($config->PUBLICKEY_BYTES);
     $hkdfSalt = $input->readBytes($config->HKDF_SALT_LEN);
     // Generate the same nonce, as per sealData()
     $nonce = \Sodium\crypto_generichash($ephPublic . $publicKey->getRawKeyMaterial(), '', \Sodium\CRYPTO_STREAM_NONCEBYTES);
     // Create a key object out of the public key:
     $ephemeral = new EncryptionPublicKey(new HiddenString($ephPublic));
     $key = AsymmetricCrypto::getSharedSecret($secretKey, $ephemeral, true);
     unset($ephemeral);
     list($encKey, $authKey) = self::splitKeys($key, $hkdfSalt, $config);
     // We no longer need the original key after we split it
     unset($key);
     $mac = \Sodium\crypto_generichash_init($authKey);
     \Sodium\crypto_generichash_update($mac, $header);
     \Sodium\crypto_generichash_update($mac, $ephPublic);
     \Sodium\crypto_generichash_update($mac, $hkdfSalt);
     $oldMACs = self::streamVerify($input, Util::safeStrcpy($mac), $config);
     // We no longer need this:
     \Sodium\memzero($hkdfSalt);
     $ret = self::streamDecrypt($input, $output, new EncryptionKey(new HiddenString($encKey)), $nonce, $mac, $config, $oldMACs);
     unset($encKey);
     unset($authKey);
     unset($nonce);
     unset($mac);
     unset($config);
     unset($oldMACs);
     return $ret;
 }