session-ios/SessionMessagingKit/LibSessionUtil/libsession-util.xcframework/session/config/encrypt.hpp

70 lines
3.4 KiB
C++

#pragma once
#include <stdexcept>
#include "../types.hpp"
namespace session::config {
/// Encrypts a config message using XChaCha20-Poly1305, using a blake2b keyed hash of the message
/// for the nonce (rather than pure random) so that different clients will encrypt the same data to
/// the same encrypted value (thus allowing for server-side deduplication of identical messages).
///
/// `key_base` must be 32 bytes. This value is a fixed key that all clients that might receive this
/// message can calculate independently (for instance a value derived from a secret key, or a shared
/// random key). This key will be hashed with the message size and domain suffix (see below) to
/// determine the actual encryption key.
///
/// `domain` is a short string (1-24 chars) used for the keyed hash. Typically this is the type of
/// config, e.g. "closed-group" or "contacts". The full key will be
/// "session-config-encrypted-message-[domain]". This value is also used for the encrypted key (see
/// above).
///
/// The returned result will consist of encrypted data with authentication tag and appended nonce,
/// suitable for being passed to decrypt() to authenticate and decrypt.
///
/// Throw std::invalid_argument on bad input (i.e. from invalid key_base or domain).
ustring encrypt(ustring_view message, ustring_view key_base, std::string_view domain);
/// Same as above, but modifies `message` in place. `message` gets encrypted plus has the extra
/// data and nonce appended.
void encrypt_inplace(ustring& message, ustring_view key_base, std::string_view domain);
/// Constant amount of extra bytes required to be appended when encrypting.
constexpr size_t ENCRYPT_DATA_OVERHEAD = 40; // ABYTES + NPUBBYTES
/// Thrown if decrypt() fails.
struct decrypt_error : std::runtime_error {
using std::runtime_error::runtime_error;
};
/// Takes a value produced by `encrypt()` and decrypts it. `key_base` and `domain` must be the same
/// given to encrypt or else decryption fails. Upon decryption failure a `decrypt_error` exception
/// is thrown.
ustring decrypt(ustring_view ciphertext, ustring_view key_base, std::string_view domain);
/// Same as above, but does in in-place. The string gets shortend to the plaintext after this call.
void decrypt_inplace(ustring& ciphertext, ustring_view key_base, std::string_view domain);
/// Returns the target size of the message with padding, assuming an additional `overhead` bytes of
/// overhead (e.g. from encrypt() overhead) will be appended. Will always return a value >= s +
/// overhead.
///
/// Padding increments we use: 256 byte increments up to 5120; 1024 byte increments up to 20480,
/// 2048 increments up to 40960, then 5120 from there up.
inline constexpr size_t padded_size(size_t s, size_t overhead = ENCRYPT_DATA_OVERHEAD) {
size_t s2 = s + overhead;
size_t chunk = s2 < 5120 ? 256 : s2 < 20480 ? 1024 : s2 < 40960 ? 2048 : 5120;
return (s2 + chunk - 1) / chunk * chunk - overhead;
}
/// Inserts null byte padding to the beginning of a message to make the final message size granular.
/// See the above function for the sizes.
///
/// \param data - the data; this is modified in place.
/// \param overhead - encryption overhead to account for to reach the desired padded size. The
/// default, if omitted, is the space used by the `encrypt()` function defined above.
void pad_message(ustring& data, size_t overhead = ENCRYPT_DATA_OVERHEAD);
} // namespace session::config