1#ifndef TENDUKE_CRYPTO_ABSTRACTCIPHERS_H
2#define TENDUKE_CRYPTO_ABSTRACTCIPHERS_H
5#include "./CryptoException.h"
6#include "./kdf/PBKDF2.h"
7#include "./symmetric/aes/AESGCMCipher.h"
8#include "../utl/BinaryView.h"
9#include "../utl/DataSink.h"
10#include "../utl/SimpleBuffer.h"
11#include "../utl/StringSink.h"
12#include "../utl/random/RandomBytes.h"
28class AbstractCiphers :
public virtual Ciphers
32 const std::shared_ptr<::tenduke::utl::random::RandomBytes> &random,
33 const std::shared_ptr<::tenduke::crypto::PBKDF2> &keyGenerator
36 , keyGenerator_(keyGenerator)
39 std::unique_ptr<::tenduke::utl::BinaryData>
decrypt(
40 const ::tenduke::utl::DataSpan &ciphertext,
41 const ::tenduke::utl::DataSpan &encryptionKey
46 ciphertext.size_bytes(),
48 encryptionKey.size_bytes()
53 const ::tenduke::utl::DataSpan &ciphertext,
54 const ::tenduke::utl::DataSpan &encryptionKey
57 auto plaintext =
decrypt(ciphertext, encryptionKey);
58 return std::string(
reinterpret_cast<char *
>(plaintext->getData()), plaintext->getLength());
61 std::unique_ptr<::tenduke::utl::BinaryData>
encrypt(
62 const ::tenduke::utl::DataSpan &plaintext,
63 const ::tenduke::utl::DataSpan &encryptionKey
68 plaintext.size_bytes(),
70 encryptionKey.size_bytes()
74 std::unique_ptr<::tenduke::utl::BinaryData>
encrypt(
75 const std::string &plaintext,
76 const ::tenduke::utl::DataSpan &encryptionKey
86 const ::tenduke::crypto::Cipher &cipher,
87 const ::tenduke::utl::DataSpan &ciphertext
90 const auto version = readAndValidateHeader(ciphertext);
91 if (version != VERSION_2) {
92 throw ::tenduke::crypto::CryptoException(
93 "invalid_blob_version",
94 "The provided blob is not compatible with this method."
109 const ::tenduke::crypto::Cipher &cipher,
110 const ::tenduke::utl::DataSpan &plaintext,
114 writeHeader(ciphertext, VERSION_2);
115 cipher.encryptData(plaintext, ciphertext);
128 static constexpr std::uint16_t VERSION_1 = 0x0001;
132 static constexpr std::uint16_t VERSION_2 = 0x0002;
137 virtual std::unique_ptr<::tenduke::utl::BinaryData> encryptBytes(
138 const unsigned char *plaintext,
139 std::size_t plaintextLength,
140 const unsigned char *encryptionKey,
141 std::size_t encryptionKeyLength
144 std::uint8_t saltBytes[::tenduke::crypto::aes::GCM_NONCE_SIZE];
145 random_->generate(saltBytes,
sizeof(saltBytes));
148 const auto key = keyGenerator_->deriveAES256Key(
154 std::unique_ptr<::tenduke::utl::SimpleBuffer> ciphertext(new ::tenduke::utl::SimpleBuffer());
155 writeHeader(*ciphertext, VERSION_1);
157 key->gcmCipher()->encryptData(
166 virtual std::unique_ptr<::tenduke::utl::BinaryData> decryptBytes(
167 const unsigned char *ciphertext,
168 std::size_t ciphertextLength,
169 const unsigned char *encryptionKey,
170 std::size_t encryptionKeyLength
173 const std::uint16_t version = readAndValidateHeader(ciphertext, ciphertextLength);
174 if (version != VERSION_1) {
175 throw ::tenduke::crypto::CryptoException(
176 "cipher_unsupported_version",
177 "Unsupported blob version"
181 if (ciphertextLength <
BLOB_HEADER_SIZE + ::tenduke::crypto::aes::GCM_NONCE_SIZE + ::tenduke::crypto::aes::GCM_MAC_SIZE) {
182 throw ::tenduke::crypto::CryptoException(
183 "cipher_invalid_ciphertext",
184 "Ciphertext too short to contain header, nonce and authentication tag"
188 const auto key = keyGenerator_->deriveAES256Key(
194 std::unique_ptr<::tenduke::utl::SimpleBuffer> plaintext(new ::tenduke::utl::SimpleBuffer());
195 key->gcmCipher()->decryptData(
203 virtual void writeHeader(
unsigned char *buffer,
const std::uint16_t version)
const
205 buffer[0] =
static_cast<unsigned char>((
BLOB_MAGIC >> 24) & 0xFF);
206 buffer[1] =
static_cast<unsigned char>((
BLOB_MAGIC >> 16) & 0xFF);
207 buffer[2] =
static_cast<unsigned char>((
BLOB_MAGIC >> 8) & 0xFF);
208 buffer[3] =
static_cast<unsigned char>(
BLOB_MAGIC & 0xFF);
209 buffer[4] =
static_cast<unsigned char>((version >> 8) & 0xFF);
210 buffer[5] =
static_cast<unsigned char>(version & 0xFF);
213 virtual void writeHeader(::tenduke::utl::DataSink &output,
const std::uint16_t version)
const
219 output.
append(
static_cast<std::uint8_t
>((version >> 8) & 0xFF));
220 output.
append(
static_cast<std::uint8_t
>(version & 0xFF));
223 virtual std::uint16_t readAndValidateHeader(
224 const unsigned char *buffer,
225 std::size_t bufferLength
229 throw ::tenduke::crypto::CryptoException(
230 "cipher_invalid_ciphertext",
231 "Ciphertext too short to contain header"
235 const std::uint32_t magic =
236 (
static_cast<std::uint32_t
>(buffer[0]) << 24) |
237 (
static_cast<std::uint32_t
>(buffer[1]) << 16) |
238 (
static_cast<std::uint32_t
>(buffer[2]) << 8) |
239 static_cast<std::uint32_t
>(buffer[3]);
242 throw ::tenduke::crypto::CryptoException(
243 "cipher_invalid_ciphertext",
244 "Invalid blob magic value"
248 return (
static_cast<std::uint16_t
>(buffer[4]) << 8) |
249 static_cast<std::uint16_t
>(buffer[5]);
252 virtual std::uint16_t readAndValidateHeader(const ::tenduke::utl::DataSpan &buffer)
const
254 return readAndValidateHeader(buffer.data(), buffer.size_bytes());
258 const std::shared_ptr<::tenduke::utl::random::RandomBytes> random_;
259 const std::shared_ptr<::tenduke::crypto::PBKDF2> keyGenerator_;
static constexpr std::uint32_t BLOB_MAGIC
Magic value for encrypted blob header.
Definition AbstractCiphers.h:121
std::string decryptString(const ::tenduke::utl::DataSpan &ciphertext, const ::tenduke::utl::DataSpan &encryptionKey) const override
Decrypts given data using the system default cipher (AES256 GCM) to a string.
Definition AbstractCiphers.h:52
std::unique_ptr<::tenduke::utl::BinaryData > encrypt(const std::string &plaintext, const ::tenduke::utl::DataSpan &encryptionKey) const override
Encrypts given data using the system default cipher (AES256 GCM).
Definition AbstractCiphers.h:74
static constexpr int PBKDF2_ITERATIONS
Number of PBKDF2 iterations for VERSION_1 key derivation.
Definition AbstractCiphers.h:135
std::string decryptString(const ::tenduke::crypto::Cipher &cipher, const ::tenduke::utl::DataSpan &ciphertext) const override
Decrypts given data using the given cipher to a string.
Definition AbstractCiphers.h:85
std::unique_ptr<::tenduke::utl::BinaryData > decrypt(const ::tenduke::utl::DataSpan &ciphertext, const ::tenduke::utl::DataSpan &encryptionKey) const override
Decrypts given data using the system default cipher (AES256 GCM).
Definition AbstractCiphers.h:39
std::unique_ptr<::tenduke::utl::BinaryData > encrypt(const ::tenduke::utl::DataSpan &plaintext, const ::tenduke::utl::DataSpan &encryptionKey) const override
Encrypts given data using the system default cipher (AES256 GCM).
Definition AbstractCiphers.h:61
void encrypt(const ::tenduke::crypto::Cipher &cipher, const ::tenduke::utl::DataSpan &plaintext, ::tenduke::utl::DataSink &ciphertext) const override
Encrypts data with the given cipher.
Definition AbstractCiphers.h:108
static constexpr std::size_t BLOB_HEADER_SIZE
Header size: magic (4 bytes) + version (2 bytes).
Definition AbstractCiphers.h:124
A "service locator" for cipher-related operations.
Definition Ciphers.h:20
A sink to which binary data can be appended.
Definition DataSink.h:14
virtual void append(const std::uint8_t *data, std::size_t size)=0
Appends binary data to the sink.
A tenduke::utl::DataSink, which appends binary data to a std::string.
Definition StringSink.h:16
Cryptography services.
Definition AbstractCiphers.h:18
BinaryView make_view(const unsigned char *data, const std::size_t size)
A helper function to create a tenduke::utl::BinaryView from a const pointer.
Definition BinaryView.h:93
Root for classes, functions and globals of 10Duke C++ Client.
Definition APIRequest.h:4