mal-packet-weaver
C++20 packet serialization/deserialization library.
Loading...
Searching...
No Matches
aes.hpp
Go to the documentation of this file.
1#pragma once
3#include "crypto-common.hpp"
4
5#ifdef MAL_PACKET_WEAVER_HAS_OPENSSL
6namespace mal_packet_weaver::crypto::AES
7{
12 class AES256 final : public non_copyable_non_movable, public EncryptionInterface
13
14 {
15 public:
19 static constexpr uint32_t KEY_SIZE = 32;
23 static constexpr uint32_t SALT_SIZE = 8;
24
31 AES256(const KeyView input_key, const ByteView salt, const int n_rounds = 5)
32 {
33 AlwaysAssert(input_key.size() == 32, "Key size must be 32 bytes");
34 AlwaysAssert(salt.size() == 8, "Salt size must be 8 bytes");
35
36 unsigned char key[32], iv[32];
37
38 /*
39 * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key
40 * material. n_rounds is the number of times the we hash the material. A greater number
41 * of rounds enhances security but results in slower performance
42 */
43 int i =
44 EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt.as<unsigned char>(), input_key.as<unsigned char>(),
45 static_cast<int>(input_key.size()), n_rounds, key, iv);
46
47 AlwaysAssert(i == 32, "Key size is " + std::to_string(i) + " bytes - should be 256 bits");
48
49 encrypt_context_.reset(EVP_CIPHER_CTX_new());
50 decrypt_context_.reset(EVP_CIPHER_CTX_new());
51 EVP_CIPHER_CTX_init(encrypt_context_.get());
52 EVP_EncryptInit_ex(encrypt_context_.get(), EVP_aes_256_cbc(), nullptr, key, iv);
53 EVP_CIPHER_CTX_init(decrypt_context_.get());
54 EVP_DecryptInit_ex(decrypt_context_.get(), EVP_aes_256_cbc(), nullptr, key, iv);
55 }
61 [[nodiscard]] ByteArray encrypt(const ByteView plaintext) const override
62 {
63 /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */
64 AlwaysAssert(plaintext.size() < INT_MAX - AES_BLOCK_SIZE, "Plaintext size is too large");
65 int c_len = static_cast<int>(plaintext.size() + AES_BLOCK_SIZE);
66 int f_len = 0;
67 ByteArray ciphertext;
68 ciphertext.resize(c_len);
69
70 EVP_EncryptInit_ex(encrypt_context_.get(), nullptr, nullptr, nullptr, nullptr);
71 EVP_EncryptUpdate(encrypt_context_.get(), ciphertext.as<unsigned char>(), &c_len,
72 plaintext.as<unsigned char>(), static_cast<int>(plaintext.size()));
73 EVP_EncryptFinal_ex(encrypt_context_.get(), ciphertext.as<unsigned char>() + c_len, &f_len);
74
75 ciphertext.resize(c_len + f_len);
76 return ciphertext;
77 }
78
84 [[nodiscard]] ByteArray decrypt(const ByteView ciphertext) const override
85 {
86 /* plaintext will always be equal to or lesser than length of ciphertext*/
87 int p_len = static_cast<int>(ciphertext.size());
88 int f_len = 0;
89 ByteArray plaintext;
90 plaintext.resize(p_len);
91 EVP_DecryptInit_ex(decrypt_context_.get(), nullptr, nullptr, nullptr, nullptr);
92 EVP_DecryptUpdate(decrypt_context_.get(), plaintext.as<unsigned char>(), &p_len,
93 ciphertext.as<unsigned char>(), static_cast<int>(ciphertext.size()));
94 EVP_DecryptFinal_ex(decrypt_context_.get(), plaintext.as<unsigned char>() + p_len, &f_len);
95 plaintext.resize(p_len + f_len);
96 return plaintext;
97 }
98 void encrypt_in_place(ByteArray &plaintext) const override
99 {
100 auto tmp = encrypt(plaintext);
101 plaintext = tmp;
102 }
103 void decrypt_in_place(ByteArray &ciphertext) const override
104 {
105 auto tmp = decrypt(ciphertext);
106 ciphertext = tmp;
107 }
108
109 private:
110 EVP_CIPHER_CTX_WRAPPER encrypt_context_;
111 EVP_CIPHER_CTX_WRAPPER decrypt_context_;
112 };
113} // namespace mal_packet_weaver::crypto::AES
114#endif
void AlwaysAssert(bool value, std::string_view message="Assert failed", std::source_location location=std::source_location::current())
Always asserts a condition with customizable behavior.