Optimization attempt
This commit is contained in:
parent
d8a050b183
commit
26533e2769
154
src/crypto.cpp
154
src/crypto.cpp
@ -12,28 +12,8 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
namespace horcrux {
|
namespace horcrux {
|
||||||
/** Cipher context class
|
|
||||||
* This is a wrapper for OpenSSL context object, just for RAII pattern
|
|
||||||
*/
|
|
||||||
class EvpCipherCtx {
|
|
||||||
EVP_CIPHER_CTX *ptr;
|
|
||||||
|
|
||||||
public:
|
void AES256_CBC::init(Mode mode, const raw_data& key,
|
||||||
EvpCipherCtx() {
|
|
||||||
ptr = EVP_CIPHER_CTX_new();
|
|
||||||
}
|
|
||||||
|
|
||||||
~EvpCipherCtx() {
|
|
||||||
EVP_CIPHER_CTX_free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
EVP_CIPHER_CTX* get() {
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
EvpCipherCtx AES256_CBC::init(Mode mode, const raw_data& key,
|
|
||||||
const raw_data& iv) {
|
const raw_data& iv) {
|
||||||
if (key.size() != kKeySize) {
|
if (key.size() != kKeySize) {
|
||||||
throw std::runtime_error("Wrong key size");
|
throw std::runtime_error("Wrong key size");
|
||||||
@ -42,24 +22,54 @@ EvpCipherCtx AES256_CBC::init(Mode mode, const raw_data& key,
|
|||||||
throw std::runtime_error("Wrong IV size");
|
throw std::runtime_error("Wrong IV size");
|
||||||
}
|
}
|
||||||
|
|
||||||
EvpCipherCtx ctx;
|
ctx = std::make_unique<EvpCipherCtx>();
|
||||||
if (mode == Mode::kEncrypt) {
|
if (mode == Mode::kEncrypt) {
|
||||||
if (EVP_EncryptInit(ctx.get(), EVP_aes_256_cbc(),
|
if (EVP_EncryptInit(ctx->get(), EVP_aes_256_cbc(),
|
||||||
key.data(), iv.data()) == 0) {
|
key.data(), iv.data()) == 0) {
|
||||||
throw std::runtime_error("EVP_EncryptInit");
|
throw std::runtime_error("EVP_EncryptInit");
|
||||||
}
|
}
|
||||||
} else if (mode == Mode::kDecrypt) {
|
} else if (mode == Mode::kDecrypt) {
|
||||||
if (EVP_DecryptInit(ctx.get(), EVP_aes_256_cbc(),
|
if (EVP_DecryptInit(ctx->get(), EVP_aes_256_cbc(),
|
||||||
key.data(), iv.data()) == 0) {
|
key.data(), iv.data()) == 0) {
|
||||||
throw std::runtime_error("EVP_DecryptInit");
|
throw std::runtime_error("EVP_DecryptInit");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw std::invalid_argument("Invalid Cipher mode");
|
throw std::invalid_argument("Invalid Cipher mode");
|
||||||
}
|
}
|
||||||
return ctx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AES256_CBC::process_chunk(Mode mode, EvpCipherCtx& ctx,
|
size_t AES256_CBC::process_start(Mode mode,
|
||||||
|
raw_data::const_iterator begin,
|
||||||
|
raw_data::const_iterator end,
|
||||||
|
raw_data& output,
|
||||||
|
bool resize_in, bool resize_out) {
|
||||||
|
auto current = begin;
|
||||||
|
size_t output_offset = 0;
|
||||||
|
raw_data iv(kIvSize);
|
||||||
|
|
||||||
|
if (mode == Mode::kEncrypt) {
|
||||||
|
// Make sure output is large enough to add IV
|
||||||
|
output.resize(kIvSize);
|
||||||
|
// generate IV
|
||||||
|
iv = generate_random(kIvSize);
|
||||||
|
// write IV to output
|
||||||
|
std::copy(iv.begin(), iv.end(), output.begin());
|
||||||
|
output_offset += kIvSize;
|
||||||
|
} else {
|
||||||
|
// kDecrypt
|
||||||
|
if (end - begin < kIvSize){
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"First encrypted chunk must contain the whole IV");
|
||||||
|
}
|
||||||
|
// read IV from input
|
||||||
|
std::copy(current, current + kIvSize, iv.begin());
|
||||||
|
current += kIvSize;
|
||||||
|
}
|
||||||
|
init(mode, encryption_key, iv);
|
||||||
|
return output_offset + process_chunk(mode, current, end, output, output_offset, resize_in, resize_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AES256_CBC::process_chunk(Mode mode,
|
||||||
raw_data::const_iterator begin,
|
raw_data::const_iterator begin,
|
||||||
raw_data::const_iterator end,
|
raw_data::const_iterator end,
|
||||||
raw_data& output, size_t output_offset,
|
raw_data& output, size_t output_offset,
|
||||||
@ -71,13 +81,13 @@ size_t AES256_CBC::process_chunk(Mode mode, EvpCipherCtx& ctx,
|
|||||||
output.resize(output_offset + chunk_size + kIvSize);
|
output.resize(output_offset + chunk_size + kIvSize);
|
||||||
}
|
}
|
||||||
if (mode == Mode::kEncrypt) {
|
if (mode == Mode::kEncrypt) {
|
||||||
if (1 != EVP_EncryptUpdate(ctx.get(),
|
if (1 != EVP_EncryptUpdate(ctx->get(),
|
||||||
output.data() + output_offset, &len,
|
output.data() + output_offset, &len,
|
||||||
&*begin, chunk_size)) {
|
&*begin, chunk_size)) {
|
||||||
throw std::runtime_error("EVP_EncryptUpdate");
|
throw std::runtime_error("EVP_EncryptUpdate");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (1 != EVP_DecryptUpdate(ctx.get(),
|
if (1 != EVP_DecryptUpdate(ctx->get(),
|
||||||
output.data() + output_offset, &len,
|
output.data() + output_offset, &len,
|
||||||
&*begin, chunk_size)) {
|
&*begin, chunk_size)) {
|
||||||
throw std::runtime_error("EVP_DecryptUpdate");
|
throw std::runtime_error("EVP_DecryptUpdate");
|
||||||
@ -88,7 +98,7 @@ size_t AES256_CBC::process_chunk(Mode mode, EvpCipherCtx& ctx,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AES256_CBC::process_final(Mode mode, EvpCipherCtx& ctx,
|
size_t AES256_CBC::process_final(Mode mode,
|
||||||
raw_data& output, size_t output_offset,
|
raw_data& output, size_t output_offset,
|
||||||
bool resize_in, bool resize_out) {
|
bool resize_in, bool resize_out) {
|
||||||
int len;
|
int len;
|
||||||
@ -97,12 +107,12 @@ size_t AES256_CBC::process_final(Mode mode, EvpCipherCtx& ctx,
|
|||||||
output.resize(output_offset + kIvSize);
|
output.resize(output_offset + kIvSize);
|
||||||
}
|
}
|
||||||
if (mode == Mode::kEncrypt) {
|
if (mode == Mode::kEncrypt) {
|
||||||
if (1 != EVP_EncryptFinal_ex(ctx.get(), output.data() + output_offset,
|
if (1 != EVP_EncryptFinal_ex(ctx->get(), output.data() + output_offset,
|
||||||
&len)) {
|
&len)) {
|
||||||
throw std::runtime_error("EVP_EncryptFinal");
|
throw std::runtime_error("EVP_EncryptFinal");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (1 != EVP_DecryptFinal_ex(ctx.get(), (output.data()) + output_offset,
|
if (1 != EVP_DecryptFinal_ex(ctx->get(), (output.data()) + output_offset,
|
||||||
&len)) {
|
&len)) {
|
||||||
throw std::runtime_error("EVP_DecryptFinal");
|
throw std::runtime_error("EVP_DecryptFinal");
|
||||||
}
|
}
|
||||||
@ -112,62 +122,78 @@ size_t AES256_CBC::process_final(Mode mode, EvpCipherCtx& ctx,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AES256_CBC::process_all(Mode mode, EvpCipherCtx& ctx,
|
size_t AES256_CBC::process_all(Mode mode,
|
||||||
raw_data::const_iterator begin,
|
raw_data::const_iterator begin,
|
||||||
raw_data::const_iterator end,
|
raw_data::const_iterator end,
|
||||||
raw_data& output, size_t output_offset,
|
raw_data& output, size_t output_offset,
|
||||||
bool resize_in, bool resize_out) {
|
bool resize_in, bool resize_out) {
|
||||||
int len = process_chunk(mode, ctx, begin, end, output, output_offset,
|
int len = process_chunk(mode, begin, end, output, output_offset,
|
||||||
resize_in, false);
|
resize_in, false);
|
||||||
len += process_final(mode, ctx, output, output_offset + len, false,
|
len += process_final(mode, output, output_offset + len, false,
|
||||||
resize_out);
|
resize_out);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_data AES256_CBC::process(const raw_data& inputdata) {
|
raw_data AES256_CBC::process(const raw_data& inputdata, bool begin, bool end) {
|
||||||
if (mode == Mode::kEncrypt)
|
//if (mode == Mode::kEncrypt)
|
||||||
return encrypt(inputdata);
|
// return encrypt(inputdata, begin, end);
|
||||||
|
//else
|
||||||
|
// return decrypt(inputdata, begin, end);
|
||||||
|
raw_data output;
|
||||||
|
size_t len;
|
||||||
|
if (begin)
|
||||||
|
len = process_start(mode, inputdata.begin(), inputdata.end(), output);
|
||||||
else
|
else
|
||||||
return decrypt(inputdata);
|
len = process_chunk(mode, inputdata.begin(), inputdata.end(), output, 0);
|
||||||
|
if (end)
|
||||||
|
process_final(mode, output, len);
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_data AES256_CBC::encrypt(const raw_data& plaintext) {
|
raw_data AES256_CBC::encrypt(const raw_data& plaintext, bool begin, bool end) {
|
||||||
return encrypt(encryption_key, horcrux::generate_random(kIvSize),
|
//return encrypt(encryption_key, horcrux::generate_random(kIvSize),
|
||||||
plaintext);
|
// plaintext);
|
||||||
|
raw_data output;
|
||||||
|
size_t len;
|
||||||
|
if (begin)
|
||||||
|
len = process_start(Mode::kEncrypt, plaintext.begin(), plaintext.end(), output);
|
||||||
|
else
|
||||||
|
len = process_chunk(Mode::kEncrypt, plaintext.begin(), plaintext.end(), output, 0);
|
||||||
|
if (end)
|
||||||
|
process_final(Mode::kEncrypt, output, len);
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
raw_data AES256_CBC::decrypt(const raw_data& ciphertext) {
|
raw_data AES256_CBC::decrypt(const raw_data& ciphertext, bool begin, bool end) {
|
||||||
return decrypt(encryption_key, ciphertext);
|
//return decrypt(encryption_key, ciphertext);
|
||||||
|
//raw_data output;
|
||||||
|
//init(Mode::kDecrypt, key, iv);
|
||||||
|
//process_all(Mode::kDecrypt, begin, end, output, 0);
|
||||||
|
//auto len = process_start(Mode::kDecrypt, ciphertext.begin(), ciphertext.end(), output);
|
||||||
|
//process_final(Mode::kDecrypt, output, len);
|
||||||
|
//return output;
|
||||||
|
raw_data output;
|
||||||
|
size_t len;
|
||||||
|
if (begin)
|
||||||
|
len = process_start(Mode::kDecrypt, ciphertext.begin(), ciphertext.end(), output);
|
||||||
|
else
|
||||||
|
len = process_chunk(Mode::kDecrypt, ciphertext.begin(), ciphertext.end(), output, 0);
|
||||||
|
if (end)
|
||||||
|
process_final(Mode::kDecrypt, output, len);
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_data AES256_CBC::encrypt(const raw_data& key, const raw_data& iv,
|
raw_data AES256_CBC::encrypt(const raw_data& key, const raw_data& iv,
|
||||||
const raw_data& input) {
|
const raw_data& input) {
|
||||||
auto ctx = init(Mode::kEncrypt, key, iv);
|
init(Mode::kEncrypt, key, iv);
|
||||||
|
|
||||||
// Make sure ouput is large enough to contain IV + encrypted data + padding
|
// Make sure ouput is large enough to contain IV + encrypted data + padding
|
||||||
raw_data output(input.size() + (2 * kIvSize));
|
raw_data output(input.size() + (2 * kIvSize));
|
||||||
std::copy(iv.begin(), iv.end(), output.begin());
|
std::copy(iv.begin(), iv.end(), output.begin());
|
||||||
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output,
|
process_all(Mode::kEncrypt, input.begin(), input.end(), output,
|
||||||
kIvSize);
|
kIvSize);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
int AES256_CBC::encrypt(const raw_data& key, const raw_data& iv,
|
|
||||||
std::istream input, const size_t input_len,
|
|
||||||
std::ostream output, size_t& output_len) {
|
|
||||||
auto inbuf = raw_data(input_len);
|
|
||||||
auto outbuf = raw_data(input_len + 16);
|
|
||||||
input.read(reinterpret_cast<char*>(inbuf.data()), input_len);
|
|
||||||
|
|
||||||
encrypt(key, iv, inbuf, outbuf);
|
|
||||||
|
|
||||||
output.write(reinterpret_cast<char*>(outbuf.data()), outbuf.size());
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
raw_data AES256_CBC::decrypt(const raw_data& key, const raw_data& ciphertext) {
|
raw_data AES256_CBC::decrypt(const raw_data& key, const raw_data& ciphertext) {
|
||||||
raw_data iv(ciphertext.begin(), ciphertext.begin() + kIvSize);
|
raw_data iv(ciphertext.begin(), ciphertext.begin() + kIvSize);
|
||||||
return decrypt(key, iv, ciphertext.begin() + kIvSize, ciphertext.end());
|
return decrypt(key, iv, ciphertext.begin() + kIvSize, ciphertext.end());
|
||||||
@ -181,9 +207,9 @@ raw_data AES256_CBC::decrypt(const raw_data& key, const raw_data& iv,
|
|||||||
raw_data AES256_CBC::decrypt(const raw_data& key, const raw_data& iv,
|
raw_data AES256_CBC::decrypt(const raw_data& key, const raw_data& iv,
|
||||||
raw_data::const_iterator begin,
|
raw_data::const_iterator begin,
|
||||||
raw_data::const_iterator end) {
|
raw_data::const_iterator end) {
|
||||||
auto ctx = init(Mode::kDecrypt, key, iv);
|
|
||||||
raw_data output;
|
raw_data output;
|
||||||
process_all(Mode::kDecrypt, ctx, begin, end, output, 0);
|
init(Mode::kDecrypt, key, iv);
|
||||||
|
process_all(Mode::kDecrypt, begin, end, output, 0);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}; // namespace horcrux
|
}; // namespace horcrux
|
||||||
|
73
src/crypto.h
73
src/crypto.h
@ -1,5 +1,6 @@
|
|||||||
#ifndef HORCRUX_SRC_CRYPTO_H
|
#ifndef HORCRUX_SRC_CRYPTO_H
|
||||||
#define HORCRUX_SRC_CRYPTO_H
|
#define HORCRUX_SRC_CRYPTO_H
|
||||||
|
#include <openssl/evp.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -48,28 +49,51 @@ public:
|
|||||||
|
|
||||||
/** @brief process inputdata according to Cipher mode
|
/** @brief process inputdata according to Cipher mode
|
||||||
* @param inputdata buffer containing data to process
|
* @param inputdata buffer containing data to process
|
||||||
|
* @param begin set to true if this is the first chunk of data to process.
|
||||||
|
* @param end set to true if this is the last chunk of data to process.
|
||||||
* @return processed data
|
* @return processed data
|
||||||
*/
|
*/
|
||||||
virtual raw_data process(
|
virtual raw_data process(
|
||||||
const raw_data& inputdata) = 0;
|
const raw_data& inputdata, bool begin = true, bool end = true) = 0;
|
||||||
|
|
||||||
/** @brief encrypt the content of a buffer using Cipher key
|
/** @brief encrypt the content of a buffer using Cipher key
|
||||||
* @param plaintext the input buffer
|
* @param plaintext the input buffer
|
||||||
|
* @param begin set to true if this is the first chunk of data to process.
|
||||||
|
* @param end set to true if this is the last chunk of data to process.
|
||||||
* @return encrypted data
|
* @return encrypted data
|
||||||
*/
|
*/
|
||||||
virtual raw_data encrypt(
|
virtual raw_data encrypt(
|
||||||
const raw_data& plaintext) = 0;
|
const raw_data& plaintext, bool begin = true, bool end = true) = 0;
|
||||||
|
|
||||||
/** @brief decrypt the content of a buffer using Cipher key
|
/** @brief decrypt the content of a buffer using Cipher key
|
||||||
* @param decrypt the input buffer
|
* @param decrypt the input buffer
|
||||||
|
* @param begin set to true if this is the first chunk of data to process.
|
||||||
|
* @param end set to true if this is the last chunk of data to process.
|
||||||
* @return decrypted data
|
* @return decrypted data
|
||||||
*/
|
*/
|
||||||
virtual raw_data decrypt(
|
virtual raw_data decrypt(
|
||||||
const raw_data& ciphertext) = 0;
|
const raw_data& ciphertext, bool begin = true, bool end = true) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// forward declaration
|
/** Cipher context class
|
||||||
class EvpCipherCtx;
|
* This is a wrapper for OpenSSL context object, just for RAII pattern
|
||||||
|
*/
|
||||||
|
class EvpCipherCtx {
|
||||||
|
EVP_CIPHER_CTX *ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EvpCipherCtx() {
|
||||||
|
ptr = EVP_CIPHER_CTX_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
~EvpCipherCtx() {
|
||||||
|
EVP_CIPHER_CTX_free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX* get() {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** @brief AES256 Cipher
|
/** @brief AES256 Cipher
|
||||||
* @details
|
* @details
|
||||||
@ -90,6 +114,8 @@ class AES256_CBC : public Cipher {
|
|||||||
/** AES256 CBC initialization vector size, from AES256 specs */
|
/** AES256 CBC initialization vector size, from AES256 specs */
|
||||||
const size_t kIvSize = 16;
|
const size_t kIvSize = 16;
|
||||||
|
|
||||||
|
std::unique_ptr<EvpCipherCtx> ctx = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** @brief Create cipher in encrypt mode with random key */
|
/** @brief Create cipher in encrypt mode with random key */
|
||||||
AES256_CBC() : Cipher(Mode::kEncrypt) {
|
AES256_CBC() : Cipher(Mode::kEncrypt) {
|
||||||
@ -108,24 +134,36 @@ public:
|
|||||||
|
|
||||||
/** @brief process inputdata according to Cipher mode
|
/** @brief process inputdata according to Cipher mode
|
||||||
* @param inputdata buffer containing data to process
|
* @param inputdata buffer containing data to process
|
||||||
|
* @param begin set to true if this is the first chunk of data to process.
|
||||||
|
* (deals with IV)
|
||||||
|
* @param end set to true if this is the last chunk of data to process.
|
||||||
|
* (deals with padding)
|
||||||
* @return processed data
|
* @return processed data
|
||||||
*/
|
*/
|
||||||
raw_data process(
|
raw_data process(
|
||||||
const raw_data& inputdata) override;
|
const raw_data& inputdata, bool begin = true, bool end = true) override;
|
||||||
|
|
||||||
/** @brief encrypt the content of a buffer using Cipher key
|
/** @brief encrypt the content of a buffer using Cipher key
|
||||||
* @param plaintext the input buffer
|
* @param plaintext the input buffer
|
||||||
|
* @param begin set to true if this is the first chunk of data to process.
|
||||||
|
* (deals with IV)
|
||||||
|
* @param end set to true if this is the last chunk of data to process.
|
||||||
|
* (deals with padding)
|
||||||
* @return encrypted data
|
* @return encrypted data
|
||||||
*/
|
*/
|
||||||
raw_data encrypt(
|
raw_data encrypt(
|
||||||
const raw_data& plaintext) override;
|
const raw_data& plaintext, bool begin = true, bool end = true) override;
|
||||||
|
|
||||||
/** @brief decrypt the content of a buffer using Cipher key
|
/** @brief decrypt the content of a buffer using Cipher key
|
||||||
* @param decrypt the input buffer
|
* @param decrypt the input buffer
|
||||||
|
* @param begin set to true if this is the first chunk of data to process.
|
||||||
|
* (deals with IV)
|
||||||
|
* @param end set to true if this is the last chunk of data to process.
|
||||||
|
* (deals with padding)
|
||||||
* @return decrypted data
|
* @return decrypted data
|
||||||
*/
|
*/
|
||||||
raw_data decrypt(
|
raw_data decrypt(
|
||||||
const raw_data& ciphertext) override;
|
const raw_data& ciphertext, bool begin = true, bool end = true) override;
|
||||||
|
|
||||||
/** @brief Read the whole input and return a buffer with the encrypted data
|
/** @brief Read the whole input and return a buffer with the encrypted data
|
||||||
* @param key the encryption key
|
* @param key the encryption key
|
||||||
@ -182,18 +220,16 @@ public:
|
|||||||
raw_data::const_iterator end);
|
raw_data::const_iterator end);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** @brief Create a Cipher context object needed for enc/dec operations
|
/** @brief Initialize the Cipher context object needed for enc/dec operations
|
||||||
* @param mode encrypt or decrypt
|
* @param mode encrypt or decrypt
|
||||||
* @param key the enc/dec key
|
* @param key the enc/dec key
|
||||||
* @param the initialization vector
|
* @param the initialization vector
|
||||||
* @return the Cipher context object
|
|
||||||
*/
|
*/
|
||||||
EvpCipherCtx init(Mode mode, const raw_data& key,
|
void init(Mode mode, const raw_data& key,
|
||||||
const raw_data& iv);
|
const raw_data& iv);
|
||||||
|
|
||||||
/** @brief process a chunk of input
|
/** @brief process a chunk of input
|
||||||
* @param mode encrypt or decrypt
|
* @param mode encrypt or decrypt
|
||||||
* @param ctx the Cipher context object
|
|
||||||
* @param begin beginning of the input chunk
|
* @param begin beginning of the input chunk
|
||||||
* @param end end of the input chunk
|
* @param end end of the input chunk
|
||||||
* @param output output buffer
|
* @param output output buffer
|
||||||
@ -203,17 +239,21 @@ private:
|
|||||||
* order to make sure there is enough room.
|
* order to make sure there is enough room.
|
||||||
* @param resize_out shrink the output buffer at the end
|
* @param resize_out shrink the output buffer at the end
|
||||||
*/
|
*/
|
||||||
size_t process_chunk(Mode mode, EvpCipherCtx& ctx,
|
size_t process_chunk(Mode mode,
|
||||||
raw_data::const_iterator begin,
|
raw_data::const_iterator begin,
|
||||||
raw_data::const_iterator end,
|
raw_data::const_iterator end,
|
||||||
raw_data& output,
|
raw_data& output,
|
||||||
size_t output_offset,
|
size_t output_offset,
|
||||||
bool resize_in = true, bool resize_out = true);
|
bool resize_in = true, bool resize_out = true);
|
||||||
|
size_t process_start(Mode mode,
|
||||||
|
raw_data::const_iterator begin,
|
||||||
|
raw_data::const_iterator end,
|
||||||
|
raw_data& output,
|
||||||
|
bool resize_in = true, bool resize_out = true);
|
||||||
|
|
||||||
/** @brief Finalize a encryption/decryption process. Write remaining bytes
|
/** @brief Finalize a encryption/decryption process. Write remaining bytes
|
||||||
* to the output
|
* to the output
|
||||||
* @param mode encrypt or decrypt
|
* @param mode encrypt or decrypt
|
||||||
* @param ctx the Cipher context object
|
|
||||||
* @param output output buffer
|
* @param output output buffer
|
||||||
* @param output_offset where to start to append the last data within
|
* @param output_offset where to start to append the last data within
|
||||||
* the output buffer
|
* the output buffer
|
||||||
@ -221,14 +261,13 @@ private:
|
|||||||
* order to make sure there is enough room.
|
* order to make sure there is enough room.
|
||||||
* @param resize_out shrink the output buffer at the end
|
* @param resize_out shrink the output buffer at the end
|
||||||
*/
|
*/
|
||||||
size_t process_final(Mode mode, EvpCipherCtx& ctx,
|
size_t process_final(Mode mode,
|
||||||
raw_data& output,
|
raw_data& output,
|
||||||
size_t output_offset,
|
size_t output_offset,
|
||||||
bool resize_in = true, bool resize_out = true);
|
bool resize_in = true, bool resize_out = true);
|
||||||
|
|
||||||
/** @brief process a input and finalize it.
|
/** @brief process a input and finalize it.
|
||||||
* @param mode encrypt or decrypt
|
* @param mode encrypt or decrypt
|
||||||
* @param ctx the Cipher context object
|
|
||||||
* @param begin beginning of the input chunk
|
* @param begin beginning of the input chunk
|
||||||
* @param end end of the input chunk
|
* @param end end of the input chunk
|
||||||
* @param output output buffer
|
* @param output output buffer
|
||||||
@ -238,7 +277,7 @@ private:
|
|||||||
* order to make sure there is enough room.
|
* order to make sure there is enough room.
|
||||||
* @param resize_out shrink the output buffer at the end
|
* @param resize_out shrink the output buffer at the end
|
||||||
*/
|
*/
|
||||||
size_t process_all(Mode mode, EvpCipherCtx& ctx,
|
size_t process_all(Mode mode,
|
||||||
raw_data::const_iterator begin,
|
raw_data::const_iterator begin,
|
||||||
raw_data::const_iterator end,
|
raw_data::const_iterator end,
|
||||||
raw_data& output, size_t output_offset,
|
raw_data& output, size_t output_offset,
|
||||||
|
@ -5,6 +5,15 @@
|
|||||||
|
|
||||||
namespace horcrux {
|
namespace horcrux {
|
||||||
|
|
||||||
|
void Horcrux::read_chunks(size_t size) {
|
||||||
|
raw_data buf = input->read(size);
|
||||||
|
output->write_chunk(cipher->process(buf, true, false));
|
||||||
|
while ((buf = input->read(size)).size() == size) {
|
||||||
|
output->write_chunk(cipher->process(buf, false, false));
|
||||||
|
}
|
||||||
|
output->write_chunk(cipher->process(buf, false, true));
|
||||||
|
}
|
||||||
|
|
||||||
void Horcrux::init() {
|
void Horcrux::init() {
|
||||||
if (options.count <= 0) {
|
if (options.count <= 0) {
|
||||||
throw std::invalid_argument("Invalid horcrux count");
|
throw std::invalid_argument("Invalid horcrux count");
|
||||||
@ -32,7 +41,8 @@ void Horcrux::init() {
|
|||||||
|
|
||||||
void Horcrux::run() {
|
void Horcrux::run() {
|
||||||
if (options.mode == Mode::kEncrypt)
|
if (options.mode == Mode::kEncrypt)
|
||||||
output->write(cipher->encrypt(input->read()));
|
//output->write(cipher->encrypt(input->read()));
|
||||||
|
read_chunks(512);
|
||||||
else
|
else
|
||||||
output->write(cipher->decrypt(input->read()));
|
output->write(cipher->decrypt(input->read()));
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ class Horcrux {
|
|||||||
* Used cipher, input and output are generic and the actual implementation
|
* Used cipher, input and output are generic and the actual implementation
|
||||||
* can be selected in this function */
|
* can be selected in this function */
|
||||||
void init();
|
void init();
|
||||||
|
void read_chunks(size_t size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** remove default constructor */
|
/** remove default constructor */
|
||||||
|
29
src/io.cpp
29
src/io.cpp
@ -68,7 +68,9 @@ raw_data FsCryptoInput::read(size_t size) {
|
|||||||
while (data_read < size && current_file < file_paths.size()) {
|
while (data_read < size && current_file < file_paths.size()) {
|
||||||
if (!file_stream.is_open())
|
if (!file_stream.is_open())
|
||||||
file_stream.open(file_paths[current_file].first, std::ios::binary);
|
file_stream.open(file_paths[current_file].first, std::ios::binary);
|
||||||
file_stream.read(reinterpret_cast<char*>(result.data()) + data_read, size - data_read);
|
file_stream.read(
|
||||||
|
reinterpret_cast<char*>(result.data()) + data_read,
|
||||||
|
size - data_read);
|
||||||
data_read += file_stream.gcount();
|
data_read += file_stream.gcount();
|
||||||
if(file_stream.eof()) {
|
if(file_stream.eof()) {
|
||||||
file_stream.close();
|
file_stream.close();
|
||||||
@ -93,7 +95,8 @@ size_t FsPlainOutput::write(const raw_data& to_write) {
|
|||||||
}
|
}
|
||||||
size_t FsPlainOutput::write_chunk(const raw_data& to_write) {
|
size_t FsPlainOutput::write_chunk(const raw_data& to_write) {
|
||||||
file_stream.open(file_path, std::ios::binary);
|
file_stream.open(file_path, std::ios::binary);
|
||||||
file_stream.write(reinterpret_cast<const char*>(to_write.data()), to_write.size());
|
file_stream.write(reinterpret_cast<const char*>(to_write.data()),
|
||||||
|
to_write.size());
|
||||||
return to_write.size();
|
return to_write.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,29 +132,37 @@ size_t FsCryptoOutput::write(const raw_data& to_write) {
|
|||||||
// }
|
// }
|
||||||
// return data_written;
|
// return data_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FsCryptoOutput::write_chunk(const raw_data& to_write) {
|
size_t FsCryptoOutput::write_chunk(const raw_data& to_write) {
|
||||||
|
// horcrux file size must be known in advance
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
throw std::invalid_argument("Invalid horcrux size");
|
throw std::invalid_argument("Invalid horcrux size");
|
||||||
}
|
}
|
||||||
size_t data_written{0};
|
size_t data_written{0};
|
||||||
std::cout << to_write.size() << " " << data_written << std::endl;
|
|
||||||
while (data_written < to_write.size()){
|
while (data_written < to_write.size()){
|
||||||
if(!file_stream.is_open()){
|
if(!file_stream.is_open()){
|
||||||
std::string name = base_name + '.' + std::to_string(created_files.size()) + ".enc";
|
// create a new file
|
||||||
|
std::string name = base_name +
|
||||||
|
'.' + std::to_string(created_files.size()) + ".enc";
|
||||||
created_files.emplace_back(folder_path / name);
|
created_files.emplace_back(folder_path / name);
|
||||||
file_stream.open(created_files.back(),
|
file_stream.open(created_files.back(),
|
||||||
std::ios::binary | std::ios::trunc);
|
std::ios::binary | std::ios::trunc);
|
||||||
}
|
}
|
||||||
|
// write up to fill the file size or consume the input buffer
|
||||||
|
auto writable = std::min(size - file_stream.tellp(),
|
||||||
|
to_write.size() - data_written);
|
||||||
// the last file may contain more data (size % num)
|
// the last file may contain more data (size % num)
|
||||||
auto writable = std::min(size - file_stream.tellp(), to_write.size() - data_written);
|
if (num == created_files.size()) {
|
||||||
if (num == created_files.size()) { writable = to_write.size() - data_written; }
|
writable = to_write.size() - data_written;
|
||||||
file_stream.write(reinterpret_cast<const char*>(to_write.data()) + data_written,
|
}
|
||||||
|
file_stream.write(
|
||||||
|
reinterpret_cast<const char*>(to_write.data()) + data_written,
|
||||||
writable);
|
writable);
|
||||||
data_written += writable;
|
data_written += writable;
|
||||||
if (file_stream.tellp() >= size){
|
if (file_stream.tellp() >= size){
|
||||||
|
// close the file if it has been filled
|
||||||
file_stream.close();
|
file_stream.close();
|
||||||
}
|
}
|
||||||
std::cout << to_write.size() << " " << data_written << std::endl;
|
|
||||||
}
|
}
|
||||||
return data_written;
|
return data_written;
|
||||||
}
|
}
|
||||||
|
7
src/io.h
7
src/io.h
@ -19,12 +19,7 @@ public:
|
|||||||
virtual raw_data read() = 0;
|
virtual raw_data read() = 0;
|
||||||
virtual raw_data read(size_t size) = 0;
|
virtual raw_data read(size_t size) = 0;
|
||||||
|
|
||||||
// template<class UnaryFunction>
|
|
||||||
// void read_chunks(size_t size, UnaryFunction f) {
|
|
||||||
// while ((auto buf = read(size)) == size) {
|
|
||||||
// f(buf);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Base Class for Output
|
/** @brief Base Class for Output
|
||||||
|
Loading…
Reference in New Issue
Block a user