Fix format
This commit is contained in:
parent
3d89f30a94
commit
01ff00f3b7
@ -1,6 +1,6 @@
|
|||||||
root = true
|
root = true
|
||||||
[*]
|
[*]
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
indent_style = tab
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
109
src/crypto.cpp
109
src/crypto.cpp
@ -1,3 +1,5 @@
|
|||||||
|
#include "crypto.h"
|
||||||
|
#include <openssl/evp.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@ -7,9 +9,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
|
|
||||||
#include "crypto.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
namespace horcrux {
|
namespace horcrux {
|
||||||
@ -33,7 +32,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
EvpCipherCtx AES256_CBC::init(Mode mode,
|
EvpCipherCtx AES256_CBC::init(Mode mode,
|
||||||
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv){
|
const std::vector<unsigned char>& key,
|
||||||
|
const std::vector<unsigned char>& iv) {
|
||||||
if (key.size() != kKeySize) {
|
if (key.size() != kKeySize) {
|
||||||
throw std::runtime_error("Wrong key size");
|
throw std::runtime_error("Wrong key size");
|
||||||
}
|
}
|
||||||
@ -44,24 +44,26 @@ EvpCipherCtx AES256_CBC::init(Mode mode,
|
|||||||
EvpCipherCtx ctx;
|
EvpCipherCtx ctx;
|
||||||
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 throw std::invalid_argument("Invalid Cipher mode");
|
} else {
|
||||||
|
throw std::invalid_argument("Invalid Cipher mode");
|
||||||
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AES256_CBC::process_chunk(Mode mode, EvpCipherCtx& ctx,
|
size_t AES256_CBC::process_chunk(
|
||||||
|
Mode mode, EvpCipherCtx& ctx,
|
||||||
std::vector<unsigned char>::const_iterator begin,
|
std::vector<unsigned char>::const_iterator begin,
|
||||||
std::vector<unsigned char>::const_iterator end,
|
std::vector<unsigned char>::const_iterator end,
|
||||||
std::vector<unsigned char>& output, size_t output_offset,
|
std::vector<unsigned char>& output, size_t output_offset,
|
||||||
bool resize_in, bool resize_out)
|
bool resize_in, bool resize_out) {
|
||||||
{
|
|
||||||
auto chunk_size = end - begin;
|
auto chunk_size = end - begin;
|
||||||
int len;
|
int len;
|
||||||
if (resize_in) {
|
if (resize_in) {
|
||||||
@ -70,12 +72,14 @@ size_t AES256_CBC::process_chunk(Mode mode, EvpCipherCtx& ctx,
|
|||||||
}
|
}
|
||||||
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, &*begin, chunk_size)){
|
output.data() + output_offset, &len,
|
||||||
|
&*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, &*begin, chunk_size)){
|
output.data() + output_offset, &len,
|
||||||
|
&*begin, chunk_size)) {
|
||||||
throw std::runtime_error("EVP_DecryptUpdate");
|
throw std::runtime_error("EVP_DecryptUpdate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,20 +89,22 @@ size_t AES256_CBC::process_chunk(Mode mode, EvpCipherCtx& ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t AES256_CBC::process_final(Mode mode, EvpCipherCtx& ctx,
|
size_t AES256_CBC::process_final(Mode mode, EvpCipherCtx& ctx,
|
||||||
std::vector<unsigned char>& output, size_t output_offset,
|
std::vector<unsigned char>& output,
|
||||||
bool resize_in, bool resize_out)
|
size_t output_offset,
|
||||||
{
|
bool resize_in, bool resize_out) {
|
||||||
int len;
|
int len;
|
||||||
if (resize_in) {
|
if (resize_in) {
|
||||||
// Make sure output is large enough to add the last block
|
// Make sure output is large enough to add the last block
|
||||||
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, &len)){
|
if (1 != EVP_EncryptFinal_ex(ctx.get(), output.data() + output_offset,
|
||||||
|
&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, &len)){
|
if (1 != EVP_DecryptFinal_ex(ctx.get(), (output.data()) + output_offset,
|
||||||
|
&len)) {
|
||||||
throw std::runtime_error("EVP_DecryptFinal");
|
throw std::runtime_error("EVP_DecryptFinal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,58 +113,65 @@ 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, EvpCipherCtx& ctx,
|
||||||
std::vector<unsigned char>::const_iterator begin,
|
std::vector<unsigned char>::const_iterator begin,
|
||||||
std::vector<unsigned char>::const_iterator end,
|
std::vector<unsigned char>::const_iterator end,
|
||||||
std::vector<unsigned char>& output, size_t output_offset,
|
std::vector<unsigned char>& 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, ctx, begin, end,
|
resize_in, false);
|
||||||
output, output_offset, resize_in, false);
|
len += process_final(mode, ctx, output, output_offset + len, false,
|
||||||
len += process_final(mode, ctx,
|
resize_out);
|
||||||
output, output_offset + len, false, resize_out);
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> AES256_CBC::process(const std::vector<unsigned char>& inputdata) {
|
std::vector<unsigned char> AES256_CBC::process(
|
||||||
|
const std::vector<unsigned char>& inputdata) {
|
||||||
if (mode == Mode::kEncrypt)
|
if (mode == Mode::kEncrypt)
|
||||||
return encrypt(inputdata);
|
return encrypt(inputdata);
|
||||||
else
|
else
|
||||||
return decrypt(inputdata);
|
return decrypt(inputdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> AES256_CBC::encrypt(const std::vector<unsigned char>& plaintext) {
|
std::vector<unsigned char> AES256_CBC::encrypt(
|
||||||
return encrypt(encryption_key, horcrux::generate_random(kIvSize), plaintext);
|
const std::vector<unsigned char>& plaintext) {
|
||||||
|
return encrypt(encryption_key, horcrux::generate_random(kIvSize),
|
||||||
|
plaintext);
|
||||||
}
|
}
|
||||||
std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>& ciphertext) {
|
std::vector<unsigned char> AES256_CBC::decrypt(
|
||||||
|
const std::vector<unsigned char>& ciphertext) {
|
||||||
return decrypt(encryption_key, ciphertext);
|
return decrypt(encryption_key, ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
std::vector<unsigned char> AES256_CBC::encrypt(
|
||||||
const std::vector<unsigned char>& input)
|
const std::vector<unsigned char>& key,
|
||||||
{
|
const std::vector<unsigned char>& iv,
|
||||||
|
const std::vector<unsigned char>& input) {
|
||||||
auto ctx = init(Mode::kEncrypt, key, iv);
|
auto ctx = 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
|
||||||
std::vector<unsigned char> output(input.size() + (2 * kIvSize));
|
std::vector<unsigned char> 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, kIvSize);
|
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output,
|
||||||
|
kIvSize);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
int AES256_CBC::encrypt(const std::vector<unsigned char>& key,
|
||||||
const std::vector<unsigned char>& input, std::vector<unsigned char>& output)
|
const std::vector<unsigned char>& iv,
|
||||||
{
|
const std::vector<unsigned char>& input,
|
||||||
|
std::vector<unsigned char>& output) {
|
||||||
auto ctx = init(Mode::kEncrypt, key, iv);
|
auto ctx = init(Mode::kEncrypt, key, iv);
|
||||||
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output, 0);
|
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
int AES256_CBC::encrypt(const std::vector<unsigned char>& key,
|
||||||
|
const std::vector<unsigned char>& iv,
|
||||||
std::istream input, const size_t input_len,
|
std::istream input, const size_t input_len,
|
||||||
std::ostream output, size_t& output_len) {
|
std::ostream output, size_t& output_len) {
|
||||||
|
|
||||||
auto inbuf = std::vector<unsigned char>(input_len);
|
auto inbuf = std::vector<unsigned char>(input_len);
|
||||||
auto outbuf = std::vector<unsigned char>(input_len + 16);
|
auto outbuf = std::vector<unsigned char>(input_len + 16);
|
||||||
input.read(reinterpret_cast<char*>(inbuf.data()), input_len);
|
input.read(reinterpret_cast<char*>(inbuf.data()), input_len);
|
||||||
@ -170,25 +183,29 @@ int AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AES256_CBC::decrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
int AES256_CBC::decrypt(const std::vector<unsigned char>& key,
|
||||||
const std::vector<unsigned char>& input, std::vector<unsigned char>& output)
|
const std::vector<unsigned char>& iv,
|
||||||
{
|
const std::vector<unsigned char>& input,
|
||||||
|
std::vector<unsigned char>& output) {
|
||||||
auto ctx = init(Mode::kDecrypt, key, iv);
|
auto ctx = init(Mode::kDecrypt, key, iv);
|
||||||
process_all(Mode::kDecrypt, ctx, input.begin(), input.end(), output, 0);
|
process_all(Mode::kDecrypt, ctx, input.begin(), input.end(), output, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>& key,
|
std::vector<unsigned char> AES256_CBC::decrypt(
|
||||||
|
const std::vector<unsigned char>& key,
|
||||||
const std::vector<unsigned char>& ciphertext) {
|
const std::vector<unsigned char>& ciphertext) {
|
||||||
std::vector<unsigned char> iv(ciphertext.begin(), ciphertext.begin() + kIvSize);
|
std::vector<unsigned char> iv(ciphertext.begin(),
|
||||||
|
ciphertext.begin() + kIvSize);
|
||||||
return decrypt(key, iv, ciphertext.begin() + kIvSize, ciphertext.end());
|
return decrypt(key, iv, ciphertext.begin() + kIvSize, ciphertext.end());
|
||||||
}
|
}
|
||||||
std::vector<unsigned char> AES256_CBC::decrypt(
|
std::vector<unsigned char> AES256_CBC::decrypt(
|
||||||
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
const std::vector<unsigned char>& key,
|
||||||
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end)
|
const std::vector<unsigned char>& iv,
|
||||||
{
|
std::vector<unsigned char>::const_iterator begin,
|
||||||
|
std::vector<unsigned char>::const_iterator end) {
|
||||||
auto ctx = init(Mode::kDecrypt, key, iv);
|
auto ctx = init(Mode::kDecrypt, key, iv);
|
||||||
std::vector<unsigned char> output;
|
std::vector<unsigned char> output;
|
||||||
process_all(Mode::kDecrypt, ctx, begin, end, output, 0);
|
process_all(Mode::kDecrypt, ctx, begin, end, output, 0);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}; //namespace
|
}; // namespace horcrux
|
||||||
|
75
src/crypto.h
75
src/crypto.h
@ -13,7 +13,7 @@ enum class Mode {kEncrypt, kDecrypt};
|
|||||||
class Cipher {
|
class Cipher {
|
||||||
protected:
|
protected:
|
||||||
Cipher() = delete;
|
Cipher() = delete;
|
||||||
Cipher(Mode m) : mode(m) { }
|
explicit Cipher(Mode m) : mode(m) { }
|
||||||
Cipher(Mode m, const std::vector<unsigned char>& key) :
|
Cipher(Mode m, const std::vector<unsigned char>& key) :
|
||||||
mode(m), encryption_key(key) {}
|
mode(m), encryption_key(key) {}
|
||||||
|
|
||||||
@ -21,18 +21,25 @@ protected:
|
|||||||
mode(m), encryption_key(key) {}
|
mode(m), encryption_key(key) {}
|
||||||
|
|
||||||
std::vector<unsigned char> encryption_key;
|
std::vector<unsigned char> encryption_key;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const Mode mode;
|
const Mode mode;
|
||||||
const std::vector<unsigned char>& get_encryption_key() {return encryption_key;}
|
const std::vector<unsigned char>& get_encryption_key() {
|
||||||
|
return encryption_key;
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::vector<unsigned char> process(const std::vector<unsigned char>& inputdata) = 0;
|
virtual std::vector<unsigned char> process(
|
||||||
virtual std::vector<unsigned char> encrypt(const std::vector<unsigned char>& plaintext) = 0;
|
const std::vector<unsigned char>& inputdata) = 0;
|
||||||
virtual std::vector<unsigned char> decrypt(const std::vector<unsigned char>& ciphertext) = 0;
|
|
||||||
|
virtual std::vector<unsigned char> encrypt(
|
||||||
|
const std::vector<unsigned char>& plaintext) = 0;
|
||||||
|
|
||||||
|
virtual std::vector<unsigned char> decrypt(
|
||||||
|
const std::vector<unsigned char>& ciphertext) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EvpCipherCtx;
|
class EvpCipherCtx;
|
||||||
class AES256_CBC : public Cipher {
|
class AES256_CBC : public Cipher {
|
||||||
|
|
||||||
const size_t kKeySize = 32;
|
const size_t kKeySize = 32;
|
||||||
const size_t kIvSize = 16;
|
const size_t kIvSize = 16;
|
||||||
|
|
||||||
@ -40,53 +47,67 @@ public:
|
|||||||
AES256_CBC() : Cipher(Mode::kEncrypt) {
|
AES256_CBC() : Cipher(Mode::kEncrypt) {
|
||||||
encryption_key = horcrux::generate_random(kKeySize);
|
encryption_key = horcrux::generate_random(kKeySize);
|
||||||
}
|
}
|
||||||
AES256_CBC(const std::vector<unsigned char>& key) : Cipher(Mode::kDecrypt, key)
|
explicit AES256_CBC(const std::vector<unsigned char>& key)
|
||||||
{
|
: Cipher(Mode::kDecrypt, key) {
|
||||||
if (key.size() != kKeySize)
|
if (key.size() != kKeySize)
|
||||||
throw std::invalid_argument("Invalid key size");
|
throw std::invalid_argument("Invalid key size");
|
||||||
}
|
}
|
||||||
AES256_CBC(std::vector<unsigned char>&& key) : Cipher(Mode::kDecrypt, key)
|
explicit AES256_CBC(std::vector<unsigned char>&& key)
|
||||||
{
|
: Cipher(Mode::kDecrypt, key) {
|
||||||
if (key.size() != kKeySize)
|
if (key.size() != kKeySize)
|
||||||
throw std::invalid_argument("Invalid key size");
|
throw std::invalid_argument("Invalid key size");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> process(const std::vector<unsigned char>& inputdata) override;
|
std::vector<unsigned char> process(
|
||||||
std::vector<unsigned char> encrypt(const std::vector<unsigned char>& plaintext) override;
|
const std::vector<unsigned char>& inputdata) override;
|
||||||
std::vector<unsigned char> decrypt(const std::vector<unsigned char>& ciphertext) override;
|
std::vector<unsigned char> encrypt(
|
||||||
|
const std::vector<unsigned char>& plaintext) override;
|
||||||
|
std::vector<unsigned char> decrypt(
|
||||||
|
const std::vector<unsigned char>& ciphertext) override;
|
||||||
|
|
||||||
std::vector<unsigned char> encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
std::vector<unsigned char> encrypt(const std::vector<unsigned char>& key,
|
||||||
|
const std::vector<unsigned char>& iv,
|
||||||
const std::vector<unsigned char>& input);
|
const std::vector<unsigned char>& input);
|
||||||
|
|
||||||
int encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
int encrypt(const std::vector<unsigned char>& key,
|
||||||
const std::vector<unsigned char>& input, std::vector<unsigned char>& output);
|
const std::vector<unsigned char>& iv,
|
||||||
|
const std::vector<unsigned char>& input,
|
||||||
|
std::vector<unsigned char>& output);
|
||||||
|
|
||||||
int encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
int encrypt(const std::vector<unsigned char>& key,
|
||||||
|
const std::vector<unsigned char>& iv,
|
||||||
std::istream input, const size_t input_len,
|
std::istream input, const size_t input_len,
|
||||||
std::ostream output, size_t& output_len);
|
std::ostream output, size_t& output_len);
|
||||||
|
|
||||||
int decrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
int decrypt(const std::vector<unsigned char>& key,
|
||||||
const std::vector<unsigned char>& input, std::vector<unsigned char>& output);
|
const std::vector<unsigned char>& iv,
|
||||||
|
const std::vector<unsigned char>& input,
|
||||||
|
std::vector<unsigned char>& output);
|
||||||
|
|
||||||
std::vector<unsigned char> decrypt(const std::vector<unsigned char>& key,
|
std::vector<unsigned char> decrypt(
|
||||||
|
const std::vector<unsigned char>& key,
|
||||||
const std::vector<unsigned char>& ciphertext);
|
const std::vector<unsigned char>& ciphertext);
|
||||||
|
|
||||||
std::vector<unsigned char> decrypt(
|
std::vector<unsigned char> decrypt(
|
||||||
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
const std::vector<unsigned char>& key,
|
||||||
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end);
|
const std::vector<unsigned char>& iv,
|
||||||
|
std::vector<unsigned char>::const_iterator begin,
|
||||||
|
std::vector<unsigned char>::const_iterator end);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EvpCipherCtx init(Mode mode,
|
EvpCipherCtx init(Mode mode, const std::vector<unsigned char>& key,
|
||||||
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv);
|
const std::vector<unsigned char>& iv);
|
||||||
|
|
||||||
size_t process_chunk(Mode mode, EvpCipherCtx& ctx,
|
size_t process_chunk(Mode mode, EvpCipherCtx& ctx,
|
||||||
std::vector<unsigned char>::const_iterator begin,
|
std::vector<unsigned char>::const_iterator begin,
|
||||||
std::vector<unsigned char>::const_iterator end,
|
std::vector<unsigned char>::const_iterator end,
|
||||||
std::vector<unsigned char>& output, size_t output_offset,
|
std::vector<unsigned char>& output,
|
||||||
|
size_t output_offset,
|
||||||
bool resize_in = true, bool resize_out = true);
|
bool resize_in = true, bool resize_out = true);
|
||||||
|
|
||||||
size_t process_final(Mode mode, EvpCipherCtx& ctx,
|
size_t process_final(Mode mode, EvpCipherCtx& ctx,
|
||||||
std::vector<unsigned char>& output, size_t output_offset,
|
std::vector<unsigned char>& output,
|
||||||
|
size_t output_offset,
|
||||||
bool resize_in = true, bool resize_out = true);
|
bool resize_in = true, bool resize_out = true);
|
||||||
|
|
||||||
size_t process_all(Mode mode, EvpCipherCtx& ctx,
|
size_t process_all(Mode mode, EvpCipherCtx& ctx,
|
||||||
@ -96,5 +117,5 @@ private:
|
|||||||
bool resize_in = true, bool resize_out = true);
|
bool resize_in = true, bool resize_out = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
}; //namespace
|
}; // namespace horcrux
|
||||||
#endif // HORCRUX_SRC_CRYPTO_H
|
#endif // HORCRUX_SRC_CRYPTO_H
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
#include "horcrux.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include "horcrux.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
namespace horcrux {
|
namespace horcrux {
|
||||||
@ -20,8 +20,9 @@ void Horcrux::init(){
|
|||||||
options.base64_key = to_base64(cipher->get_encryption_key());
|
options.base64_key = to_base64(cipher->get_encryption_key());
|
||||||
break;
|
break;
|
||||||
case Mode::kDecrypt:
|
case Mode::kDecrypt:
|
||||||
if (options.count != options.input.size())
|
if (options.count != options.input.size()) {
|
||||||
throw std::invalid_argument("Invalid horcrux count");
|
throw std::invalid_argument("Invalid horcrux count");
|
||||||
|
}
|
||||||
cipher = std::make_unique<AES256_CBC>(from_base64(options.base64_key));
|
cipher = std::make_unique<AES256_CBC>(from_base64(options.base64_key));
|
||||||
input = std::make_unique<FsCryptoInput>(options.input);
|
input = std::make_unique<FsCryptoInput>(options.input);
|
||||||
output = std::make_unique<FsPlainOutput>(options.output);
|
output = std::make_unique<FsPlainOutput>(options.output);
|
||||||
@ -69,7 +70,8 @@ HorcruxOptions parse_arguments(std::vector<std::string>&& arguments){
|
|||||||
if (arguments[2] != "-k")
|
if (arguments[2] != "-k")
|
||||||
parse_error(arguments[0], "load: unknown option " + arguments[2]);
|
parse_error(arguments[0], "load: unknown option " + arguments[2]);
|
||||||
opt.base64_key = arguments[3];
|
opt.base64_key = arguments[3];
|
||||||
opt.input.insert(opt.input.begin(), arguments.begin() + 4, arguments.end() - 1);
|
opt.input.insert(opt.input.begin(), arguments.begin() + 4,
|
||||||
|
arguments.end() - 1);
|
||||||
opt.count = opt.input.size();
|
opt.count = opt.input.size();
|
||||||
opt.output = arguments.back();
|
opt.output = arguments.back();
|
||||||
} else {
|
} else {
|
||||||
@ -77,6 +79,4 @@ HorcruxOptions parse_arguments(std::vector<std::string>&& arguments){
|
|||||||
}
|
}
|
||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
|
}; // namespace horcrux
|
||||||
|
|
||||||
}; //namespace
|
|
||||||
|
@ -18,7 +18,6 @@ struct HorcruxOptions {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Horcrux {
|
class Horcrux {
|
||||||
|
|
||||||
HorcruxOptions options;
|
HorcruxOptions options;
|
||||||
std::unique_ptr<Cipher> cipher;
|
std::unique_ptr<Cipher> cipher;
|
||||||
std::unique_ptr<Input> input;
|
std::unique_ptr<Input> input;
|
||||||
@ -27,15 +26,14 @@ class Horcrux {
|
|||||||
void init();
|
void init();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Horcrux(const HorcruxOptions& opt);
|
explicit Horcrux(const HorcruxOptions& opt);
|
||||||
Horcrux(HorcruxOptions&& opt);
|
explicit Horcrux(HorcruxOptions&& opt);
|
||||||
void execute();
|
void execute();
|
||||||
const Mode& mode() { return options.mode; }
|
const Mode& mode() { return options.mode; }
|
||||||
const std::string& key() { return options.base64_key; }
|
const std::string& key() { return options.base64_key; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HorcruxOptions parse_arguments(std::vector<std::string>&& arguments);
|
HorcruxOptions parse_arguments(std::vector<std::string>&& arguments);
|
||||||
|
|
||||||
}; //namespace
|
}; // namespace horcrux
|
||||||
#endif // HORCRUX_HORCRUX_H
|
#endif // HORCRUX_HORCRUX_H
|
||||||
|
21
src/io.cpp
21
src/io.cpp
@ -1,12 +1,12 @@
|
|||||||
#include <iostream>
|
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include <iostream>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
namespace horcrux {
|
namespace horcrux {
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
FsPlainInput::FsPlainInput(const std::string& path) : file_path(fs::absolute(path))
|
FsPlainInput::FsPlainInput(const std::string& path)
|
||||||
{
|
: file_path(fs::absolute(path)) {
|
||||||
if (fs::status(path).type() != fs::file_type::regular) {
|
if (fs::status(path).type() != fs::file_type::regular) {
|
||||||
throw std::invalid_argument("Input is not a regular file");
|
throw std::invalid_argument("Input is not a regular file");
|
||||||
}
|
}
|
||||||
@ -23,8 +23,7 @@ std::vector<unsigned char> FsPlainInput::read(){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsCryptoInput::FsCryptoInput(const std::vector<std::string>& filenames)
|
FsCryptoInput::FsCryptoInput(const std::vector<std::string>& filenames) {
|
||||||
{
|
|
||||||
if (filenames.empty()){
|
if (filenames.empty()){
|
||||||
throw std::invalid_argument("No files to decrypt");
|
throw std::invalid_argument("No files to decrypt");
|
||||||
}
|
}
|
||||||
@ -53,9 +52,9 @@ std::vector<unsigned char> FsCryptoInput::read(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
FsPlainOutput::FsPlainOutput(const std::string& filename)
|
FsPlainOutput::FsPlainOutput(const std::string& filename)
|
||||||
: file_path(fs::absolute(filename))
|
: file_path(fs::absolute(filename)) {
|
||||||
{
|
if (fs::exists(file_path)
|
||||||
if (fs::exists(file_path) && fs::status(file_path).type() != fs::file_type::regular){
|
&& fs::status(file_path).type() != fs::file_type::regular) {
|
||||||
throw std::invalid_argument("Output file is not a regular file");
|
throw std::invalid_argument("Output file is not a regular file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,8 +67,7 @@ size_t FsPlainOutput::write(const std::vector<unsigned char>& to_write){
|
|||||||
FsCryptoOutput::FsCryptoOutput(const std::string& folder, const int horcrux_num,
|
FsCryptoOutput::FsCryptoOutput(const std::string& folder, const int horcrux_num,
|
||||||
const std::string& filename, const size_t horcrux_size)
|
const std::string& filename, const size_t horcrux_size)
|
||||||
: folder_path(fs::absolute(folder)), base_name(filename),
|
: folder_path(fs::absolute(folder)), base_name(filename),
|
||||||
num(horcrux_num), size(horcrux_size)
|
num(horcrux_num), size(horcrux_size) {
|
||||||
{
|
|
||||||
if (fs::status(folder_path).type() != fs::file_type::directory) {
|
if (fs::status(folder_path).type() != fs::file_type::directory) {
|
||||||
throw std::invalid_argument("Output is not a directory");
|
throw std::invalid_argument("Output is not a directory");
|
||||||
}
|
}
|
||||||
@ -90,7 +88,8 @@ size_t FsCryptoOutput::write(const std::vector<unsigned char>& to_write){
|
|||||||
f = std::ofstream(created_files.back(),
|
f = std::ofstream(created_files.back(),
|
||||||
std::ios::binary | std::ios::trunc);
|
std::ios::binary | std::ios::trunc);
|
||||||
auto chunk_size = i + 1 != num ? size : size + to_write.size() % size;
|
auto chunk_size = i + 1 != num ? size : size + to_write.size() % size;
|
||||||
f.write(reinterpret_cast<const char*>(to_write.data()) + data_written, chunk_size);
|
f.write(reinterpret_cast<const char*>(to_write.data()) + data_written,
|
||||||
|
chunk_size);
|
||||||
data_written += chunk_size;
|
data_written += chunk_size;
|
||||||
}
|
}
|
||||||
return data_written;
|
return data_written;
|
||||||
|
12
src/io.h
12
src/io.h
@ -4,6 +4,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace horcrux {
|
namespace horcrux {
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ class FsPlainInput : public Input {
|
|||||||
FsPlainInput() = delete;
|
FsPlainInput() = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FsPlainInput(const std::string& path);
|
explicit FsPlainInput(const std::string& path);
|
||||||
std::vector<unsigned char> read() override;
|
std::vector<unsigned char> read() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ class FsCryptoInput : public Input{
|
|||||||
FsCryptoInput() = delete;
|
FsCryptoInput() = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FsCryptoInput(const std::vector<std::string>& filenames);
|
explicit FsCryptoInput(const std::vector<std::string>& filenames);
|
||||||
std::vector<unsigned char> read() override;
|
std::vector<unsigned char> read() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ class FsPlainOutput : public Output {
|
|||||||
FsPlainOutput() = delete;
|
FsPlainOutput() = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FsPlainOutput(const std::string& filename);
|
explicit FsPlainOutput(const std::string& filename);
|
||||||
size_t write(const std::vector<unsigned char>& to_write) override;
|
size_t write(const std::vector<unsigned char>& to_write) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,8 +62,9 @@ public:
|
|||||||
std::vector<std::filesystem::path> created_files;
|
std::vector<std::filesystem::path> created_files;
|
||||||
|
|
||||||
FsCryptoOutput(const std::string& folder, const int horcrux_num,
|
FsCryptoOutput(const std::string& folder, const int horcrux_num,
|
||||||
const std::string& filename = "horcrux", const size_t horcrux_size = 0);
|
const std::string& filename = "horcrux",
|
||||||
|
const size_t horcrux_size = 0);
|
||||||
size_t write(const std::vector<unsigned char>& to_write) override;
|
size_t write(const std::vector<unsigned char>& to_write) override;
|
||||||
};
|
};
|
||||||
};
|
}; // namespace horcrux
|
||||||
#endif // HORCRUX_SRC_IO_H
|
#endif // HORCRUX_SRC_IO_H
|
||||||
|
@ -1,32 +1,30 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
#include <openssl/rand.h>
|
||||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||||
#include <boost/archive/iterators/transform_width.hpp>
|
#include <boost/archive/iterators/transform_width.hpp>
|
||||||
#include <openssl/rand.h>
|
|
||||||
|
|
||||||
#include "utils.h"
|
std::string horcrux::to_base64(const std::vector<unsigned char>& binary) {
|
||||||
|
|
||||||
std::string horcrux::to_base64(const std::vector<unsigned char>& binary)
|
|
||||||
{
|
|
||||||
using namespace boost::archive::iterators;
|
using namespace boost::archive::iterators;
|
||||||
using It = base64_from_binary<transform_width<std::vector<unsigned char>::const_iterator, 6, 8>>;
|
using It = base64_from_binary<transform_width<
|
||||||
|
std::vector<unsigned char>::const_iterator, 6, 8>>;
|
||||||
auto base64 = std::string(It(binary.begin()), It(binary.end()));
|
auto base64 = std::string(It(binary.begin()), It(binary.end()));
|
||||||
// Add padding.
|
// Add padding.
|
||||||
return base64.append((3 - binary.size() % 3) % 3, '=');
|
return base64.append((3 - binary.size() % 3) % 3, '=');
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> horcrux::from_base64(const std::string& base64)
|
std::vector<unsigned char> horcrux::from_base64(const std::string& base64) {
|
||||||
{
|
|
||||||
using namespace boost::archive::iterators;
|
using namespace boost::archive::iterators;
|
||||||
using It = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
|
using It = transform_width<binary_from_base64<std::string::const_iterator>,
|
||||||
auto binary = std::vector<unsigned char>(It(base64.begin()), It(base64.end()));
|
8, 6>;
|
||||||
|
auto binary = std::vector<unsigned char>(It(base64.begin()),
|
||||||
|
It(base64.end()));
|
||||||
// Remove padding.
|
// Remove padding.
|
||||||
auto length = base64.size();
|
auto length = base64.size();
|
||||||
if(binary.size() > 2 && base64[length - 1] == '=' && base64[length - 2] == '=')
|
if (binary.size() > 2 && base64[length - 1] == '='
|
||||||
{
|
&& base64[length - 2] == '=') {
|
||||||
binary.erase(binary.end() - 2, binary.end());
|
binary.erase(binary.end() - 2, binary.end());
|
||||||
}
|
} else if (binary.size() > 1 && base64[length - 1] == '=') {
|
||||||
else if(binary.size() > 1 && base64[length - 1] == '=')
|
|
||||||
{
|
|
||||||
binary.erase(binary.end() - 1, binary.end());
|
binary.erase(binary.end() - 1, binary.end());
|
||||||
}
|
}
|
||||||
return binary;
|
return binary;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "gtest/gtest.h"
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
/* Utility functions */
|
/* Utility functions */
|
||||||
std::vector<unsigned char> generic_read_file(const std::string& filename) {
|
std::vector<unsigned char> generic_read_file(const std::string& filename) {
|
||||||
@ -11,10 +11,11 @@ std::vector<unsigned char> generic_read_file(const std::string& filename){
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> get_created_filenames(const horcrux::FsCryptoOutput& out){
|
std::vector<std::string> get_created_filenames(
|
||||||
|
const horcrux::FsCryptoOutput& out) {
|
||||||
std::vector<std::string> result(out.created_files.size());
|
std::vector<std::string> result(out.created_files.size());
|
||||||
transform(out.created_files.begin(), out.created_files.end(), result.begin(),
|
transform(out.created_files.begin(), out.created_files.end(),
|
||||||
[](auto path){return path.string();});
|
result.begin(), [](auto path) { return path.string(); } );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
void delete_created_files(const horcrux::FsCryptoOutput& out) {
|
void delete_created_files(const horcrux::FsCryptoOutput& out) {
|
||||||
@ -22,13 +23,15 @@ void delete_created_files(const horcrux::FsCryptoOutput& out){
|
|||||||
[](auto f) { std::filesystem::remove(f); } );
|
[](auto f) { std::filesystem::remove(f); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> get_encrypted_files(const std::string& folder, const std::string& basename) {
|
std::vector<std::string> get_encrypted_files(const std::string& folder,
|
||||||
|
const std::string& basename) {
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
for (auto& p: std::filesystem::directory_iterator(folder)) {
|
for (auto& p: std::filesystem::directory_iterator(folder)) {
|
||||||
if (p.path().string().starts_with(basename) &&
|
if (p.path().string().starts_with(basename)
|
||||||
p.path().string().ends_with(".enc"))
|
&& p.path().string().ends_with(".enc")) {
|
||||||
result.push_back(p.path().string());
|
result.push_back(p.path().string());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
std::sort(result.begin(), result.end());
|
std::sort(result.begin(), result.end());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user