Hi everyone,
I'm trying to write a little C++ wrapper around the PolarSLL SHA-512 / 384 implementation, the source code of which you can view here:
https://polarssl.org/sha-512-source-code
The problem I'm having is that the length of the digest is not always 64 bytes (for sha512) or 49 bytes (for sha384) as it's supposed to be, it often is, but not always - which is kind of weird.
I have pretty much used the code as it is on PolarSSL's website, except for wrapping it in an "impl" namespace. I also ran the self_tests, which all passed.
Here's the code I'm using to wrap the PolarSSL implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
namespace {
void sha4(const std::string& input, const sha_t& type, std::string& result)
{
bool is_384 = (type == sha_t::SHA_384);
const unsigned char* in = reinterpret_cast<const unsigned char*>(input.c_str());
unsigned char result_buffer[64];
//Actual call to the PolarSSL function:
impl::sha4(in, input.size(), result_buffer, static_cast<int>(is_384));
//If we don't null-terminate the buffers, the hash will be
//different every time because of trailing garbage values.
if (is_384)
result_buffer[48] = '\0';
else
result_buffer[63] = '\0';
std::ostringstream oss;
oss << result_buffer;
result = oss.str();
}
std::string to_hex(const std::string& input)
{
std::ostringstream osstream;
static char const hex_table[17] = "0123456789abcdef";
for (const char& c : input)
{
if (c != '\0')
{
int current_char = static_cast<int>(c);
//first hex character
osstream << hex_table[(current_char >> 4) & 0xF]
//second hex character
<< hex_table[current_char & 0xF];
}
}
return osstream.str();
}
}//anonymous namespace
std::string sha512(const std::string& input)
{
std::string result;
sha4(input, sha_t::SHA_512, result);
return result;
}
std::string sha512_hex(const std::string& input)
{
return to_hex(sha512(input));
}
std::string sha384(const std::string& input)
{
std::string result;
sha4(input, sha_t::SHA_384, result);
return result;
}
std::string sha384_hex(const std::string& input)
{
return to_hex(sha384(input));
}
|
When I run a test for sha384 using single characters and hex output (so I expect (48*2=)96 total characters in the output), here's what I get:
a / 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31 / 96
b / 98a906182cdcfb1eb4eb471176 / 26
c / 40f98a05660bf871802ee59964de1945bd731a45cc7f48e4dadd92f34a7eeec089e149ad8c2434f11792e588b740d997 / 96
d / 8ac10705a78a2dcd15fa577bac70762708597a02e130d8a6192d73dababd2b14502dbeee29d0e22bc341a0c42af6a4fb / 96
e / 8d182905e535537a32cc0c475403d1fe78ee541a40d61e0b306d7541ed8dbb63d550dab383d0fca0e23448af99bffe10 / 96
f / 3a31ca443b6cae3717b4a4f19972bc92413645380e4990e4fe4dc322386494fadaa2b63b4f62be6e2b7077e982bb7ada / 96
g / 400351f8d278fdf7e765ccb2943e8a99548a68ae0235b96fa47cb758a354ddd1201d034199439c49ff22cfc0904bc2e2 / 96
h / a4eb0778c79fce94c02126543cba398d645b2fd4c6ff6a02eecc026bbe0cc0dd666279722b7615bc15b4c9126b941c04 / 96
i / 2051ff7a91bcc6245fe7c3c4bdfcb0538553f73c54100c686a6fc0279354d12ecb4b7589a60a516c4fabadbeb622f397 / 96
j / 417316736caf4fc0f2a09f5d6e4c90d78b768fe08add82c5db9f0a22809bd6a719e3ad367f149d92b5455e952b79613b / 96
k / 81deaf76b8f3d7c9c58bb0ed5f83962c136ea4c5dd075272072843a8283a096a58e2b5199f32d4b2e37f0bbb953c7a09 / 96
l / 1ad0ee901a40bf4536640f4f0c8c2b9fca9f5fbac283fd6dc4d1fd7021f8ca66c69c399619921f6dec5a2d9d942bc7ac / 96
m / 7857a47542aca03c22c39461231a919d9904a5915937278535a41291791b96c06717638cd6b0a2e5b8a20a53ec980f57 / 96
n / a87d8f7ff9267bad515057f7a7f772c469d2536b70f1e8e770f9a5581922b986520a3d71d952f30593bcfa2318bfeb0d / 96
o / 1d587bbe50d4aef51f2ea3743f3c6f849a16e6c2cfe711029e5e202ab3484b0d6ed8de1e2c / 74
p / 049e7caf67d83409ea363e89c09d67c7f1fd1bd679016ad9f422830ef105435e12a4c2dcad5a9e5a9602924d479574dc / 96
q / 081de7624429ffbb0cd03c81da55df6fc8e36d09406bc581aa78c84742fdf45f58d999adb87f89740d2a4f88aaf38209 / 96
r / 75d37880e899ba856e8504e8588796691b90dd93853e7e4507c68d9941dbddf430663b0ed30942f3d3d7f986e5989efe / 96
s / 5335f048bddebe600ae6edb89b36da3a2d7c18bc53b83e2fa577cc9a4f262fc1c3741830955303a0158e7d48be7965f8 / 96
t / e7cdceeaff40fcf3eb07011b4facb47e6c06f82d243289ca9e598282f1e58ea4ee2378d5772c26e926ecbffba13f6d53 / 96
u / 8b / 2
v / 4c52ccee / 8
w / f99557d0ede293bde12229d548d97d77b548d3659852cb45672fbfdd4431397760b2fd6d23b04a08680ec9d030b83579 / 96
x / d752c2c51fba0e29aa190570a9d4253e44077a058d3297fa3a5630d5bd012622f97c28acaed313b5c83bb990caa7da85 / 96
y / 883c52bd6105dadf36411ccbc5b3b19f9926f3ffacbf0275b3b7ed6e1228aff6c5585a2e77f1e8fdef6a23e31b838cf6 / 96
z / c39c06ca383f11c2870c8ea1368e861cee29dde246368c17b6985f7a7d650d86a90aa8bbb176ddbd99f06d490f0495e5 / 96
? / / 0
! / 1d0ec8c84ee9521e21f06774de232367b64de628474cb5b2e372b699a1f55ae335cc37193ef823e33324dfd9a70738a6 / 96
{ / 95ed401953c1d4c284ee689b77a75356c6b92a4095bace5f611aace86c4dc41925fdcf / 70
} / 1f366c84945e30278b3f85a80ca9cfa193ed5adabe117789ee08eff673779cd4fb1f881ec98505672ead70b402190554 / 96
[ / cf1e1cb005d298b1782c988946d3a2d3d08e4021bcc81669d1d22cb470f48e4282eb639f8fa4f7badb4f8ad93f556124 / 96
] / af03681360120cccd5c2c6050bcbe74806c6b5454b9ff1c946058c944638adfaa4652dadaafea6ad964c0c16a53deebe / 96
|
When I do a strchr() for '\0' on the original (non-hex) values, the pointer position returned is the same as the checksums length, so I'm wondering if perhaps the sha4 implementation would shift bits around and one of them happens to become a '\0', null terminating the hash early?
I'm not too strong on C, nor cryptography, nor C++ for that matter, so any help at all would be greatly appreciated. Please let me know if you require any additional information.
All the best,
NwN