public static function encrypt(HiddenString $plaintext, EncryptionKey $secretKey, $encoding = Halite::ENCODE_BASE64URLSAFE) : string
{
$config = SymmetricConfig::getConfig(Halite::HALITE_VERSION, 'encrypt');
// Generate a nonce and HKDF salt:
$nonce = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_NONCEBYTES);
$salt = \Sodium\randombytes_buf($config->HKDF_SALT_LEN);
/* Split our key into two keys: One for encryption, the other for
authentication. By using separate keys, we can reasonably dismiss
likely cross-protocol attacks.
This uses salted HKDF to split the keys, which is why we need the
salt in the first place. */
list($encKey, $authKey) = self::splitKeys($secretKey, $salt, $config);
// Encrypt our message with the encryption key:
$encrypted = \Sodium\crypto_stream_xor($plaintext->getString(), $nonce, $encKey);
\Sodium\memzero($encKey);
// Calculate an authentication tag:
$auth = self::calculateMAC(Halite::HALITE_VERSION . $salt . $nonce . $encrypted, $authKey, $config);
\Sodium\memzero($authKey);
$message = Halite::HALITE_VERSION . $salt . $nonce . $encrypted . $auth;
// Wipe every superfluous piece of data from memory
\Sodium\memzero($nonce);
\Sodium\memzero($salt);
\Sodium\memzero($encrypted);
\Sodium\memzero($auth);
$encoder = Halite::chooseEncoder($encoding);
if ($encoder) {
return $encoder($message);
}
return $message;
}