iw5-mod/src/utils/cryptography.cpp

324 lines
8.0 KiB
C++
Raw Normal View History

2019-09-24 05:46:47 -04:00
#include <std_include.hpp>
#include "string.hpp"
#include "cryptography.hpp"
/// http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/libtomcrypt/doc/libTomCryptDoc.pdf
2019-09-27 16:35:57 -04:00
namespace utils::cryptography
2019-09-24 05:46:47 -04:00
{
2019-09-27 16:35:57 -04:00
ecc::key::key()
2019-09-24 05:46:47 -04:00
{
2019-09-27 16:35:57 -04:00
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
ecc::key::~key()
{
this->free();
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
bool ecc::key::is_valid() const
{
return (!memory::is_set(&this->key_storage_, 0, sizeof(this->key_storage_)));
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
ecc_key* ecc::key::get()
{
return &this->key_storage_;
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string ecc::key::get_public_key() const
{
uint8_t buffer[512] = {0};
DWORD length = sizeof(buffer);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
if (ecc_ansi_x963_export(&this->key_storage_, buffer, &length) == CRYPT_OK)
2019-09-24 05:46:47 -04:00
{
2019-09-27 16:35:57 -04:00
return std::string(reinterpret_cast<char*>(buffer), length);
2019-09-24 05:46:47 -04:00
}
2019-09-27 16:35:57 -04:00
return {};
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
void ecc::key::set(const std::string& pub_key_buffer)
{
this->free();
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
if (ecc_ansi_x963_import(reinterpret_cast<const uint8_t*>(pub_key_buffer.data()), pub_key_buffer.size(),
&this->key_storage_) != CRYPT_OK)
2019-09-24 05:46:47 -04:00
{
2019-09-27 16:35:57 -04:00
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
2019-09-24 05:46:47 -04:00
}
2019-09-27 16:35:57 -04:00
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
void ecc::key::deserialize(const std::string& key)
{
this->free();
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
if (ecc_import(reinterpret_cast<const uint8_t*>(key.data()), key.size(), &this->key_storage_) != CRYPT_OK)
{
2019-09-24 05:46:47 -04:00
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
}
2019-09-27 16:35:57 -04:00
}
std::string ecc::key::serialize(const int type) const
{
uint8_t buffer[4096] = {0};
DWORD length = sizeof(buffer);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK)
2019-09-24 05:46:47 -04:00
{
2019-09-27 16:35:57 -04:00
return std::string(reinterpret_cast<char*>(buffer), length);
2019-09-24 05:46:47 -04:00
}
2019-09-27 16:35:57 -04:00
return "";
}
void ecc::key::free()
{
if (this->is_valid())
2019-09-24 05:46:47 -04:00
{
2019-09-27 16:35:57 -04:00
ecc_free(&this->key_storage_);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
bool ecc::key::operator==(key& key) const
{
return (this->is_valid() && key.is_valid() && this->serialize(PK_PUBLIC) == key.serialize(PK_PUBLIC));
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
ecc::key ecc::generate_key(const int bits)
{
key key;
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
ltc_mp = ltm_desc;
register_prng(&sprng_desc);
ecc_make_key(nullptr, find_prng("sprng"), bits / 8, key.get());
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
return key;
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string ecc::sign_message(key key, const std::string& message)
{
if (!key.is_valid()) return "";
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
uint8_t buffer[512];
DWORD length = sizeof(buffer);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
ltc_mp = ltm_desc;
register_prng(&sprng_desc);
ecc_sign_hash(reinterpret_cast<const uint8_t*>(message.data()), message.size(), buffer, &length, nullptr,
find_prng("sprng"), key.get());
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
return std::string(reinterpret_cast<char*>(buffer), length);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
bool ecc::verify_message(key key, const std::string& message, const std::string& signature)
{
if (!key.is_valid()) return false;
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
ltc_mp = ltm_desc;
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
auto result = 0;
return (ecc_verify_hash(reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
reinterpret_cast<const uint8_t*>(message.data()), message.size(), &result,
key.get()) == CRYPT_OK && result != 0);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key)
{
initialize();
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
const auto prng_id = find_prng("yarrow");
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
rsa_key new_key;
rsa_import(PBYTE(key.data()), key.size(), &new_key);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
prng_state yarrow;
rng_make_prng(128, prng_id, &yarrow, nullptr);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
unsigned char buffer[0x80];
unsigned long length = sizeof(buffer);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
const auto rsa_result = rsa_encrypt_key( //
PBYTE(data.data()), //
data.size(), //
buffer, //
&length, //
PBYTE(hash.data()), //
hash.size(), //
&yarrow, //
prng_id, //
find_hash("sha1"), //
&new_key);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
rsa_free(&new_key);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
if (rsa_result == CRYPT_OK)
{
return std::string(PCHAR(buffer), length);
2019-09-24 05:46:47 -04:00
}
2019-09-27 16:35:57 -04:00
return {};
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
void rsa::initialize()
{
static auto initialized = false;
if (initialized) return;
initialized = true;
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
ltc_mp = ltm_desc;
register_hash(&sha1_desc);
register_prng(&yarrow_desc);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key)
{
initialize();
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string enc_data;
enc_data.resize(data.size());
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
symmetric_CBC cbc;
const auto des3 = find_cipher("3des");
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
cbc_start(des3, reinterpret_cast<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
key.size(), 0, &cbc);
cbc_encrypt(reinterpret_cast<const uint8_t*>(data.data()),
reinterpret_cast<uint8_t*>(const_cast<char*>(enc_data.data())), data.size(), &cbc);
cbc_done(&cbc);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
return enc_data;
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string des3::decrypt(const std::string& data, const std::string& iv, const std::string& key)
{
initialize();
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string dec_data;
dec_data.resize(data.size());
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
symmetric_CBC cbc;
const auto des3 = find_cipher("3des");
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
cbc_start(des3, reinterpret_cast<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
key.size(), 0, &cbc);
cbc_decrypt(reinterpret_cast<const uint8_t*>(data.data()),
reinterpret_cast<uint8_t*>(const_cast<char*>(dec_data.data())), data.size(), &cbc);
cbc_done(&cbc);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
return dec_data;
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
void des3::initialize()
{
static auto initialized = false;
if (initialized) return;
initialized = true;
register_cipher(&des3_desc);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string tiger::compute(const std::string& data, const bool hex)
{
return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string tiger::compute(const uint8_t* data, const size_t length, const bool hex)
{
uint8_t buffer[24] = {0};
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
hash_state state;
tiger_init(&state);
tiger_process(&state, data, length);
tiger_done(&state, buffer);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
return string::dump_hex(hash, "");
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string sha1::compute(const std::string& data, const bool hex)
{
return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string sha1::compute(const uint8_t* data, const size_t length, const bool hex)
{
uint8_t buffer[20] = {0};
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
hash_state state;
sha1_init(&state);
sha1_process(&state, data, length);
sha1_done(&state, buffer);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
return string::dump_hex(hash, "");
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string sha256::compute(const std::string& data, const bool hex)
{
return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string sha256::compute(const uint8_t* data, const size_t length, const bool hex)
{
uint8_t buffer[32] = {0};
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
hash_state state;
sha256_init(&state);
sha256_process(&state, data, length);
sha256_done(&state, buffer);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
return string::dump_hex(hash, "");
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string sha512::compute(const std::string& data, const bool hex)
{
return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex);
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string sha512::compute(const uint8_t* data, const size_t length, const bool hex)
{
uint8_t buffer[64] = {0};
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
hash_state state;
sha512_init(&state);
sha512_process(&state, data, length);
sha512_done(&state, buffer);
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
return string::dump_hex(hash, "");
}
2019-09-24 05:46:47 -04:00
2019-09-27 16:35:57 -04:00
unsigned int jenkins_one_at_a_time::compute(const std::string& data)
{
return compute(data.data(), data.size());
}
unsigned int jenkins_one_at_a_time::compute(const char* key, const size_t len)
{
unsigned int hash, i;
for (hash = i = 0; i < len; ++i)
2019-09-24 05:46:47 -04:00
{
2019-09-27 16:35:57 -04:00
hash += key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
2019-09-24 05:46:47 -04:00
}
2019-09-27 16:35:57 -04:00
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
2019-09-24 05:46:47 -04:00
}
}