Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
felixguendling committed Dec 28, 2023
1 parent 64673ef commit 86918d8
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 57 deletions.
4 changes: 2 additions & 2 deletions .pkg.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
884132695651941781
13283054806179763047
FTXUI dd6a5d371fd7a3e2937bb579955003c54b727233
utf8proc 1cb28a66ca79a0845e99433fd1056257456cef8b
cista e5a58c750d5432cc4ea2855bbfc42bcea591d0f7
Expand Down Expand Up @@ -30,4 +30,4 @@ unordered_dense c11595a7743d20622637584bddf77243d72ae152
rtree.c 498f993c38e80f21d55ab72f14675b72fca991cc
tg 9d3db9c9ccbde60449e25338550b14865ea1b98e
libressl 390253a44ceef00eb620c38606588414326e9f23
uWebSockets 22e346ec2087089cfe46a59d3fc4a328b63561e3
uWebSockets 6d73aac9097121a3c42b862d6c3019f560764dd7
50 changes: 33 additions & 17 deletions exe/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ int main(int ac, char** av) {
auto ctx = adr::guess_context{cache};
auto lang_list =
std::basic_string<adr::language_idx_t>{adr::kDefaultLang};
auto c = adr::crypto{iv, key};
auto c = adr::crypto{key};
auto h = adr::http{};

ctx.resize(*t);
Expand All @@ -108,23 +108,39 @@ int main(int ac, char** av) {

server.post("/", [&](uWS::HttpResponse<false>* res,
uWS::HttpRequest* req) {
auto const iv_header = req->getHeader("x-iv");
auto aborted = std::make_shared<bool>(false);
res->onData([&c, &h, res, req_body = std::make_shared<std::string>(),
aborted](std::string_view chunk, bool const fin) mutable {
(*req_body) += chunk;
if (fin && !*aborted) {
adr::decode(c,
std::span{reinterpret_cast<std::uint8_t const*>(
req_body->data()),
req_body->size()},
h);
std::cout << h << "\n";
auto const response = adr::encode(c, {.body_ = "Hello World!"});
res->end({reinterpret_cast<char const*>(response.data()),
response.size()});
}
});
res->onAborted([aborted]() { *aborted = true; });
try {
res->onData([&c, &h, res, req_body = std::make_shared<std::string>(),
iv = adr::crypto::decode_base64(iv_header, 16), aborted](
std::string_view chunk, bool const fin) mutable {
try {
(*req_body) += chunk;
if (fin && !*aborted) {
adr::decode(c, iv,
std::span{reinterpret_cast<std::uint8_t const*>(
req_body->data()),
req_body->size()},
h);
std::cout << h << "\n";
auto const response = adr::encode(c, {.body_ = "Hello World!"});
res->writeHeader("X-Iv", response.iv_);
res->end(
{reinterpret_cast<char const*>(response.encrypted_.data()),
response.encrypted_.size()});
}
} catch (...) {
*aborted = true;
res->writeStatus("500 Internal Server Error");
res->endWithoutBody(std::nullopt, true);
}
});
res->onAborted([aborted]() { *aborted = true; });
} catch (...) {
*aborted = true;
res->writeStatus("500 Internal Server Error");
res->endWithoutBody(std::nullopt, true);
}
});
server.listen(port, [&](auto* listen_socket) {
if (listen_socket) {
Expand Down
13 changes: 9 additions & 4 deletions include/adr/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <vector>

#include "openssl/evp.h"
#include "openssl/rand.h"

namespace adr {

Expand All @@ -21,18 +22,22 @@ struct crypto {

static std::vector<std::uint8_t> read_base64_file(
std::filesystem::path const&, std::size_t);
static std::vector<std::uint8_t> decode_base64(std::string_view, std::size_t);
static std::string encode_base64(std::span<std::uint8_t const>);
static std::vector<std::uint8_t> generate_random_bytes(std::size_t n);

crypto(std::vector<std::uint8_t> const& iv,
std::vector<std::uint8_t> const& key);
crypto(std::vector<std::uint8_t> const& key);
crypto(crypto const&) = delete;
crypto(crypto&&) = delete;
crypto& operator=(crypto const&) = delete;
crypto& operator=(crypto&&) = delete;
~crypto();

std::span<std::uint8_t const> crypt(std::span<std::uint8_t const>, mode);
std::span<std::uint8_t const> crypt(std::span<std::uint8_t const> iv,
std::span<std::uint8_t const> input,
mode);

std::vector<std::uint8_t> const &iv_, &key_;
std::vector<std::uint8_t> const& key_;
std::vector<std::uint8_t> buf_;
EVP_CIPHER_CTX* ctx_{nullptr};
};
Expand Down
12 changes: 10 additions & 2 deletions include/adr/request.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@ struct http {
std::string body_;
};

void decode(crypto& c, std::span<std::uint8_t const> encoded, http& req);
struct encoded {
std::string iv_;
std::span<std::uint8_t const> encrypted_;
};

void decode(crypto& c,
std::span<std::uint8_t const> iv,
std::span<std::uint8_t const> encoded,
http& req);

std::span<std::uint8_t const> encode(crypto& c, http const& res);
encoded encode(crypto& c, http const& res);

} // namespace adr
48 changes: 33 additions & 15 deletions src/crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,24 @@

namespace adr {

crypto::crypto(std::vector<std::uint8_t> const& iv,
std::vector<std::uint8_t> const& key)
: iv_{iv}, key_{key}, ctx_{EVP_CIPHER_CTX_new()} {
utl::verify(iv.size() == 16U,
"crypto: IV should be 16 bytes (128 bit), size={}", iv.size());
crypto::crypto(std::vector<std::uint8_t> const& key)
: key_{key}, ctx_{EVP_CIPHER_CTX_new()} {
utl::verify(key.size() == 32U,
"crypto: key should be 32 bytes (256 bit), size={}", key.size());
utl::verify(ctx_ != nullptr, "decrypt_ctx: EVP_CIPHER_CTX_new -> nullptr");
}

crypto::~crypto() { EVP_CIPHER_CTX_free(ctx_); }

std::vector<std::uint8_t> crypto::read_base64_file(
std::filesystem::path const& path, std::size_t const expected_size) {
auto const content = utl::read_file(path.generic_string().c_str());
utl::verify(content.has_value(),
"read_base64_file: count not read file \"{}\"", path);
std::vector<std::uint8_t> crypto::decode_base64(
std::string_view const s, std::size_t const expected_size) {
if (s.empty()) {
return {};
}

auto out = std::vector<std::uint8_t>(3U * content->size() / 4U + 1U);
auto out = std::vector<std::uint8_t>(3U * s.size() / 4U + 1U);
auto const length = EVP_DecodeBlock(
out.data(), reinterpret_cast<std::uint8_t const*>(content->data()),
content->size());
out.data(), reinterpret_cast<std::uint8_t const*>(s.data()), s.size());
utl::verify(length + 1U == out.size(),
"read_base64_file: expected {} bytes, got {}", out.size(),
length);
Expand All @@ -40,10 +36,32 @@ std::vector<std::uint8_t> crypto::read_base64_file(
return out;
}

std::span<std::uint8_t const> crypto::crypt(std::span<std::uint8_t const> input,
std::vector<std::uint8_t> crypto::read_base64_file(
std::filesystem::path const& path, std::size_t const expected_size) {
auto const content = utl::read_file(path.generic_string().c_str());
utl::verify(content.has_value(),
"read_base64_file: count not read file \"{}\"", path);
return decode_base64(*content, expected_size);
}

std::string crypto::encode_base64(std::span<std::uint8_t const> bytes) {
auto out = std::string{};
out.resize(4 * ((bytes.size() + 2) / 3));
auto const length = EVP_EncodeBlock(
reinterpret_cast<unsigned char*>(out.data()), bytes.data(), bytes.size());
utl::verify(length == out.size(), "encode_base64: expected {} bytes, got {}",
out.size(), length);
return out;
}

std::span<std::uint8_t const> crypto::crypt(std::span<std::uint8_t const> iv,
std::span<std::uint8_t const> input,
mode const m) {
utl::verify(iv.size() == 16U,
"crypto: IV should be 16 bytes (128 bit), size={}", iv.size());

EVP_CIPHER_CTX_reset(ctx_);
EVP_CipherInit(ctx_, EVP_aes_256_cbc(), key_.data(), iv_.data(), m);
EVP_CipherInit(ctx_, EVP_aes_256_cbc(), key_.data(), iv.data(), m);

auto out_size = 0;
buf_.resize(input.size() + AES_BLOCK_SIZE);
Expand Down
25 changes: 18 additions & 7 deletions src/request.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "adr/request.h"

#include "openssl/rand.h"

#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
Expand All @@ -10,8 +12,11 @@ namespace json = rapidjson;

namespace adr {

void decode(crypto& c, std::span<std::uint8_t const> encoded, http& req) {
auto const decrypted = c.crypt(encoded, adr::crypto::kDecrypt);
void decode(crypto& c,
std::span<std::uint8_t const> iv,
std::span<std::uint8_t const> encoded,
http& req) {
auto const decrypted = c.crypt(iv, encoded, adr::crypto::kDecrypt);
auto const input = std::string_view{
reinterpret_cast<char const*>(decrypted.data()), decrypted.size()};

Expand All @@ -38,7 +43,7 @@ void decode(crypto& c, std::span<std::uint8_t const> encoded, http& req) {
}
}

std::span<std::uint8_t const> encode(crypto& c, http const& res) {
encoded encode(crypto& c, http const& res) {
auto buf = json::StringBuffer{};
auto w = json::Writer<json::StringBuffer>{buf};

Expand All @@ -53,10 +58,16 @@ std::span<std::uint8_t const> encode(crypto& c, http const& res) {
}
w.EndObject();

return c.crypt(
std::span{reinterpret_cast<std::uint8_t const*>(buf.GetString()),
buf.GetLength()},
adr::crypto::kEncrypt);
auto iv = std::vector<std::uint8_t>(16);
RAND_bytes(iv.data(), iv.size());

return encoded{
.iv_ = crypto::encode_base64(iv),
.encrypted_ = c.crypt(
iv,
std::span{reinterpret_cast<std::uint8_t const*>(buf.GetString()),
buf.GetLength()},
adr::crypto::kEncrypt)};
}

} // namespace adr
31 changes: 21 additions & 10 deletions test/crypto_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ TEST(crypto, crypto) {
auto const key = std::vector<std::uint8_t>{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
auto c = adr::crypto{iv, key};
auto c = adr::crypto{key};

auto const input =
std::vector<std::uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
fmt::print("input: {}, size={}\n", input, input.size());

for (auto i = 0U; i != 10; ++i) {
auto const encrypted = c.crypt(std::span{input}, adr::crypto::kEncrypt);
auto const encrypted = c.crypt(iv, std::span{input}, adr::crypto::kEncrypt);
auto const encrypted_copy =
std::vector<std::uint8_t>{encrypted.begin(), encrypted.end()};
fmt::print("encrypted: {}, size={}\n", encrypted_copy,
encrypted_copy.size());

auto const decrypted =
c.crypt(std::span{encrypted_copy}, adr::crypto::kDecrypt);
c.crypt(iv, std::span{encrypted_copy}, adr::crypto::kDecrypt);
auto const decrypted_copy =
std::vector<std::uint8_t>{decrypted.begin(), decrypted.end()};
fmt::print("decrypted: {}, size={}\n", decrypted_copy,
Expand All @@ -53,17 +53,17 @@ TEST(crypto, read_key_iv) {
std::vector<std::uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
fmt::print("input: {}, size={}\n", input, input.size());

auto c = adr::crypto{iv, key};
auto c = adr::crypto{key};

for (auto i = 0U; i != 10; ++i) {
auto const encrypted = c.crypt(std::span{input}, adr::crypto::kEncrypt);
auto const encrypted = c.crypt(iv, std::span{input}, adr::crypto::kEncrypt);
auto const encrypted_copy =
std::vector<std::uint8_t>{encrypted.begin(), encrypted.end()};
fmt::print("encrypted: {}, size={}\n", encrypted_copy,
encrypted_copy.size());

auto const decrypted =
c.crypt(std::span{encrypted_copy}, adr::crypto::kDecrypt);
c.crypt(iv, std::span{encrypted_copy}, adr::crypto::kDecrypt);
auto const decrypted_copy =
std::vector<std::uint8_t>{decrypted.begin(), decrypted.end()};
fmt::print("decrypted: {}, size={}\n", decrypted_copy,
Expand All @@ -76,15 +76,26 @@ TEST(crypto, read_key_iv) {
TEST(crypto, request_response) {
auto const key = adr::crypto::read_base64_file("test/key.txt", 32);
auto const iv = adr::crypto::read_base64_file("test/iv.txt", 16);
auto c = adr::crypto{iv, key};
auto c = adr::crypto{key};

auto const h = adr::http{.path_ = "abc", .body_ = "def"};
auto const encoded = adr::encode(c, h);
auto const encoded_copy =
std::vector<std::uint8_t>{encoded.begin(), encoded.end()};
auto const encoded_copy = std::vector<std::uint8_t>{
encoded.encrypted_.begin(), encoded.encrypted_.end()};

auto decoded = adr::http{};
adr::decode(c, encoded_copy, decoded);
adr::decode(c, adr::crypto::decode_base64(encoded.iv_, 16), encoded_copy,
decoded);

EXPECT_EQ(h, decoded);
}

TEST(crypto, base64_roundtrip) {
auto const str = std::string_view{"1234567890abcdef"};
auto const data = std::vector<std::uint8_t>{str.begin(), str.end()};

auto const b64_encoded = adr::crypto::encode_base64(data);
auto const decoded = adr::crypto::decode_base64(b64_encoded, 16);

EXPECT_EQ(data, decoded);
}

0 comments on commit 86918d8

Please sign in to comment.