-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
353 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,352 @@ | ||
// Copyright 2024 Matt Borland | ||
// Distributed under the Boost Software License, Version 1.0. | ||
// https://www.boost.org/LICENSE_1_0.txt | ||
|
||
#include <boost/crypt/hash/sha224.hpp> | ||
#include <boost/core/lightweight_test.hpp> | ||
#include "generate_random_strings.hpp" | ||
#include <random> | ||
#include <iostream> | ||
#include <string> | ||
#include <array> | ||
#include <tuple> | ||
#include <fstream> | ||
#include <cstdlib> | ||
#include <ctime> | ||
#include <cstring> | ||
|
||
constexpr std::array<std::tuple<const char*, boost::crypt::sha224_hasher::return_type>, 4> test_values = | ||
{ | ||
std::make_tuple("a", | ||
boost::crypt::sha224_hasher::return_type{0xab, 0xd3, 0x75, 0x34, 0xc7, 0xd9, 0xa2, 0xef, 0xb9, 0x46, 0x5d, 0xe9, 0x31, 0xcd, 0x70, 0x55, 0xff, 0xdb, 0x88, 0x79, 0x56, 0x3a, 0xe9, 0x80, 0x78, 0xd6, 0xd6, 0xd5}), | ||
std::make_tuple("The quick brown fox jumps over the lazy dog", | ||
boost::crypt::sha224_hasher::return_type{0x73, 0x0e, 0x10, 0x9b, 0xd7, 0xa8, 0xa3, 0x2b, 0x1c, 0xb9, 0xd9, 0xa0, 0x9a, 0xa2, 0x32, 0x5d, 0x24, 0x30, 0x58, 0x7d, 0xdb, 0xc0, 0xc3, 0x8b, 0xad, 0x91, 0x15, 0x25}), | ||
std::make_tuple("The quick brown fox jumps over the lazy dog.", | ||
boost::crypt::sha224_hasher::return_type{0x61, 0x9c, 0xba, 0x8e, 0x8e, 0x05, 0x82, 0x6e, 0x9b, 0x8c, 0x51, 0x9c, 0x0a, 0x5c, 0x68, 0xf4, 0xfb, 0x65, 0x3e, 0x8a, 0x3d, 0x8a, 0xa0, 0x4b, 0xb2, 0xc8, 0xcd, 0x4c}), | ||
std::make_tuple("", | ||
boost::crypt::sha224_hasher::return_type {0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3, 0xe4, 0x2f}) | ||
}; | ||
|
||
void basic_tests() | ||
{ | ||
for (const auto& test_value : test_values) | ||
{ | ||
const auto message_result {boost::crypt::sha224(std::get<0>(test_value))}; | ||
const auto valid_result {std::get<1>(test_value)}; | ||
for (std::size_t i {}; i < message_result.size(); ++i) | ||
{ | ||
if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) | ||
{ | ||
// LCOV_EXCL_START | ||
std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; | ||
break; | ||
// LCOV_EXCL_STOP | ||
} | ||
} | ||
} | ||
} | ||
|
||
void string_test() | ||
{ | ||
for (const auto& test_value : test_values) | ||
{ | ||
const std::string string_message {std::get<0>(test_value)}; | ||
const auto message_result {boost::crypt::sha224(string_message)}; | ||
const auto valid_result {std::get<1>(test_value)}; | ||
for (std::size_t i {}; i < message_result.size(); ++i) | ||
{ | ||
if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) | ||
{ | ||
// LCOV_EXCL_START | ||
std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; | ||
break; | ||
// LCOV_EXCL_STOP | ||
} | ||
} | ||
} | ||
} | ||
|
||
void string_view_test() | ||
{ | ||
#ifdef BOOST_CRYPT_HAS_STRING_VIEW | ||
for (const auto& test_value : test_values) | ||
{ | ||
const std::string string_message {std::get<0>(test_value)}; | ||
const std::string_view string_view_message {string_message}; | ||
const auto message_result {boost::crypt::sha224(string_view_message)}; | ||
const auto valid_result {std::get<1>(test_value)}; | ||
for (std::size_t i {}; i < message_result.size(); ++i) | ||
{ | ||
if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) | ||
{ | ||
// LCOV_EXCL_START | ||
std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; | ||
break; | ||
// LCOV_EXCL_STOP | ||
} | ||
} | ||
} | ||
#endif | ||
} | ||
|
||
void bad_input() | ||
{ | ||
const auto null_message {boost::crypt::sha224(static_cast<const char*>(nullptr))}; | ||
BOOST_TEST_EQ(null_message[0], 0x0); | ||
BOOST_TEST_EQ(null_message[1], 0x0); | ||
BOOST_TEST_EQ(null_message[2], 0x0); | ||
BOOST_TEST_EQ(null_message[3], 0x0); | ||
|
||
const auto null_message_len {boost::crypt::sha224(static_cast<const char*>(nullptr), 100)}; | ||
BOOST_TEST_EQ(null_message_len[0], 0x0); | ||
BOOST_TEST_EQ(null_message_len[1], 0x0); | ||
BOOST_TEST_EQ(null_message_len[2], 0x0); | ||
BOOST_TEST_EQ(null_message_len[3], 0x0); | ||
|
||
const auto unsigned_null_message {boost::crypt::sha224(static_cast<const std::uint8_t*>(nullptr))}; | ||
BOOST_TEST_EQ(unsigned_null_message[0], 0x0); | ||
BOOST_TEST_EQ(unsigned_null_message[1], 0x0); | ||
BOOST_TEST_EQ(unsigned_null_message[2], 0x0); | ||
BOOST_TEST_EQ(unsigned_null_message[3], 0x0); | ||
|
||
const auto unsigned_null_message_len {boost::crypt::sha224(static_cast<const std::uint8_t*>(nullptr), 100)}; | ||
BOOST_TEST_EQ(unsigned_null_message_len[0], 0x0); | ||
BOOST_TEST_EQ(unsigned_null_message_len[1], 0x0); | ||
BOOST_TEST_EQ(unsigned_null_message_len[2], 0x0); | ||
BOOST_TEST_EQ(unsigned_null_message_len[3], 0x0); | ||
|
||
std::string test_str {"Test string"}; | ||
const auto reveresed_input {boost::crypt::detail::sha224(test_str.end(), test_str.begin())}; | ||
BOOST_TEST_EQ(reveresed_input[0], 0x0); | ||
BOOST_TEST_EQ(reveresed_input[1], 0x0); | ||
BOOST_TEST_EQ(reveresed_input[2], 0x0); | ||
BOOST_TEST_EQ(reveresed_input[3], 0x0); | ||
} | ||
|
||
void test_class() | ||
{ | ||
boost::crypt::sha224_hasher hasher; | ||
|
||
for (const auto& test_value : test_values) | ||
{ | ||
const auto msg {std::get<0>(test_value)}; | ||
hasher.process_bytes(msg, std::strlen(msg)); | ||
const auto message_result {hasher.get_digest()}; | ||
|
||
const auto valid_result {std::get<1>(test_value)}; | ||
for (std::size_t i {}; i < message_result.size(); ++i) | ||
{ | ||
if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) | ||
{ | ||
// LCOV_EXCL_START | ||
std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; | ||
break; | ||
// LCOV_EXCL_STOP | ||
} | ||
} | ||
|
||
hasher.init(); | ||
} | ||
} | ||
|
||
template <typename T> | ||
void test_file(T filename, const boost::crypt::sha224_hasher::return_type& res) | ||
{ | ||
const auto crypt_res {boost::crypt::sha224_file(filename)}; | ||
|
||
for (std::size_t j {}; j < crypt_res.size(); ++j) | ||
{ | ||
if (!BOOST_TEST_EQ(res[j], crypt_res[j])) | ||
{ | ||
// LCOV_EXCL_START | ||
std::cerr << "Failure with file: " << filename << std::endl; | ||
break; | ||
// LCOV_EXCL_STOP | ||
} | ||
} | ||
} | ||
|
||
template <typename T> | ||
void test_invalid_file(T filename) | ||
{ | ||
constexpr boost::crypt::sha224_hasher::return_type res{}; | ||
|
||
const auto crypt_res {boost::crypt::sha224_file(filename)}; | ||
|
||
for (std::size_t j {}; j < crypt_res.size(); ++j) | ||
{ | ||
if (!BOOST_TEST_EQ(res[j], crypt_res[j])) | ||
{ | ||
// LCOV_EXCL_START | ||
std::cerr << "Failure with file: " << filename << std::endl; | ||
break; | ||
// LCOV_EXCL_STOP | ||
} | ||
} | ||
} | ||
|
||
void files_test() | ||
{ | ||
// Based off where we are testing from (test vs boost_root) we need to adjust our filepath | ||
const char* filename; | ||
const char* filename_2; | ||
|
||
// Boost-root | ||
std::ifstream fd("libs/crypt/test/test_file_1.txt", std::ios::binary | std::ios::in); | ||
filename = "libs/crypt/test/test_file_1.txt"; | ||
filename_2 = "libs/crypt/test/test_file_2.txt"; | ||
|
||
// LCOV_EXCL_START | ||
if (!fd.is_open()) | ||
{ | ||
// Local test directory or IDE | ||
std::ifstream fd2("test_file_1.txt", std::ios::binary | std::ios::in); | ||
filename = "test_file_1.txt"; | ||
filename_2 = "test_file_2.txt"; | ||
|
||
if (!fd2.is_open()) | ||
{ | ||
// test/cover | ||
std::ifstream fd3("../test_file_1.txt", std::ios::binary | std::ios::in); | ||
filename = "../test_file_1.txt"; | ||
filename_2 = "../test_file_2.txt"; | ||
|
||
if (!fd3.is_open()) | ||
{ | ||
std::cerr << "Test not run due to file system issues" << std::endl; | ||
return; | ||
} | ||
else | ||
{ | ||
fd3.close(); | ||
} | ||
} | ||
else | ||
{ | ||
fd2.close(); | ||
} | ||
} | ||
else | ||
{ | ||
fd.close(); | ||
} | ||
// LCOV_EXCL_STOP | ||
|
||
// On macOS 15 | ||
// sha224 test_file_1.txt | ||
// sha224 (test_file_1.txt) = e88799b0d0d5becc6791837fa95388d4056f1250a511d14829766663 | ||
constexpr boost::crypt::sha224_hasher::return_type res{0xe8, 0x87, 0x99, 0xb0, 0xd0, 0xd5, 0xbe, 0xcc, 0x67, 0x91, 0x83, 0x7f, 0xa9, 0x53, 0x88, 0xd4, 0x05, 0x6f, 0x12, 0x50, 0xa5, 0x11, 0xd1, 0x48, 0x29, 0x76, 0x66, 0x63}; | ||
|
||
test_file(filename, res); | ||
|
||
const std::string str_filename {filename}; | ||
test_file(str_filename, res); | ||
|
||
#ifdef BOOST_CRYPT_HAS_STRING_VIEW | ||
const std::string_view str_view_filename {str_filename}; | ||
test_file(str_view_filename, res); | ||
#endif | ||
|
||
const auto invalid_filename = "broken.bin"; | ||
test_invalid_file(invalid_filename); | ||
|
||
const std::string str_invalid_filename {invalid_filename}; | ||
test_invalid_file(str_invalid_filename); | ||
|
||
#ifdef BOOST_CRYPT_HAS_STRING_VIEW | ||
const std::string_view str_view_invalid_filename {str_invalid_filename}; | ||
test_invalid_file(str_view_invalid_filename); | ||
#endif | ||
|
||
// On macOS 15 | ||
// sha224 test_file_2.txt | ||
// sha224 (test_file_2.txt) = c58605901d0923feb172e964ca6722378063574d18ff3efa7881bd91 | ||
constexpr boost::crypt::sha224_hasher::return_type res_2{0xc5, 0x86, 0x05, 0x90, 0x1d, 0x09, 0x23, 0xfe, 0xb1, 0x72, 0xe9, 0x64, 0xca, 0x67, 0x22, 0x37, 0x80, 0x63, 0x57, 0x4d, 0x18, 0xff, 0x3e, 0xfa, 0x78, 0x81, 0xbd, 0x91}; | ||
|
||
test_file(filename_2, res_2); | ||
|
||
const char* test_null_file = nullptr; | ||
test_invalid_file(test_null_file); | ||
} | ||
|
||
void test_invalid_state() | ||
{ | ||
boost::crypt::sha224_hasher hasher; | ||
auto current_state = hasher.process_bytes("test", 4); | ||
BOOST_TEST(current_state == boost::crypt::hasher_state::success); | ||
|
||
hasher.get_digest(); | ||
|
||
const auto bad_state = hasher.process_bytes("test", 4); | ||
BOOST_TEST(bad_state == boost::crypt::hasher_state::state_error); | ||
|
||
const auto digest = hasher.get_digest(); | ||
|
||
for (const auto& val : digest) | ||
{ | ||
BOOST_TEST_EQ(val, static_cast<std::uint8_t>(0)); | ||
} | ||
|
||
hasher.init(); | ||
|
||
current_state = hasher.process_bytes("test", 4); | ||
BOOST_TEST(current_state == boost::crypt::hasher_state::success); | ||
current_state = hasher.process_byte(0x03); | ||
BOOST_TEST(current_state == boost::crypt::hasher_state::success); | ||
const char* ptr = nullptr; | ||
current_state = hasher.process_bytes(ptr, 4); | ||
BOOST_TEST(current_state == boost::crypt::hasher_state::null); | ||
|
||
const char16_t* ptr16 = nullptr; | ||
current_state = hasher.process_bytes(ptr16, 4); | ||
BOOST_TEST(current_state == boost::crypt::hasher_state::null); | ||
|
||
const char32_t* ptr32 = nullptr; | ||
current_state = hasher.process_bytes(ptr32, 4); | ||
BOOST_TEST(current_state == boost::crypt::hasher_state::null); | ||
|
||
const wchar_t* wptr = nullptr; | ||
current_state = hasher.process_bytes(wptr, 4); | ||
BOOST_TEST(current_state == boost::crypt::hasher_state::null); | ||
} | ||
|
||
// This ends up being completely calculated in a constexpr fashion so Codecov complains | ||
// LCOV_EXCL_START | ||
void test_span() | ||
{ | ||
#ifdef BOOST_CRYPT_HAS_SPAN | ||
|
||
// "abc" in hex | ||
const std::byte vals[] = {std::byte{0x61}, std::byte{0x62}, std::byte{0x63}}; | ||
std::span<const std::byte> byte_span {vals}; | ||
const auto expected_res = boost::crypt::sha224_hasher::return_type{0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7}; | ||
const auto res = boost::crypt::sha224(byte_span); | ||
|
||
for (std::size_t i {}; i < res.size(); ++i) | ||
{ | ||
BOOST_TEST_EQ(res[i], expected_res[i]); | ||
} | ||
|
||
#endif // BOOST_CRYPT_HAS_SPAN | ||
} | ||
// LCOV_EXCL_STOP | ||
|
||
int main() | ||
{ | ||
basic_tests(); | ||
string_test(); | ||
string_view_test(); | ||
bad_input(); | ||
test_class(); | ||
|
||
// The Windows file system returns a different result than on UNIX platforms | ||
#if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) | ||
files_test(); | ||
#endif | ||
|
||
test_invalid_state(); | ||
|
||
test_span(); | ||
|
||
return boost::report_errors(); | ||
} |