diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5a3921eaf2670ed4921e522b5b8c25b541019939..9af8d012e8ec3c42ff3458ac7af1726aec898cda 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,9 +15,9 @@ build:linux: #- DEBIAN_FRONTEND=noninteractive apt-get -y upgrade #- DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade - DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential gcc clang cmake autoconf automake libtool-bin gperf gengetopt pkg-config curl wget gzip tar doxygen graphviz unzip - - DEBIAN_FRONTEND=noninteractive apt-get -y install libgl-dev libegl-dev libpcre2-dev libxkbcommon-dev libmd4c-dev libdbus-1-dev + - DEBIAN_FRONTEND=noninteractive apt-get -y install libgl-dev libegl-dev libpcre2-dev libxkbcommon-dev libmd4c-dev libdbus-1-dev libbrotli-dev libzstd-dev zlib1g-dev - - curl -s -o artifacts.zip https://git.ralph.or.at/causal/causal-cpp-contrib/-/jobs/351/artifacts/download + - curl -s -o artifacts.zip https://git.ralph.or.at/causal/causal-cpp-contrib/-/jobs/1138/artifacts/download - unzip -q artifacts.zip script: @@ -78,7 +78,7 @@ build:android: #- DEBIAN_FRONTEND=noninteractive apt-get -y upgrade #- DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade - DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential cmake autoconf automake libtool-bin gperf gengetopt pkg-config curl wget gzip tar doxygen graphviz default-jdk unzip - - curl -s -o artifacts.zip https://git.ralph.or.at/causal/causal-cpp-contrib/-/jobs/351/artifacts/download + - curl -s -o artifacts.zip https://git.ralph.or.at/causal/causal-cpp-contrib/-/jobs/1138/artifacts/download - unzip -q artifacts.zip - cd tool/android/ndk/25.2.9519653/toolchains/llvm/prebuilt @@ -109,7 +109,7 @@ doc: #- DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade - DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential gcc clang clang-tools cmake autoconf automake doxygen graphviz pkg-config curl wget unzip - - curl -s -o artifacts.zip https://git.ralph.or.at/causal/causal-cpp-contrib/-/jobs/351/artifacts/download + - curl -s -o artifacts.zip https://git.ralph.or.at/causal/causal-cpp-contrib/-/jobs/1138/artifacts/download - unzip -q artifacts.zip script: diff --git a/CHANGELOG.md b/CHANGELOG.md index ca465bb4c22ed6dfb11c764bca8f12769afd4923..a589a45a03a0ee170f988af7eef3fdcbc3e1bec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,3 +92,4 @@ * #000010 Filesystem Junction * #000012 Memory Junction * #000006 added Web Application Server +* #000015 Replace OpenDHT based crypto implementation for core functions with a GnuTLS based diff --git a/CMakeLists.txt b/CMakeLists.txt index f8959f352cbead9ff4b09db65a917bc579d6dd57..f6a0ac8d3696820bbe19b793e69832d4c25e7e9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,8 @@ endif() find_package(Boost 1.74 REQUIRED COMPONENTS log stacktrace_basic) add_definitions(-DWITH_STACKTRACE) +pkg_check_modules(GnuTLS REQUIRED gnutls>=3.7) + add_library(causal-core src/trace.cpp src/core/wirks.cpp src/sync/util.cpp @@ -103,9 +105,10 @@ install(TARGETS causal-core COMPONENT core DESTINATION lib) add_library(causal-data src/data/junction.cpp src/data/memory.cpp + src/data/crypto.cpp src/data/channel.cpp src/data/fs.cpp) -target_link_libraries(causal-data causal-core) +target_link_libraries(causal-data causal-core ${GnuTLS_LIBRARIES}) install(FILES include/causal/data/channel.hpp include/causal/data/junction.hpp include/causal/data/memory.hpp @@ -300,9 +303,8 @@ if(GTEST_FOUND) add_causal_test(NAME test_causal-data_opendht SOURCES test/data/opendht.cpp LIBS causal-data-opendht) endif() - if(Msgpack_FOUND AND OpenDHT_FOUND AND LMDB_FOUND) - # TODO: LMDB crypto Tests are powered by crypto API of OpenDHT => replace using proper GNUTLS implementation - add_causal_test(NAME test_causal-data_lmdb SOURCES test/data/lmdb.cpp LIBS causal-data-junction-lmdb causal-msgpack causal-data-opendht) + if(Msgpack_FOUND AND LMDB_FOUND) + add_causal_test(NAME test_causal-data_lmdb SOURCES test/data/lmdb.cpp LIBS causal-data-junction-lmdb causal-msgpack) endif() if(OpenSSL_FOUND AND LIBMICROHTTPD_FOUND) diff --git a/include/causal/data/crypto.hpp b/include/causal/data/crypto.hpp index 1cfb607f09c878155354d40a350a8ca2480321f7..95d5b56fc47647c64ba7c3b3aff8c89fe23ef022 100644 --- a/include/causal/data/crypto.hpp +++ b/include/causal/data/crypto.hpp @@ -6,6 +6,9 @@ #include <memory> #include <map> +#include <gnutls/crypto.h> +#include <gnutls/gnutls.h> + #include "causal/trace.hpp" #include "causal/core/aspect.hpp" @@ -93,6 +96,37 @@ namespace causal { Certificate certificate; }; + EXCEPTION_ERROR(gnutls_error, "GnuTLS error") + + class gnutls_init final { + private: + // Private constructor to prevent instantiation from outside + gnutls_init(); + + // Singleton instance + static gnutls_init* instance; + + // Flag for thread-safe initialization + static std::once_flag initFlag; + + // Method to initialize the library if not already initialized + static void _init(); + + public: + ~gnutls_init(); + + // Delete copy constructor and assignment operator to prevent copying + gnutls_init(const gnutls_init&) = delete; + void operator=(const gnutls_init&) = delete; + + // Public method to access the singleton instance + static void init(); + }; + + std::string gnutls_derrive_sha_key(const std::string& password, u_short key_length); + + EXCEPTION_ERROR(sha_hash_lenght_invalid, "hash_length should be larger than or equal to 256") + /// @brief abstract base of hasher class hasher { public: @@ -101,7 +135,15 @@ namespace causal { * @param hash_length requested SHA length * @return SHA hash of data */ - virtual std::string hash_sha(const std::string& data, u_short hash_length=DEFAULT_SHA_HASH_LENGTH) const = 0; + virtual std::string hash(const std::string& data, u_short hash_length=DEFAULT_SHA_HASH_LENGTH) const = 0; + }; + + /// @brief GnuTLS backed SHA crypto hasher + class gnutls_sha_hasher final : public hasher { + public: + gnutls_sha_hasher(); + + std::string hash(const std::string& data, u_short hash_length=DEFAULT_SHA_HASH_LENGTH) const override; }; /// @brief abstract base of crypto provider @@ -273,8 +315,10 @@ namespace causal { }; /// @brief abstract base of symmetric coder - class crypto_coder { + class cipher { public: + virtual ~cipher() = default; + /** @brief get hasher using coders backend * @return hasher to use */ @@ -299,6 +343,23 @@ namespace causal { virtual std::string decrypt(const std::string& encrypted_data) const = 0; }; + /// @brief GnuTLS backed AES crypto coder + class gnutls_aes_cipher final : public cipher { + private: + const std::string key, iv; + const gnutls_cipher_algorithm_t algo; + + public: + const u_short key_length; + + gnutls_aes_cipher(const std::string& password, const u_short key_length = 256); + + const hasher& get_hasher() const override; + const std::string get_token() const override; + std::string encrypt(const std::string& data) const override; + std::string decrypt(const std::string& encrypted_data) const override; + }; + /// @brief basic metadata for channels supporting identification struct IdentifiedMessageMeta : MessageMeta { PublicIdentity owner_id; diff --git a/include/causal/data/lmdb.hpp b/include/causal/data/lmdb.hpp index 8b9d763162a64e699477f417462b9f61805e6e1b..a1ecef73a9444dba8980ce037891f54a98610bed 100644 --- a/include/causal/data/lmdb.hpp +++ b/include/causal/data/lmdb.hpp @@ -3,10 +3,12 @@ #pragma once +#include <memory> #include <string> #include <map> #include <lmdb.h> +#include <type_traits> #include "junction.hpp" #include "crypto.hpp" @@ -38,7 +40,7 @@ namespace causal { */ class lmdb_junction final : public junction { private: - const std::shared_ptr<const crypto_coder> coder; + const std::unique_ptr<const cipher> ciph; MDB_dbi db; MDB_env* env = nullptr; @@ -71,14 +73,22 @@ namespace causal { lmdb_junction(const std::string path, const std::string name = std::string(), const mode_t create_mode = 0600, const size_t map_size = 10485760); /** @brief constructs encrypting junction for given LMDB - * @param coder to use for symmetric encryption + * @param ciph cipher to use for symmetric encryption * @param path to LMDB file * @param name of database, empty for using unnamed database * @param create_mode filemode to use when creating new LMDB file * @param map_size to use for mapping data * @remark changing map size requires to reload database file and is not supported yet */ - lmdb_junction(const std::shared_ptr<const crypto_coder> coder, const std::string path, const std::string name = std::string(), const mode_t create_mode = 0600, const size_t map_size = 10485760); + template<typename cipherT> + lmdb_junction(cipherT&& ciph, const std::string path, const std::string name = std::string(), + const mode_t create_mode = 0600, const size_t map_size = 10485760) + requires(std::is_base_of_v<cipher, cipherT>) + : ciph(std::make_unique<cipherT>(std::forward<cipherT>(ciph))) { + this->initialize(path, name, create_mode); + this->open(name, map_size); + this->check_crypto_token(); + } ~lmdb_junction(); void attract(junction_space& s, const std::string id) override; diff --git a/include/causal/data/opendht.hpp b/include/causal/data/opendht.hpp index 42e90ee7a95b2454d456ed76b68ffb555682b152..45ce37b4c3bdfc97ba437c640dba15d5dd696b4b 100644 --- a/include/causal/data/opendht.hpp +++ b/include/causal/data/opendht.hpp @@ -25,10 +25,10 @@ namespace causal { namespace data { MAKE_TRACE_SCOPE(scope_opendht) - /// @brief OpenDHT backed crypto hasher - class opendht_hasher final : public hasher { + /// @brief OpenDHT backed SHA crypto hasher + class opendht_sha_hasher final : public hasher { public: - std::string hash_sha(const std::string& data, u_short hash_length=DEFAULT_SHA_HASH_LENGTH) const override; + std::string hash(const std::string& data, u_short hash_length=DEFAULT_SHA_HASH_LENGTH) const override; }; /// @brief OpenDHT backed crypto provider @@ -79,12 +79,14 @@ namespace causal { }; /// @brief OpenDHT backed AES crypto coder - class opendht_aes_coder final : public crypto_coder { + class opendht_aes_cipher final : public cipher { private: const dht::Blob key; public: - opendht_aes_coder(const std::string& password, const u_short key_length = 32); + const u_short key_length; + + opendht_aes_cipher(const std::string& password, const u_short key_length = 256); const hasher& get_hasher() const override; const std::string get_token() const override; diff --git a/src/data/crypto.cpp b/src/data/crypto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d887a4ee0429b3b849f5c318228bdada37e3ace9 --- /dev/null +++ b/src/data/crypto.cpp @@ -0,0 +1,284 @@ +// Licensed under the terms of the AGPL-3.0-only (GNU AFFERO GENERAL PUBLIC LICENSE version 3) +// Copyright (C) 2018-2024 by Ralph Alexander Bariz + +#include "causal/data/crypto.hpp" +#include "causal/trace.hpp" + +#include <sstream> + +#include <gnutls/crypto.h> +#include <gnutls/gnutls.h> +#include <string> + +namespace causal { + namespace data { + gnutls_init* gnutls_init::instance = nullptr; + std::once_flag gnutls_init::initFlag; + gnutls_init::~gnutls_init() { + gnutls_global_deinit(); + } + + void gnutls_init::init() { + std::call_once(initFlag, &gnutls_init::_init); + } + + gnutls_init::gnutls_init() { + gnutls_global_init(); + TRACE(scope_data) << "GNU TLS library successfully initialized."; + } + + void gnutls_init::_init() { + gnutls_init::instance = new gnutls_init(); + } + + gnutls_sha_hasher::gnutls_sha_hasher() { + gnutls_init::init(); + } + + std::string gnutls_sha_hasher::hash(const std::string& data, u_short hash_length) const { + gnutls_digest_algorithm_t algorithm; + + if (hash_length >= 512) { + algorithm = GNUTLS_DIG_SHA512; + } else if (hash_length >= 384) { + algorithm = GNUTLS_DIG_SHA384; + } else if (hash_length >= 256) { + algorithm = GNUTLS_DIG_SHA256; + } else { + throw sha_hash_lenght_invalid(); + } + size_t digest_size = gnutls_hash_get_len(algorithm); + + unsigned char *digest = new unsigned char[digest_size]; + + // Hash initialization + gnutls_hash_hd_t handle; + if (gnutls_hash_init(&handle, algorithm) < 0) { + delete[] digest; + throw gnutls_error("gnutls_hash_init failed"); + } + + // Input the data to be hashed + if (gnutls_hash(handle, data.data(), data.length()) < 0) { + gnutls_hash_deinit(handle, NULL); + delete[] digest; + throw gnutls_error("gnutls_hash failed"); + } + + // Output hash value + gnutls_hash_output(handle, digest); + + // Free and deinitialize handle + gnutls_hash_deinit(handle , NULL); + + // Convert binary hash value to hexadecimal string + std::ostringstream oss; + for (size_t i = 0; i < digest_size; i++) + oss << static_cast<char>(digest[i]); + + delete[] digest; + return oss.str(); + } + + // Generate a random Initialization Vector of length 16 bytes + std::string generate_iv() { + unsigned char iv[16]; // AES requires a 128-bit IV + + int ret = gnutls_rnd(GNUTLS_RND_NONCE, iv, sizeof(iv)); + if (ret < 0) { + throw gnutls_error("Generating random nonce failed."); + } + + return std::string((const char *)iv, sizeof(iv)); + } + + std::string gnutls_derrive_key_sha(const std::string& password, u_short key_length) { + gnutls_mac_algorithm_t algorithm; + + if (key_length >= 512) { + algorithm = GNUTLS_MAC_SHA512; + } else if (key_length >= 384) { + algorithm = GNUTLS_MAC_SHA384; + } else if (key_length >= 256) { + algorithm = GNUTLS_MAC_SHA256; + } else { + throw sha_hash_lenght_invalid(); + } + + // Choose suitable this->algo based on key length + u_char derived_key[key_length / 8]; + const char *key = (const char *)(&derived_key[0]); + void *digest = derived_key; + + gnutls_hmac_hd_t hmac_handle; + + int ret = gnutls_hmac_init(&hmac_handle, algorithm, (const u_char *)password.data(), password.size()); + if (ret < 0) { + throw gnutls_error("Init HMAC failed."); + } + + ret = gnutls_hmac(hmac_handle, nullptr, 0); // Use empty input as we just need the key derivation + if (ret < 0) { + throw gnutls_error("Computing HMAC failed."); + } + + gnutls_hmac_output(hmac_handle, digest); + + gnutls_hmac_deinit(hmac_handle, digest); + + return std::string(key, key_length / 8); + } + + gnutls_aes_cipher::gnutls_aes_cipher(const std::string& pw, const u_short key_length) + : key(gnutls_derrive_key_sha(pw, key_length)), iv(generate_iv()), + algo((key_length == 128) ? GNUTLS_CIPHER_AES_128_CBC : + (key_length == 192) ? GNUTLS_CIPHER_AES_192_CBC : + (key_length == 256) ? GNUTLS_CIPHER_AES_256_CBC : GNUTLS_CIPHER_UNKNOWN), + key_length(key_length) { + if (this->algo == GNUTLS_CIPHER_UNKNOWN) { + throw gnutls_error("Unsupported key length for AES encryption."); + } + gnutls_init::init(); + } + + const hasher& gnutls_aes_cipher::get_hasher() const { + static const gnutls_sha_hasher h; + return h; + } + + const std::string gnutls_aes_cipher::get_token() const { + return this->get_hasher().hash(this->key, this->key_length); + } + + // Padding function for PKCS#7 + std::string pkcs7_pad(const std::string &data, const unsigned int block_size = 16) { + // Determine the number of padding bytes needed + size_t padding_length = (block_size - (data.size() % block_size)); + + // Create a new string that is a copy of data and appends the required padding bytes + std::string padded_data = data; + for(unsigned int i=0; i<padding_length; ++i){ + padded_data.push_back(static_cast<char>(padding_length)); + } + return padded_data; + } + + // Unpadding function for PKCS#7 + std::string pkcs7_unpad(const std::string &data, const unsigned int block_size = 16) { + // Check that the data is a multiple of the block size + if(data.size() % block_size != 0){ + throw gnutls_error("Data length is not a multiple of the block size."); + } + + // Get the padding byte from the end of the string + unsigned char padding_length = static_cast<unsigned char>(data.back()); + + // Validate the padding length (must be within range) + if(padding_length > data.size() || padding_length == 0){ + throw gnutls_error("Invalid PKCS#7 padding."); + } + + // Remove the padding bytes + return data.substr(0, data.size() - padding_length); + } + + std::string gnutls_aes_cipher::encrypt(const std::string& data) const { + // Create a cipher handle using the desired key length for AES encryption + gnutls_cipher_hd_t cipher_handle; + + gnutls_datum_t _key{.data = (u_char *)this->key.data(), .size = static_cast<u_int>(this->key.size())}; + gnutls_datum_t _iv{.data = (u_char *)this->iv.data(), .size = static_cast<u_int>(this->iv.size())}; + + try { + //TRACE(scope_data) << "encrypt->data: " << std::to_string(data.size()) << " | " << data; + int ret = gnutls_cipher_init(&cipher_handle, this->algo, &_key, &_iv); + if (ret < 0) { + throw gnutls_error("Error initializing cipher handle."); + } + + // Pad the data to a multiple of the block size (16 bytes for AES) + const std::string padded_data = pkcs7_pad(data); + const size_t padded_data_length = padded_data.size(); + + //TRACE(scope_data) << "encrypt->padded_data: " << std::to_string(padded_data.size()) << " | " << padded_data; + + // Allocate memory for the ciphertext + // Insert the IV at the beginning of the ciphertext + std::string ciphertext; + ciphertext.resize(padded_data_length); + + // Encrypt the data + ret = gnutls_cipher_encrypt2(cipher_handle, (const u_char *)padded_data.data(), + padded_data_length, (u_char *)ciphertext.data(), padded_data_length); + if (ret < 0) { + throw gnutls_error("Error during encryption: "+std::to_string(ret)); + } + + //TRACE(scope_data) << "encrypt->ciphertext: " << std::to_string(ciphertext.size()) << " | " << ciphertext; + + const auto encrypted_data = this->iv + ciphertext; + + //TRACE(scope_data) << "encrypt->encrypted_data: " << std::to_string(encrypted_data.size()) << " | " << encrypted_data; + + // Clean up resources + gnutls_cipher_deinit(cipher_handle); + + return encrypted_data; + } catch (...) { + gnutls_cipher_deinit(cipher_handle); + throw; // Re-throw with original exception message. + } + } + + std::string gnutls_aes_cipher::decrypt(const std::string& encrypted_data) const { + gnutls_cipher_hd_t cipher_handle; + + try { + //TRACE(scope_data) << "decrypt->encrypted_data: " << std::to_string(encrypted_data.size()) << " | " << encrypted_data; + // 1. Extract IV from prefix of ciphertext + if(encrypted_data.size() < this->iv.size()) { throw gnutls_error("Ciphertext must include an IV."); } + + gnutls_datum_t _key{.data = (u_char *)this->key.data(), .size = static_cast<u_int>(this->key.size())}; + const std::string iv_str = encrypted_data.substr(0, this->iv.size()); + const gnutls_datum_t _iv = {.data = (u_char *)iv_str.data(), .size = static_cast<u_int>(iv_str.size())}; + + // 3. Set up the Cipher handle for AES decryption + int ret = gnutls_cipher_init(&cipher_handle, this->algo, &_key, &_iv); + if (ret < 0) { + throw gnutls_error("Error initializing cipher handle."); + } + + const auto ciphertext = encrypted_data.substr(_iv.size); + + //TRACE(scope_data) << "decrypt->ciphertext: " << std::to_string(ciphertext.size()) << " | " << ciphertext; + + const size_t padded_data_length = ciphertext.size(); + std::string padded_data; + padded_data.resize(padded_data_length); + + ret = gnutls_cipher_decrypt2(cipher_handle, + (const u_char *)ciphertext.data(), + padded_data_length, + (u_char *)padded_data.data(), + padded_data_length); + if (ret < 0) { + throw gnutls_error("AES decryption failed."); + } + + //TRACE(scope_data) << "decrypt->padded_data: " << std::to_string(padded_data.size()) << " | " << padded_data; + + const auto data = pkcs7_unpad(padded_data); + + //TRACE(scope_data) << "decrypt->data: " << std::to_string(data.size()) << " | " << data; + + // Clean up handle after use + gnutls_cipher_deinit(cipher_handle); + + return data; + } catch (const std::exception& e) { + gnutls_cipher_deinit(cipher_handle); + throw; // Re-throw with original exception message. + } + } + } +} \ No newline at end of file diff --git a/src/data/httpd.cpp b/src/data/httpd.cpp index f4a5712fc0b0974e7f6a4340dfb692dc8dccc1b8..05fddf8949a7f690f83bafecba9eb2bcb7b42b1c 100644 --- a/src/data/httpd.cpp +++ b/src/data/httpd.cpp @@ -10,7 +10,6 @@ #include <filesystem> #include <microhttpd.h> #include <mutex> -#include <nlohmann/json_fwd.hpp> #include <shared_mutex> #include <sstream> #include <random> diff --git a/src/data/lmdb.cpp b/src/data/lmdb.cpp index c4b38c98aa8d4eb369e8c0cabe7fbf7d89a4dc62..1972bc15a3eb9837984f93522ff017e580145e48 100644 --- a/src/data/lmdb.cpp +++ b/src/data/lmdb.cpp @@ -1,8 +1,10 @@ // Licensed under the terms of the AGPL-3.0-only (GNU AFFERO GENERAL PUBLIC LICENSE version 3) // Copyright (C) 2018-2024 by Ralph Alexander Bariz +#include <memory> #include <vector> +#include "causal/data/crypto.hpp" #include "causal/trace.hpp" #include "causal/data/lmdb.hpp" @@ -18,12 +20,13 @@ namespace causal { this->check_crypto_token(); } - lmdb_junction::lmdb_junction(const std::shared_ptr<const crypto_coder> coder, const std::string path, const std::string name, const mode_t create_mode, const size_t map_size) - : coder(std::move(coder)) { + /*lmdb_junction::lmdb_junction(std::unique_ptr<const cipher>&& ciph, const std::string path, const std::string name, + const mode_t create_mode, const size_t map_size) + : ciph(std::forward<std::unique_ptr<const cipher>>(ciph)) { this->initialize(path, name, create_mode); this->open(name, map_size); this->check_crypto_token(); - } + }*/ lmdb_junction::~lmdb_junction() { std::unique_lock l(this->mtx); @@ -98,7 +101,7 @@ namespace causal { void lmdb_junction::check_crypto_token() { const std::string key("crypto"), - expected = this->coder ? this->coder->get_token() : std::string("plain"); + expected = this->ciph ? this->ciph->get_token() : std::string("plain"); std::string given; auto* txn = this->begin_txn(); MDB_val idVal = {.mv_size = key.size(), .mv_data = (void*)key.data()}, data; @@ -208,25 +211,25 @@ namespace causal { void lmdb_junction::repel(const junction_space& s, const std::string id) {} MDB_val lmdb_junction::get_hashed_id(const std::string& id, std::string& buf) const { - if(this->coder) { - buf = this->coder->get_hasher().hash_sha(id); + if(this->ciph) { + buf = this->ciph->get_hasher().hash(id); return {.mv_size = buf.size(), .mv_data = (void*)buf.data()}; } else return {.mv_size = id.size(), .mv_data = (void*)id.data()}; } MDB_val lmdb_junction::get_crypt_data(const std::string& data, std::string& buf) const { - if(this->coder) { - buf = this->coder->encrypt(data); + if(this->ciph) { + buf = this->ciph->encrypt(data); return {.mv_size = buf.size(), .mv_data = (void*)buf.data()}; } else return {.mv_size = data.size(), .mv_data = (void*)data.data()}; } std::string lmdb_junction::get_decrypt_data(const MDB_val val) const { - if(this->coder) { + if(this->ciph) { std::string encrypted_data((char*)val.mv_data, val.mv_size); - return this->coder->decrypt(encrypted_data); + return this->ciph->decrypt(encrypted_data); } else return std::string((char*)val.mv_data, val.mv_size); } @@ -356,7 +359,7 @@ namespace causal { bool lmdb_junction::iterate(std::function<bool(const std::string&, const std::string&)> f) const { // id is hashed why restoring it is impossible, however it would pose a security risk so do not even try - ASSERT_MSG(scope_lmdb, !this->coder, "cannot iterate encrypted database") + ASSERT_MSG(scope_lmdb, !this->ciph, "cannot iterate encrypted database") std::shared_lock l(this->mtx); auto* txn = this->begin_txn(true); MDB_cursor* cur; diff --git a/src/data/opendht.cpp b/src/data/opendht.cpp index 5afe0dd486983cf13cf36ca37a0ae1e2667dcb72..c57994990ed1a575092e12e2afb22dc96b4379e8 100644 --- a/src/data/opendht.cpp +++ b/src/data/opendht.cpp @@ -11,7 +11,7 @@ namespace causal { namespace data { INIT_TRACE_SCOPE(scope_opendht, "opendht") - std::string opendht_hasher::hash_sha(const std::string& data, u_short hash_length) const { + std::string opendht_sha_hasher::hash(const std::string& data, u_short hash_length) const { dht::Blob d(data.begin(), data.end()); auto h = dht::crypto::hash(d, hash_length); return std::string(h.begin(), h.end()); @@ -30,7 +30,7 @@ namespace causal { } const hasher& opendht_crypto_provider::get_hasher() const { - static const opendht_hasher h; + static const opendht_sha_hasher h; return h; //return this->hasher_; } @@ -329,26 +329,25 @@ namespace causal { return std::string(data.begin(), data.end()); } - opendht_aes_coder::opendht_aes_coder(const std::string& pw, const u_short key_length) - : key(dht::crypto::hash(dht::Blob(pw.begin(), pw.end()), key_length)) {} + opendht_aes_cipher::opendht_aes_cipher(const std::string& pw, const u_short key_length) + : key(dht::crypto::hash(dht::Blob(pw.begin(), pw.end()), key_length / 8)), key_length(key_length) {} - const hasher& opendht_aes_coder::get_hasher() const { - static const opendht_hasher h; + const hasher& opendht_aes_cipher::get_hasher() const { + static const opendht_sha_hasher h; return h; - //return this->hasher_; } - const std::string opendht_aes_coder::get_token() const { - auto blob = dht::crypto::hash(this->key, 20); + const std::string opendht_aes_cipher::get_token() const { + auto blob = dht::crypto::hash(this->key, this->key_length / 8); return std::string(blob.begin(), blob.end()); } - std::string opendht_aes_coder::encrypt(const std::string& data) const { + std::string opendht_aes_cipher::encrypt(const std::string& data) const { auto e = dht::crypto::aesEncrypt(dht::Blob(data.begin(), data.end()), this->key); return std::string(e.begin(), e.end()); } - std::string opendht_aes_coder::decrypt(const std::string& encrypted_data) const { + std::string opendht_aes_cipher::decrypt(const std::string& encrypted_data) const { auto d = dht::crypto::aesDecrypt(dht::Blob(encrypted_data.begin(), encrypted_data.end()), this->key); return std::string(d.begin(), d.end()); } diff --git a/test/data/httpd.cpp b/test/data/httpd.cpp index 901caead78e01714d99d052cebe74b7d9c41bd7b..83c3777dd2a18f0984b9c685787b33e73ece5578 100644 --- a/test/data/httpd.cpp +++ b/test/data/httpd.cpp @@ -3,7 +3,6 @@ #include <gtest/gtest.h> #include <memory> -#include <nlohmann/json_fwd.hpp> #include "causal/core/aspect.hpp" #include "causal/core/wirks.hpp" diff --git a/test/data/lmdb.cpp b/test/data/lmdb.cpp index e6e817a6633d197eb7e7dbb31cd16cce4a5d63ae..0e84285af58ef7e772dfb41a7623422173ae7846 100644 --- a/test/data/lmdb.cpp +++ b/test/data/lmdb.cpp @@ -11,8 +11,8 @@ #include <stdio.h> #include "causal/data/junction.hpp" +#include "causal/data/crypto.hpp" #include "causal/data/msgpack.hpp" -#include "causal/data/opendht.hpp" #include "causal/data/lmdb.hpp" #include "causal/facet/common.hpp" #include "causal/facet/spreads.hpp" @@ -283,14 +283,11 @@ TEST(causal_data_lmdb_junction, round_trip) { TEST(causal_data_lmdb_junction, crypted_round_trip) { std::string pwd1("password1"), pwd2("password2"); remove("/tmp/testlmdb_crypted"); - { const std::shared_ptr<const cd::crypto_coder> c( - new cd::opendht_aes_coder(pwd1) - ); - auto j1 = std::make_shared<cd::lmdb_junction>(c, "/tmp/testlmdb_crypted", "test1"); + { auto j1 = std::make_shared<cd::lmdb_junction>(cd::gnutls_aes_cipher(pwd1), "/tmp/testlmdb_crypted", "test1"); auto s1 = std::make_shared<cd::msgpack_space>(j1); s1->register_types<test_other_1, test_other_2>(); - auto j2 = std::make_shared<cd::lmdb_junction>(c, "/tmp/testlmdb_crypted", "test2"); + auto j2 = std::make_shared<cd::lmdb_junction>(cd::gnutls_aes_cipher(pwd1), "/tmp/testlmdb_crypted", "test2"); auto s2 = std::make_shared<cd::msgpack_space>(j2); s2->register_types<test_other_1, test_other_2>(); @@ -301,14 +298,11 @@ TEST(causal_data_lmdb_junction, crypted_round_trip) { round_trip_check(*s2, "bar"); } - { const std::shared_ptr<const cd::crypto_coder> c( - new cd::opendht_aes_coder(pwd1) - ); - auto j1 = std::make_shared<cd::lmdb_junction>(c, "/tmp/testlmdb_crypted", "test1"); + { auto j1 = std::make_shared<cd::lmdb_junction>(cd::gnutls_aes_cipher(pwd1), "/tmp/testlmdb_crypted", "test1"); auto s1 = std::make_shared<cd::msgpack_space>(j1); s1->register_types<test_other_1, test_other_2>(); - auto j2 = std::make_shared<cd::lmdb_junction>(c, "/tmp/testlmdb_crypted", "test2"); + auto j2 = std::make_shared<cd::lmdb_junction>(cd::gnutls_aes_cipher(pwd1), "/tmp/testlmdb_crypted", "test2"); auto s2 = std::make_shared<cd::msgpack_space>(j2); s2->register_types<test_other_1, test_other_2>(); @@ -316,11 +310,9 @@ TEST(causal_data_lmdb_junction, crypted_round_trip) { round_trip_check(*s2, "bar"); } - { const std::shared_ptr<const cd::crypto_coder> c( - new cd::opendht_aes_coder(pwd2) - ); - EXPECT_THROW(std::make_shared<cd::lmdb_junction>(c, "/tmp/testlmdb_crypted", "test1"), cd::lmdb_crypto_token_mismatch); - EXPECT_THROW(std::make_shared<cd::lmdb_junction>(c, "/tmp/testlmdb_crypted", "test2"), cd::lmdb_crypto_token_mismatch); + { + EXPECT_THROW(std::make_shared<cd::lmdb_junction>(cd::gnutls_aes_cipher(pwd2), "/tmp/testlmdb_crypted", "test1"), cd::lmdb_crypto_token_mismatch); + EXPECT_THROW(std::make_shared<cd::lmdb_junction>(cd::gnutls_aes_cipher(pwd2), "/tmp/testlmdb_crypted", "test2"), cd::lmdb_crypto_token_mismatch); } { @@ -331,10 +323,7 @@ TEST(causal_data_lmdb_junction, crypted_round_trip) { { remove("/tmp/testlmdb_noncrypted"); std::make_shared<cd::lmdb_junction>("/tmp/testlmdb_noncrypted"); - const std::shared_ptr<const cd::crypto_coder> c( - new cd::opendht_aes_coder(pwd1) - ); - EXPECT_THROW(std::make_shared<cd::lmdb_junction>(c, "/tmp/testlmdb_noncrypted"), cd::lmdb_crypto_token_mismatch); + EXPECT_THROW(std::make_shared<cd::lmdb_junction>(cd::gnutls_aes_cipher(pwd1), "/tmp/testlmdb_noncrypted"), cd::lmdb_crypto_token_mismatch); } } diff --git a/test/data/opendht.cpp b/test/data/opendht.cpp index f24c843155f8127135fad6eccef5e6d72e77c073..4cfb78ebd865c57e554b14a67056955bb8cb4e61 100644 --- a/test/data/opendht.cpp +++ b/test/data/opendht.cpp @@ -269,7 +269,7 @@ TEST(causal_data_opendht_crypto, crypto_encrypt_decrypt_msgpack) { TEST(causal_data_opendht_crypter, crypto_encrypt_decrypt) { std::string msg("message"), pwd("password1"); - cd::opendht_aes_coder c1(pwd), c2(pwd), c3("password2"); + cd::opendht_aes_cipher c1(pwd), c2(pwd), c3("password2"); auto encrypted_msg1 = c1.encrypt(msg); auto encrypted_msg2 = c2.encrypt(msg); EXPECT_NE(msg, encrypted_msg1); @@ -290,7 +290,7 @@ TEST(causal_data_opendht_crypter, crypto_encrypt_decrypt_msgpack) { std::string msg(ss.str()), pwd("password"); - cd::opendht_aes_coder c1(pwd), c2(pwd); + cd::opendht_aes_cipher c1(pwd), c2(pwd); auto encrypted_msg1 = c1.encrypt(msg); auto encrypted_msg2 = c2.encrypt(msg); EXPECT_NE(msg, encrypted_msg1); @@ -313,9 +313,9 @@ TEST(causal_data_opendht_crypter, crypto_hash) { std::string msg("message"), pwd1("password1"), pwd2("password2"); - cd::opendht_aes_coder c1(pwd1), c2(pwd2); - auto hashed_msg1 = c1.get_hasher().hash_sha(msg); - auto hashed_msg2 = c2.get_hasher().hash_sha(msg); + cd::opendht_aes_cipher c1(pwd1), c2(pwd2); + auto hashed_msg1 = c1.get_hasher().hash(msg); + auto hashed_msg2 = c2.get_hasher().hash(msg); EXPECT_NE(msg, hashed_msg1); EXPECT_NE(msg, hashed_msg2); EXPECT_EQ(hashed_msg1, hashed_msg2);