Skip to content

Commit

Permalink
Addressing #50, optimization and fix of tohex() (#53)
Browse files Browse the repository at this point in the history
* This optimizes tohex() a fair bit
* Also fixes the link I missed in November to the old osslsignicode
  project page in the README
* Made the unit tests for hashes case-insensitive; this should capture
  the spirit of the string representation of strings better. Where it
  _truly_ matters, a case-sensitive check can explicitly be used.
* Added checks against the expected (string) length for the known hashes
* Replaced a number of the literal hashes given in the unit tests. It
  turns out the old tohex() was not just slower but also had a defect
  which caused leading '0' in the hexadecimal representation of bytes to
  disappear. The resulting strings also had irregular sizes.

Below a list of the wrong and correct string representation (duplicates
included):

6663dd7c24fa84fce7f16eb2689952c06cfa22
6663dd7c24fa84fce7f16e0b02689952c06cfa22

2559e91a60953a5e16f965f5f88953a2cca5425
2559e91a60953a5e16f9650f5f88953a2cca5425

f1c260304ec64414a97e10cb19dd4c755f9e7079f85feb38ee7ff9f938db99
f10c2600304ec64414a97e10cb19dd4c755f9e7079f85feb38ee7ff9f938db99

ddc5b39c429212745eb86a67eaa331032cc5a0dafaf6e28ec9aaf189c408d
ddc5b39c4292120745eb86a67eaa331032cc05a0dafaf6e28ec9aa0f189c408d

6f7ac8c1754fad04fba2a552a122e7
6f7ac8c17504fad04fba2a552a122e07

4ba4c91418e28cb63b97cfde1cff95a91139
4ba40c91418e28cb630b97cfde1cff0905a91139

e260f8a57faa823453bd9552506878fcbfb33203d9b606cb9a27e605a8d7b
e260f8a57faa823453bd95525068780fcbfb0332003d9b606cb9a27e605a8d7b

6663dd7c24fa84fce7f16eb2689952c06cfa22
6663dd7c24fa84fce7f16e0b02689952c06cfa22

ea13992f99840f76dcac225dd1262edcec3254511b250a6d1e98d99fc48f815
ea013992f99840f76dcac225dd1262edcec3254511b250a6d1e98d99fc48f815

ea235b77d552633c5a38974cef0e2b5
ea0235b77d552633c5a38974cef0e2b5

2559e91a60953a5e16f965f5f88953a2cca5425
2559e91a60953a5e16f9650f5f88953a2cca5425

5c823491c5991914aec971d9456d93d6cf2b8ee7e0ed7abcb7731d8ec073c0
5c823491c5991914aec971d9456d93d6cf2b8ee7e0ed7abc0b77031d8ec073c0
  • Loading branch information
hugmyndakassi authored Jan 28, 2022
1 parent 104388d commit e72f495
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 23 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ Other available solutions are deficient:

* WINE implements most of `Wintrust`, but is a massive (and arguably non-native) dependency
for a single task.
* [`osslsigncode`](https://sourceforge.net/projects/osslsigncode/) can add signatures and check
timestamps, but is long-abandoned and CLI-focused.
* [`osslsigncode`](https://github.com/mtrojnar/osslsigncode) can add signatures and check
timestamps, but is CLI-focused.

## Beware!

Expand Down
15 changes: 9 additions & 6 deletions src/uthenticode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,21 @@ static inline std::size_t round(std::size_t x, std::size_t factor) {
* @return the hex string
*/
static inline std::string tohex(std::uint8_t *buf, std::size_t len) {
if (buf == nullptr) {
constexpr static char lookup_table[] = "0123456789ABCDEF";

if (!buf || !len) {
return {};
}

std::stringstream ss;
ss << std::hex << std::setw(2) << std::setfill('0');
std::string hexstr;
hexstr.reserve(len * 2); // each byte creates two hex digits

for (std::size_t i = 0; i < len; ++i) {
ss << static_cast<int>(buf[i]);
for (auto i = 0; i < len; i++) {
hexstr += lookup_table[buf[i] >> 4];
hexstr += lookup_table[buf[i] & 0xF];
}

return ss.str();
return hexstr;
}

/**
Expand Down
20 changes: 14 additions & 6 deletions test/signeddata-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ TEST_F(Auth32Test, SignedData_properties) {

auto checksum = signed_data->get_checksum();
ASSERT_EQ(std::get<uthenticode::checksum_kind>(checksum), uthenticode::checksum_kind::SHA1);
ASSERT_EQ(std::get<std::string>(checksum), "6663dd7c24fa84fce7f16eb2689952c06cfa22");
auto const checksumstr = std::get<std::string>(checksum);
ASSERT_EQ(checksumstr.size(), 40);
ASSERT_STRCASEEQ(checksumstr.c_str(), "6663dd7c24fa84fce7f16e0b02689952c06cfa22");

ASSERT_EQ(signed_data->get_nested_signed_data(), std::nullopt);
}
Expand All @@ -36,7 +38,9 @@ TEST_F(Auth32PlusTest, SignedData_properties) {

auto checksum = signed_data->get_checksum();
ASSERT_EQ(std::get<uthenticode::checksum_kind>(checksum), uthenticode::checksum_kind::SHA1);
ASSERT_EQ(std::get<std::string>(checksum), "2559e91a60953a5e16f965f5f88953a2cca5425");
auto const checksumstr = std::get<std::string>(checksum);
ASSERT_EQ(checksumstr.size(), 40);
ASSERT_STRCASEEQ(checksumstr.c_str(), "2559e91a60953a5e16f9650f5f88953a2cca5425");

ASSERT_EQ(signed_data->get_nested_signed_data(), std::nullopt);
}
Expand All @@ -59,8 +63,10 @@ TEST_F(AuthNest32Test, SignedData_properties_nested) {

auto checksum = nested_signed_data->get_checksum();
ASSERT_EQ(std::get<uthenticode::checksum_kind>(checksum), uthenticode::checksum_kind::SHA256);
ASSERT_EQ(std::get<std::string>(checksum),
"f1c260304ec64414a97e10cb19dd4c755f9e7079f85feb38ee7ff9f938db99");
auto const checksumstr = std::get<std::string>(checksum);
ASSERT_EQ(checksumstr.size(), 64);
ASSERT_STRCASEEQ(checksumstr.c_str(),
"f10c2600304ec64414a97e10cb19dd4c755f9e7079f85feb38ee7ff9f938db99");
}

TEST_F(AuthNest32PlusTest, SignedData_properties_nested) {
Expand All @@ -81,6 +87,8 @@ TEST_F(AuthNest32PlusTest, SignedData_properties_nested) {

auto checksum = nested_signed_data->get_checksum();
ASSERT_EQ(std::get<uthenticode::checksum_kind>(checksum), uthenticode::checksum_kind::SHA256);
ASSERT_EQ(std::get<std::string>(checksum),
"ddc5b39c429212745eb86a67eaa331032cc5a0dafaf6e28ec9aaf189c408d");
auto const checksumstr = std::get<std::string>(checksum);
ASSERT_EQ(checksumstr.size(), 64);
ASSERT_STRCASEEQ(checksumstr.c_str(),
"ddc5b39c4292120745eb86a67eaa331032cc05a0dafaf6e28ec9aa0f189c408d");
}
30 changes: 21 additions & 9 deletions test/uthenticode-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,41 +57,53 @@ TEST_F(NoAuthTest, calculate_checksum) {
EXPECT_TRUE(unk.empty());

auto md5 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::MD5);
EXPECT_EQ(md5, "6f7ac8c1754fad04fba2a552a122e7");
EXPECT_EQ(md5.size(), 32);
EXPECT_STRCASEEQ(md5.c_str(), "6f7ac8c17504fad04fba2a552a122e07");

auto sha1 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::SHA1);
EXPECT_EQ(sha1, "4ba4c91418e28cb63b97cfde1cff95a91139");
EXPECT_EQ(sha1.size(), 40);
EXPECT_STRCASEEQ(sha1.c_str(), "4ba40c91418e28cb630b97cfde1cff0905a91139");

auto sha256 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::SHA256);
EXPECT_EQ(sha256, "e260f8a57faa823453bd9552506878fcbfb33203d9b606cb9a27e605a8d7b");
EXPECT_EQ(sha256.size(), 64);
EXPECT_STRCASEEQ(sha256.c_str(),
"e260f8a57faa823453bd95525068780fcbfb0332003d9b606cb9a27e605a8d7b");
}

TEST_F(Auth32Test, calculate_checksum) {
auto unk = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::UNKNOWN);
EXPECT_TRUE(unk.empty());

auto md5 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::MD5);
EXPECT_EQ(md5, "64c29391b57679b2973ac562cf64685d");
EXPECT_EQ(md5.size(), 32);
EXPECT_STRCASEEQ(md5.c_str(), "64c29391b57679b2973ac562cf64685d");

auto sha1 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::SHA1);
EXPECT_EQ(sha1, "6663dd7c24fa84fce7f16eb2689952c06cfa22");
EXPECT_EQ(sha1.size(), 40);
EXPECT_STRCASEEQ(sha1.c_str(), "6663dd7c24fa84fce7f16e0b02689952c06cfa22");

auto sha256 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::SHA256);
EXPECT_EQ(sha256, "ea13992f99840f76dcac225dd1262edcec3254511b250a6d1e98d99fc48f815");
EXPECT_EQ(sha256.size(), 64);
EXPECT_STRCASEEQ(sha256.c_str(),
"ea013992f99840f76dcac225dd1262edcec3254511b250a6d1e98d99fc48f815");
}

TEST_F(Auth32PlusTest, calculate_checksum) {
auto unk = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::UNKNOWN);
EXPECT_TRUE(unk.empty());

auto md5 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::MD5);
EXPECT_EQ(md5, "ea235b77d552633c5a38974cef0e2b5");
EXPECT_EQ(md5.size(), 32);
EXPECT_STRCASEEQ(md5.c_str(), "ea0235b77d552633c5a38974cef0e2b5");

auto sha1 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::SHA1);
EXPECT_EQ(sha1, "2559e91a60953a5e16f965f5f88953a2cca5425");
EXPECT_EQ(sha1.size(), 40);
EXPECT_STRCASEEQ(sha1.c_str(), "2559e91a60953a5e16f9650f5f88953a2cca5425");

auto sha256 = uthenticode::calculate_checksum(pe, uthenticode::checksum_kind::SHA256);
EXPECT_EQ(sha256, "5c823491c5991914aec971d9456d93d6cf2b8ee7e0ed7abcb7731d8ec073c0");
EXPECT_EQ(sha256.size(), 64);
EXPECT_STRCASEEQ(sha256.c_str(),
"5c823491c5991914aec971d9456d93d6cf2b8ee7e0ed7abc0b77031d8ec073c0");
}

TEST(verify, handles_nullptr) {
Expand Down

0 comments on commit e72f495

Please sign in to comment.