/** * Calculate a MAC * * @param string $message * @param string $authKey * @return string */ protected static function calculateMAC($message, $authKey) { return \Sodium\crypto_auth($message, $authKey); }
/** * Message encryption (secret-key) * * @param string|resource $plaintext * @param EncryptionKey $key * * @return string */ public function encryptSymmetric($plaintext, EncryptionKey $key, array $options = []) : string { // Build our header: // [VV][VV]: $message = \chr(Common::VERSION_MAJOR); $message .= \chr(Common::VERSION_MAJOR); // [DD]: $message .= \chr(0x7f & self::DRIVER_ID); // [CC]: $message .= \chr(Common::VERSION_MAJOR ^ Common::VERSION_MINOR ^ 0x7f & self::DRIVER_ID); // Salt: $salt = \random_bytes(\Sodium\CRYPTO_GENERICHASH_KEYBYTES); // Split keys: list($encKey, $authKey) = $this->splitSymmetricKey($key, $salt); $message .= $salt; // HKDF salt // Nonce: $nonce = \random_bytes(\Sodium\CRYPTO_STREAM_NONCEBYTES); $message .= $nonce; // Nonce for the stream cipher // Encrypt: $message .= \Sodium\crypto_stream_xor($plaintext, $nonce, $encKey->getRawBytes()); unset($encKey); // Authenticate: $message .= \Sodium\crypto_auth($message, $authKey->getRawBytes()); unset($authKey); // Return: return $message; }
/** * @param mixed $unencrypted * * @throws CryptoException * * @return string */ public function encrypt($unencrypted) { if (!is_scalar($unencrypted)) { throw new CryptoException(sprintf(self::ERR_CANNOT_ENCRYPT, gettype($unencrypted))); } // Generate 24 byte nonce $nonce = \random_bytes(self::NONCE_SIZE_BYTES); // Encrypt payload try { $encrypted = \Sodium\crypto_secretbox($unencrypted, $nonce, $this->cryptoSecret->getValue()); } catch (Exception $ex) { throw new CryptoException(sprintf(self::ERR_ENCRYPT, $ex->getMessage()), $ex->getCode(), $ex); } // Calculate MAC try { $mac = \Sodium\crypto_auth($nonce . $encrypted, $this->authSecret->getValue()); } catch (Exception $ex) { throw new CryptoException(sprintf(self::ERR_ENCODE, $ex->getMessage()), $ex->getCode(), $ex); } // Return appended binary string return $nonce . $mac . $encrypted; }
/** * Returns a signed message to the client for authentication. * * @param string $message The message to be signed. * @param string $key The signing key used with the message. * @param string $hashKey The key to hash the key with. * @return string A JSON string including the signing information and message. * @throws Exceptions\InvalidTypeException * @throws Exceptions\OutOfRangeException */ public static function signMessage($message, $key, $hashKey = '') { # Test the message and key for string validity. Helpers::isString($message, 'Encryption', 'signMessage'); Helpers::isString($key, 'Encryption', 'signMessage'); Helpers::isString($hashKey, 'Encryption', 'signMessage'); # Create a special hashed key for encryption. $key = Hash::hash($key, $hashKey, Constants::AUTH_KEYBYTES); # Generate a MAC for the message. $mac = \Sodium\crypto_auth($message, $key); return base64_encode(json_encode(['mac' => Helpers::bin2hex($mac), 'msg' => $message])); }