Beispiel #1
0
 /**
  * Unseal a (file handle)
  * 
  * @param $input
  * @param $output
  * @param \ParagonIE\Halite\Contract\CryptoKeyInterface $secretkey
  */
 public static function unsealResource($input, $output, \ParagonIE\Halite\Contract\CryptoKeyInterface $secretkey)
 {
     // Input validation
     if (!\is_resource($input)) {
         throw new \ParagonIE\Halite\Alerts\InvalidType('Expected input handle to be a resource');
     }
     if (!\is_resource($output)) {
         throw new \ParagonIE\Halite\Alerts\InvalidType('Expected output handle to be a resource');
     }
     if (!$secretkey->isSecretKey()) {
         throw new CryptoAlert\InvalidKey('Expected a secret key');
     }
     if (!$secretkey->isAsymmetricKey()) {
         throw new CryptoAlert\InvalidKey('Expected a key intended for asymmetric-key cryptography');
     }
     $secret_key = $secretkey->get();
     $public_key = \Sodium\crypto_box_publickey_from_secretkey($secret_key);
     // Parse the header, ensuring we get 4 bytes
     $header = self::readBytes($input, Halite::VERSION_TAG_LEN);
     // Load the config
     $config = self::getConfig($header, 'seal');
     // Let's grab the public key and salt
     $eph_public = self::readBytes($input, $config['PUBLICKEY_BYTES']);
     $hkdfsalt = self::readBytes($input, $config['HKDF_SALT_LEN']);
     $nonce = \Sodium\crypto_generichash($eph_public . $public_key, null, \Sodium\CRYPTO_STREAM_NONCEBYTES);
     $ephemeral = new Key($eph_public, true, false, true);
     $key = Asymmetric::getSharedSecret($secretkey, $ephemeral, true);
     list($encKey, $authKey) = self::splitKeys($key, $hkdfsalt);
     // 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 Key($encKey), $nonce, $mac, $config, $old_macs);
     unset($encKey);
     unset($authKey);
     unset($nonce);
     unset($mac);
     unset($config);
     unset($old_macs);
     return $ret;
 }
Beispiel #2
0
 /**
  * Decrypt a sealed message with our private key
  * 
  * @param string $source Encrypted message (string or resource for a file)
  * @param Contract\CryptoKeyInterface $privateKey
  * @param boolean $raw Don't hex decode the input?
  * 
  * @return string
  */
 public static function unseal($source, Contract\CryptoKeyInterface $privateKey, $raw = false)
 {
     if (!$raw) {
         $source = \Sodium\hex2bin($source);
     }
     if ($privateKey->isSecretKey()) {
         if (function_exists('\\Sodium\\crypto_box_seal_open')) {
             // Get a box keypair (needed by crypto_box_seal_open)
             $secret_key = $privateKey->get();
             $public_key = \Sodium\crypto_box_publickey_from_secretkey($secret_key);
             $kp = \Sodium\crypto_box_keypair_from_secretkey_and_publickey($secret_key, $public_key);
             // Now let's open that sealed box
             $message = \Sodium\crypto_box_seal_open($source, $kp);
             // Always memzero after retrieving a value
             \Sodium\memzero($secret_key);
             \Sodium\memzero($public_key);
             \Sodium\memzero($kp);
         } else {
             /**
              * Polyfill for libsodium < 1.0.3
              */
             // Let's generate the box keypair
             $my_secret = $privateKey->get();
             $my_public = \Sodium\crypto_box_publickey_from_secretkey($my_secret);
             $eph_public = mb_substr($source, 0, \Sodium\CRYPTO_BOX_PUBLICKEYBYTES, '8bit');
             $box_kp = \Sodium\crypto_box_keypair_from_secretkey_and_publickey($my_secret, $eph_public);
             // Calculate the nonce as libsodium does
             $nonce = \Sodium\crypto_generichash($eph_public . $my_public, null, \Sodium\CRYPTO_BOX_NONCEBYTES);
             // $boxed is the ciphertext from crypto_box_seal
             $boxed = mb_substr($source, \Sodium\CRYPTO_BOX_PUBLICKEYBYTES, null, '8bit');
             $message = \Sodium\crypto_box_open($boxed, $nonce, $box_kp);
             \Sodium\memzero($my_secret);
             \Sodium\memzero($my_public);
             \Sodium\memzero($box_kp);
             \Sodium\memzero($nonce);
             \Sodium\memzero($eph_public);
         }
         if ($message === false) {
             throw new CryptoAlert\InvalidKey('Incorrect secret key');
         }
         // We have our encrypted message here
         return $message;
     }
     throw new CryptoAlert\InvalidKey('Expected a secret key');
 }
Beispiel #3
0
 /**
  * Decrypt a sealed message with our private key
  * 
  * @param string $source Encrypted message (string or resource for a file)
  * @param Contract\CryptoKeyInterface $privateKey
  * @param boolean $raw Don't hex decode the input?
  * 
  * @return string
  */
 public static function unseal($source, Contract\CryptoKeyInterface $privateKey, $raw = false)
 {
     if (!$raw) {
         $source = \Sodium\hex2bin($source);
     }
     if ($privateKey->isSecretKey()) {
         if (function_exists('\\Sodium\\crypto_box_seal_open')) {
             // Get a box keypair (needed by crypto_box_seal_open)
             $secret_key = $privateKey->get();
             $public_key = \Sodium\crypto_box_publickey_from_secretkey($secret_key);
             $kp = \Sodium\crypto_box_keypair_from_secretkey_and_publickey($secret_key, $public_key);
             // Now let's open that sealed box
             $message = \Sodium\crypto_box_seal_open($source, $kp);
             // Always memzero after retrieving a value
             \Sodium\memzero($secret_key);
             \Sodium\memzero($public_key);
             \Sodium\memzero($kp);
         } else {
             throw new CryptoException\CannotPerformOperation('crypto_box_seal_open is not available');
         }
         if ($message === false) {
             throw new CryptoException\InvalidKey('Incorrect secret key');
         }
         // We have our encrypted message here
         return $message;
     }
     throw new CryptoException\InvalidKey('Expected a secret key');
 }