예제 #1
0
 /**
  * Unseal a (file handle)
  * 
  * @param ReadOnlyFile $input
  * @param MutableFile $output
  * @param EncryptionSecretKey $secretkey
  */
 public static function unsealStream(ReadOnlyFile $input, MutableFile $output, EncryptionSecretKey $secretkey)
 {
     if (!$secretkey instanceof EncryptionSecretKey) {
         throw new \ParagonIE\Halite\Alerts\InvalidKey('Argument 3: Expected an instance of EncryptionSecretKey');
     }
     $secret_key = $secretkey->get();
     $public_key = \Sodium\crypto_box_publickey_from_secretkey($secret_key);
     // Parse the header, ensuring we get 4 bytes
     $header = $input->readBytes(Halite::VERSION_TAG_LEN);
     // Load the config
     $config = self::getConfig($header, 'seal');
     // 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, null, \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);
     $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;
 }