Skip to content

Commit

Permalink
Merge pull request #43 from xtuml/hash-utils
Browse files Browse the repository at this point in the history
Add Hash domain
  • Loading branch information
leviathan747 authored Mar 5, 2024
2 parents b71186a + 8e2b9b1 commit 9e0bfbf
Show file tree
Hide file tree
Showing 6 changed files with 403 additions and 0 deletions.
1 change: 1 addition & 0 deletions utils/Hash_OOA/Hash.int
54 changes: 54 additions & 0 deletions utils/Hash_OOA/Hash.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
domain Hash is

exception HashException;

public type Algorithm is enum(
MD5, SHA1,
SHA224, SHA256, SHA384, SHA512,
SHA3_224, SHA3_256, SHA3_384, SHA3_512 );

public type Hash is sequence of byte;
public type Key is sequence of byte;

//! Returns the cryptographic hash of the input bytes using the supplied algorithm
public service hash (
algorithm : in Algorithm,
input : in anonymous sequence of anonymous byte ) return Hash;

//! Returns the cryptographic hash of the input string using the supplied algorithm
public service hash (
algorithm : in Algorithm,
input : in anonymous string ) return Hash;

//! Returns the cryptographic hash of the input file using the supplied algorithm
public service hash (
algorithm : in Algorithm,
input : in anonymous device ) return Hash;

//! Returns the HMAC code of the input bytes using the supplied key and algorithm
public service hmac (
algorithm : in Algorithm,
key : in Key,
input : in anonymous sequence of anonymous byte ) return Hash;

//! Returns the HMAC code of the input string using the supplied key and algorithm
public service hmac (
algorithm : in Algorithm,
key : in Key,
input : in anonymous string ) return Hash;

//! Returns the HMAC code of the input file using the supplied key and algorithm
public service hmac (
algorithm : in Algorithm,
key : in Key,
input : in anonymous device ) return Hash;

//! Returns a non-cryptographic hash of the input bytes using the XXH3 algorithm
//! See http://fastcompression.blogspot.com/2019/03/presenting-xxh3.html
public service hash_xxh3 ( input : in anonymous sequence of anonymous byte ) return long_integer;

//! Returns a non-cryptographic hash of the input string using the XXH3 algorithm
//! See http://fastcompression.blogspot.com/2019/03/presenting-xxh3.html
public service hash_xxh3 ( input : in anonymous string ) return long_integer;

end domain;
22 changes: 22 additions & 0 deletions utils/Hash_OOA/custom/custom.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
find_package(OpenSSL REQUIRED)
find_package(xxHash REQUIRED)
find_package(Boost REQUIRED headers)
include(GoogleTest)
find_package(GTest CONFIG REQUIRED)

target_sources( Hash PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/Hash_services.cc )
target_link_libraries(Hash PRIVATE openssl::openssl xxHash::xxhash )


simple_add_executable(
NAME testHash
SOURCES
test_hash.cc
LINKS
Hash
Boost::headers
GTest::gtest_main
)

gtest_add_tests(TARGET testHash)

214 changes: 214 additions & 0 deletions utils/Hash_OOA/custom/src/Hash_services.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// ----------------------------------------------------------------------------
// (c) 2024 - CROWN OWNED COPYRIGHT. All rights reserved.
// The copyright of this Software is vested in the Crown
// and the Software is the property of the Crown.
// ----------------------------------------------------------------------------
// Classification: UK OFFICIAL
// ----------------------------------------------------------------------------

#include "Hash_OOA/__Hash_services.hh"
#include "Hash_OOA/__Hash_types.hh"
#include "Hash_OOA/__Hash__HashException.hh"
#include "swa/Sequence.hh"
#include "swa/String.hh"
#include <openssl/err.h>
#include <openssl/evp.h>

#include <xxhash.h>

namespace masld_Hash {


std::shared_ptr <EVP_MD> get_digest(maslt_Algorithm algorithm) {

static const std::array<std::shared_ptr < EVP_MD>, maslt_Algorithm::index_masle_SHA3_512 + 1 > evp_digests = {
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "MD5", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA1", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA224", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA256", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA384", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA512", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA3-224", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA3-256", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA3-384", nullptr), EVP_MD_free},
std::shared_ptr < EVP_MD > {EVP_MD_fetch(nullptr, "SHA3-512", nullptr), EVP_MD_free}};

return evp_digests[algorithm.getIndex()];
}

void checkErrors(int status) {
if (status != 1) {
std::string message;
ERR_print_errors_cb([](const char *str, std::size_t len, void *ctx) {
static_cast<std::string *>(ctx)->append(str, len);
return 1;
}, &message);
throw masld_Hash::maslex_HashException(message);
}
}


class Hasher {

private:
std::shared_ptr <EVP_MD_CTX> context{EVP_MD_CTX_new(), EVP_MD_CTX_free};
std::shared_ptr <EVP_MD> digest;
public:
Hasher(maslt_Algorithm algorithm) : digest(get_digest(algorithm)) {
checkErrors(EVP_DigestInit_ex(context.get(), digest.get(), nullptr));

}

template<typename Buffer>
requires(std::ranges::contiguous_range<Buffer>
&& std::ranges::sized_range <Buffer>)

void update(const Buffer &input) {
checkErrors(EVP_DigestUpdate(context.get(), std::ranges::cdata(input),
std::ranges::size(input) * sizeof(std::ranges::range_value_t < Buffer > )));

}

std::vector<unsigned char> hash() {
std::vector<unsigned char> result(EVP_MD_CTX_size(context.get()));
checkErrors(EVP_DigestFinal_ex(context.get(), result.data(), nullptr));
return result;
}
};

class HMACHasher {

private:
std::shared_ptr <EVP_MD_CTX> context{EVP_MD_CTX_new(), EVP_MD_CTX_free};
std::shared_ptr <EVP_MD> digest;
std::shared_ptr <EVP_PKEY> key;
public:
template<typename Key>
requires (std::ranges::contiguous_range<Key>
&&
std::ranges::sized_range <Key> &&requires{
sizeof(std::ranges::range_value_t < Key > ) == 1;
}
)

HMACHasher(maslt_Algorithm algorithm, const Key &key) :
digest(get_digest(algorithm)),
key(EVP_PKEY_new_mac_key(
EVP_PKEY_HMAC,
nullptr,
reinterpret_cast<const unsigned char *>(std::ranges::data(key)),
std::ranges::size(key)),
EVP_PKEY_free) {
checkErrors(EVP_DigestSignInit(context.get(), nullptr, digest.get(), nullptr, this->key.get()));

}

template<typename Buffer>
requires std::ranges::contiguous_range<Buffer>
&&

std::ranges::sized_range <Buffer>
void update(const Buffer &input) {
checkErrors(EVP_DigestSignUpdate(context.get(), std::ranges::cdata(input),
std::ranges::size(input) *
sizeof(std::ranges::range_value_t < Buffer > )));

}

std::vector<unsigned char> hash() {
std::size_t size = EVP_MD_CTX_size(context.get());
std::vector<unsigned char> result(size);
checkErrors(EVP_DigestSignFinal(context.get(), result.data(), &size));
return result;
}
};

template<class Function>
void process_stream(std::istream &input, Function function) {
static const std::size_t maxReadSize = 4 * 1024 * 1024;

std::ios::pos_type cur_pos = input.tellg();
input.seekg(0, std::ios::end);
std::ios::pos_type end_pos = input.tellg();
input.seekg(cur_pos);

std::size_t remaining = end_pos - cur_pos;
std::vector<char> buffer;
buffer.reserve(std::min(maxReadSize, remaining));

while (input && remaining) {
std::size_t to_read = std::min(buffer.capacity(), remaining);
buffer.resize(to_read);
input.read(buffer.data(), to_read);
remaining -= to_read;

function(buffer);

}

}


maslt_Hash masls_hash(const maslt_Algorithm &maslp_algorithm,
const ::SWA::Sequence <uint8_t> &maslp_input) {
Hasher hasher{maslp_algorithm};
hasher.update(maslp_input.getData());
return hasher.hash();
}

maslt_Hash masls_overload1_hash(const maslt_Algorithm &maslp_algorithm,
const ::SWA::String &maslp_input) {
Hasher hasher{maslp_algorithm};
hasher.update(maslp_input.s_str());
return hasher.hash();
}

maslt_Hash masls_overload2_hash(const maslt_Algorithm &maslp_algorithm,
const ::SWA::Device &maslp_input) {
Hasher hasher{maslp_algorithm};
process_stream(*maslp_input.getInputStream(), [&hasher](const std::vector<char> &buffer) {
hasher.update(buffer);
});
return hasher.hash();

}

maslt_Hash masls_hmac(const maslt_Algorithm &maslp_algorithm,
const ::SWA::Sequence <uint8_t> &maslp_key,
const ::SWA::Sequence <uint8_t> &maslp_input) {
HMACHasher hasher{maslp_algorithm, maslp_key.getData()};
hasher.
update(maslp_input.getData());
return hasher.

hash();
}

maslt_Hash masls_overload1_hmac(const maslt_Algorithm &maslp_algorithm,
const ::SWA::Sequence <uint8_t> &maslp_key,
const ::SWA::String &maslp_input) {
HMACHasher hasher{maslp_algorithm, maslp_key.getData()};
hasher.update(maslp_input.s_str());
return hasher.hash();
}

maslt_Hash masls_overload2_hmac(const maslt_Algorithm &maslp_algorithm,
const ::SWA::Sequence <uint8_t> &maslp_key,
const ::SWA::Device &maslp_input) {
HMACHasher hasher{maslp_algorithm, maslp_key.getData()};
process_stream(*maslp_input.getInputStream(), [&hasher](const std::vector<char> &buffer) {
hasher.update(buffer);
});
return hasher.hash();

}
int64_t masls_hash_xxh3 ( const ::SWA::Sequence<uint8_t>& maslp_input ) {
return std::bit_cast<int64_t,uint64_t>(XXH3_64bits(maslp_input.getData().data(), maslp_input.size()));
}

int64_t masls_overload1_hash_xxh3 ( const ::SWA::String& maslp_input ) {
return std::bit_cast<int64_t,uint64_t>(XXH3_64bits(maslp_input.s_str().data(), maslp_input.size()));
}


}
Loading

0 comments on commit 9e0bfbf

Please sign in to comment.