Exemple #1
0
 /**
  * Seal a message, using only the recipient's public key.
  * 
  * @param string $message
  * @param EncryptionPublicKey $publicKey
  * @return string
  */
 public function sealAsymmetric($plaintext, EncryptionPublicKey $publicKey, array $options = []) : string
 {
     /**
      * 1. Generate a random DH private key.
      */
     list($eph_secret, $eph_public) = KeyFactory::generateEncryptionKeyPair(Common::DRIVER_OPENSSL);
     /**
      * 2. Calculate the shared secret.
      */
     $sharedSecret = $this->getSharedSecret($eph_secret, $publicKey);
     /**
      * 3. Encrypt with symmetric-key crypto.
      */
     // Build our header:
     // [VV][VV]:
     $message = \chr(Common::VERSION_MAJOR);
     $message .= \chr(Common::VERSION_MINOR);
     // [DD]: Make sure leftmost bit is 1 because we're sealing
     $message .= \chr(0x80 | self::DRIVER_ID & 0x7f);
     // [CC]:
     $message .= \chr(Common::VERSION_MAJOR ^ Common::VERSION_MINOR ^ (0x80 | self::DRIVER_ID & 0x7f));
     $message .= $eph_public->getRawBytes();
     // Salt:
     $salt = \random_bytes(Common::safeStrlen(\hash($this->config['hash'], '', true)));
     // Split keys:
     list($encKey, $authKey) = $this->splitSymmetricKey($sharedSecret, $salt);
     $message .= $salt;
     // HKDF salt
     // Nonce:
     $nonce = \random_bytes(\openssl_cipher_iv_length($this->config['cipher']));
     $message .= $nonce;
     // Nonce for the stream cipher
     // Encrypt:
     $message .= \openssl_encrypt($plaintext, $this->config['cipher'] . '-ctr', $encKey->getRawBytes(), OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $nonce);
     unset($encKey);
     /**
      * 4. Authenticate:
      */
     $message .= \hash_hmac($this->config['hash'], $message, $authKey->getRawBytes(), true);
     unset($authKey);
     // Return:
     return $message;
 }
Exemple #2
0
 /**
  * Seal the contents of a file.
  *
  * @param ReadOnlyFile $input
  * @param MutableFile $output
  * @param EncryptionPublicKey $publicKey
  * @return int
  */
 protected static function sealData(ReadOnlyFile $input, MutableFile $output, EncryptionPublicKey $publicKey) : int
 {
     // Generate a new keypair for this encryption
     $ephemeralKeyPair = KeyFactory::generateEncryptionKeyPair();
     $ephSecret = $ephemeralKeyPair->getSecretKey();
     $ephPublic = $ephemeralKeyPair->getPublicKey();
     unset($ephemeralKeyPair);
     // Calculate the shared secret key
     $sharedSecretKey = AsymmetricCrypto::getSharedSecret($ephSecret, $publicKey, true);
     // Destroy the secret key after we have the shared secret
     unset($ephSecret);
     // Load the configuration
     $config = self::getConfig(Halite::HALITE_VERSION_FILE, 'seal');
     // Generate a nonce as per crypto_box_seal
     $nonce = \Sodium\crypto_generichash($ephPublic->getRawKeyMaterial() . $publicKey->getRawKeyMaterial(), '', \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($sharedSecretKey, $hkdfSalt, $config);
     // We no longer need the original key after we split it
     unset($key);
     // Write the header:
     $output->writeBytes(Halite::HALITE_VERSION_FILE, Halite::VERSION_TAG_LEN);
     $output->writeBytes($ephPublic->getRawKeyMaterial(), \Sodium\CRYPTO_BOX_PUBLICKEYBYTES);
     $output->writeBytes($hkdfSalt, $config->HKDF_SALT_LEN);
     // VERSION 2+
     $mac = \Sodium\crypto_generichash_init($authKey);
     // We no longer need $authKey after we set up the hash context
     \Sodium\memzero($authKey);
     \Sodium\crypto_generichash_update($mac, Halite::HALITE_VERSION_FILE);
     \Sodium\crypto_generichash_update($mac, $ephPublic->getRawKeyMaterial());
     \Sodium\crypto_generichash_update($mac, $hkdfSalt);
     unset($ephPublic);
     \Sodium\memzero($hkdfSalt);
     return self::streamEncrypt($input, $output, new EncryptionKey(new HiddenString($encKey)), $nonce, $mac, $config);
 }