EHS/src/SHA256.cpp
Karutoh bce48fe121
All checks were successful
Build & Release / Windows-AMD64-Build (push) Successful in 6m9s
Build & Release / Linux-AMD64-Build (push) Successful in 15m26s
Build & Release / Linux-AARCH64-Build (push) Successful in 45m54s
Fixed "System::OpenURI". Added SHA256. Added URI safe Base64 methods.
2025-05-11 19:43:50 -07:00

210 lines
5.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ehs/SHA256.h"
#include "ehs/Util.h"
namespace ehs
{
UInt_32 SHA256::ROTR(const UInt_32 x, const UInt_32 n)
{
return (x >> n) | (x << (32 - n));
}
UInt_32 SHA256::CH(const UInt_32 x, const UInt_32 y, const UInt_32 z)
{
return (x & y) ^ (~x & z);
}
UInt_32 SHA256::MAJ(const UInt_32 x, const UInt_32 y, const UInt_32 z)
{
return (x & y) ^ (x & z) ^ (y & z);
}
UInt_32 SHA256::EP0(const UInt_32 x)
{
return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22);
}
UInt_32 SHA256::EP1(const UInt_32 x)
{
return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25);
}
UInt_32 SHA256::SIG0(const UInt_32 x)
{
return ROTR(x, 7) ^ ROTR(x, 18) ^ (x >> 3);
}
UInt_32 SHA256::SIG1(const UInt_32 x)
{
return ROTR(x,17) ^ ROTR(x, 19) ^ (x >> 10);
}
SHA256::SHA256()
: state{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19},
bitLen(0), data{}, dataLen(0)
{
}
SHA256::SHA256(SHA256&& other) noexcept
: state{}, bitLen(0), data{}, dataLen(0)
{
Util::Copy(state, other.state, sizeof(state) / sizeof(UInt_32));
bitLen = other.bitLen;
Util::Copy(data, other.data, sizeof(data));
dataLen = other.dataLen;
Util::Zero(other.state, sizeof(state) / sizeof(UInt_32));
other.bitLen = 0;
Util::Zero(other.data, sizeof(data));
other.dataLen = 0;
}
SHA256::SHA256(const SHA256& other)
: state{}, bitLen(0), data{}, dataLen(0)
{
Util::Copy(state, other.state, sizeof(state) / sizeof(UInt_32));
bitLen = other.bitLen;
Util::Copy(data, other.data, sizeof(data));
dataLen = other.dataLen;
}
SHA256& SHA256::operator=(SHA256&& other) noexcept
{
if (this == &other)
return *this;
Util::Copy(state, other.state, sizeof(state) / sizeof(UInt_32));
bitLen = other.bitLen;
Util::Copy(data, other.data, sizeof(data));
dataLen = other.dataLen;
Util::Zero(other.state, sizeof(state) / sizeof(UInt_32));
other.bitLen = 0;
Util::Zero(other.data, sizeof(data));
other.dataLen = 0;
return *this;
}
SHA256& SHA256::operator=(const SHA256& other)
{
if (this == &other)
return *this;
Util::Copy(state, other.state, sizeof(state) / sizeof(UInt_32));
bitLen = other.bitLen;
Util::Copy(data, other.data, sizeof(data));
dataLen = other.dataLen;
return *this;
}
void SHA256::Update(const Byte* data, const UInt_64 len)
{
for(UInt_64 i = 0; i < len; ++i)
{
this->data[dataLen++] = data[i];
if(dataLen == 64)
{
Transform(this->data);
bitLen += 512;
dataLen = 0;
}
}
}
void SHA256::Final(Byte hash[32])
{
UInt_32 i = dataLen;
/* Pad */
data[i++] = 0x80;
if(i > 56)
{
while(i < 64)
data[i++] = 0x00;
Transform(data);
i = 0;
}
while(i < 56)
data[i++] = 0x00;
/* Length in bits */
bitLen += dataLen * 8ULL;
data[63] = bitLen;
data[62] = bitLen >> 8;
data[61] = bitLen >> 16;
data[60] = bitLen >> 24;
data[59] = bitLen >> 32;
data[58] = bitLen >> 40;
data[57] = bitLen >> 48;
data[56] = bitLen >> 56;
Transform(data);
/* bigendian output */
for(i = 0; i < 4; ++i) {
hash[i] = (state[0] >> (24 - i * 8)) & 0xff;
hash[i + 4] = (state[1] >> (24 - i * 8)) & 0xff;
hash[i + 8] = (state[2] >> (24 - i * 8)) & 0xff;
hash[i + 12] = (state[3] >> (24 - i * 8)) & 0xff;
hash[i + 16] = (state[4] >> (24 - i * 8)) & 0xff;
hash[i + 20] = (state[5] >> (24 - i * 8)) & 0xff;
hash[i + 24] = (state[6] >> (24 - i * 8)) & 0xff;
hash[i + 28] = (state[7] >> (24 - i * 8)) & 0xff;
}
}
void SHA256::Hash(const Byte* data, const UInt_64 len, Byte hash[32])
{
Update(data, len);
Final(hash);
}
void SHA256::Transform(const Byte data[64])
{
UInt_32 m[64];
UInt_32 a = state[0];
UInt_32 b = state[1];
UInt_32 c = state[2];
UInt_32 d = state[3];
UInt_32 e = state[4];
UInt_32 f = state[5];
UInt_32 g = state[6];
UInt_32 h = state[7];
UInt_32 i, t1, t2;
for (i = 0; i < 16; ++i)
m[i] = (UInt_32)data[i * 4] << 24 | (UInt_32)data[i * 4 + 1] << 16 | (UInt_32)data[i * 4 + 2] << 8 | (UInt_32)data[i * 4 + 3];
for (; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
for(i = 0; i < 64; ++i)
{
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
t2 = EP0(a) + MAJ(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
}
}