/** * We are expecting one secret key and one public key * * @param type $privatekey * @param type $publickey * @return [Key, Key] secret, public * @throws CryptoAlert\InvalidKey */ protected static function judgeKeys(Contract\CryptoKeyInterface $privatekey, Contract\CryptoKeyInterface $publickey) { if ($privatekey->isPublicKey()) { if ($publickey->isPublicKey()) { throw new CryptoAlert\InvalidKey('Both keys cannot be public keys'); } return [$publickey, $privatekey]; } elseif ($publickey->isPublicKey()) { return [$privatekey, $publickey]; } else { throw new CryptoAlert\InvalidKey('Both keys cannot be secret keys'); } }
/** * Seal a (file handle) * * @param $input * @param $output * @param \ParagonIE\Halite\Contract\CryptoKeyInterface $publickey */ public static function sealResource($input, $output, \ParagonIE\Halite\Contract\CryptoKeyInterface $publickey) { // 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 (!$publickey->isPublicKey()) { throw new CryptoAlert\InvalidKey('Especter a public key'); } if (!$publickey->isAsymmetricKey()) { throw new CryptoAlert\InvalidKey('Expected a key intended for asymmetric-key cryptography'); } // Generate a new keypair for this encryption list($eph_secret, $eph_public) = Key::generate(Key::CRYPTO_BOX); // Calculate the shared secret key $key = Asymmetric::getSharedSecret($eph_secret, $publickey, true); // Destroy the secre tkey after we have the shared secret unset($eph_secret); $config = self::getConfig(Halite::HALITE_VERSION, 'seal'); // Generate a nonce as per crypto_box_seal $nonce = \Sodium\crypto_generichash($eph_public->get() . $publickey->get(), null, \Sodium\CRYPTO_STREAM_NONCEBYTES); // Generate a random HKDF salt $hkdfsalt = \Sodium\randombytes_buf($config['HKDF_SALT_LEN']); // Split the keys 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); // We no longer need to retain this after we've set up the hash context unset($authKey); $written = \fwrite($output, Halite::HALITE_VERSION, Halite::VERSION_TAG_LEN); if ($written === false) { throw new FileAlert\AccessDenied('Could not write to the file'); } $written &= \fwrite($output, $eph_public->get(), \Sodium\CRYPTO_BOX_PUBLICKEYBYTES); if ($written === false) { throw new FileAlert\AccessDenied('Could not write to the file'); } $written &= \fwrite($output, $hkdfsalt, Halite::HKDF_SALT_LEN); if ($written === false) { throw new FileAlert\AccessDenied('Could not write to the file'); } \hash_update($mac, Halite::HALITE_VERSION); \hash_update($mac, $eph_public->get()); \hash_update($mac, $hkdfsalt); unset($eph_public); return self::streamEncrypt($input, $output, new Key($encKey), $nonce, $mac, $config); }