// Copyright Low Entry. Apache License, Version 2.0. #include "LowEntryHashingSha256Library.h" constexpr int32 ULowEntryHashingSha256Library::k[64] = {0x428a2f98, 0x71374491, static_cast(0xb5c0fbcf), static_cast(0xe9b5dba5), 0x3956c25b, 0x59f111f1, static_cast(0x923f82a4), static_cast(0xab1c5ed5), static_cast(0xd807aa98), 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, static_cast(0x80deb1fe), static_cast(0x9bdc06a7), static_cast(0xc19bf174), static_cast(0xe49b69c1), static_cast(0xefbe4786), 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, static_cast(0x983e5152), static_cast(0xa831c66d), static_cast(0xb00327c8), static_cast(0xbf597fc7), static_cast(0xc6e00bf3), static_cast(0xd5a79147), 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, static_cast(0x81c2c92e), static_cast(0x92722c85), static_cast(0xa2bfe8a1), static_cast(0xa81a664b), static_cast(0xc24b8b70), static_cast(0xc76c51a3), static_cast(0xd192e819), static_cast(0xd6990624), static_cast(0xf40e3585), 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, static_cast(0x84c87814), static_cast(0x8cc70208), static_cast(0x90befffa), static_cast(0xa4506ceb), static_cast(0xbef9a3f7), static_cast(0xc67178f2)}; void ULowEntryHashingSha256Library::initialize() { w.SetNum(64); buffer.SetNum(64); } void ULowEntryHashingSha256Library::update(const TArray& b, const int64 offset, const int64 len) { int32 n = count % BLOCK_SIZE; count += len; int64 partLen = BLOCK_SIZE - n; int64 i = 0; if (len >= partLen) { for (int32 index = 0; index < partLen; index++) { buffer[n + index] = b[offset + index]; } sha(buffer, 0); for (i = partLen; ((i + BLOCK_SIZE) - 1) < len; i += BLOCK_SIZE) { sha(b, offset + i); } n = 0; } if (i < len) { for (int32 index = 0; index < len - i; index++) { buffer[n + index] = b[offset + i + index]; } } } TArray ULowEntryHashingSha256Library::digest() { TArray tail = padBuffer(); update(tail, 0, tail.Num()); return getResult(); } TArray ULowEntryHashingSha256Library::padBuffer() { int32 n = count % BLOCK_SIZE; int32 padding = (n < 56) ? (56 - n) : (120 - n); TArray result; result.SetNum(padding + 8); result[0] = static_cast(0x80); int64 bits = count << 3; result[padding + 0] = static_cast(bits >> 56); result[padding + 1] = static_cast(bits >> 48); result[padding + 2] = static_cast(bits >> 40); result[padding + 3] = static_cast(bits >> 32); result[padding + 4] = static_cast(bits >> 24); result[padding + 5] = static_cast(bits >> 16); result[padding + 6] = static_cast(bits >> 8); result[padding + 7] = static_cast(bits); return result; } TArray ULowEntryHashingSha256Library::getResult() { TArray result; result.SetNum(32); result[0] = static_cast(h0 >> 24); result[1] = static_cast(h0 >> 16); result[2] = static_cast(h0 >> 8); result[3] = static_cast(h0); result[4] = static_cast(h1 >> 24); result[5] = static_cast(h1 >> 16); result[6] = static_cast(h1 >> 8); result[7] = static_cast(h1); result[8] = static_cast(h2 >> 24); result[9] = static_cast(h2 >> 16); result[10] = static_cast(h2 >> 8); result[11] = static_cast(h2); result[12] = static_cast(h3 >> 24); result[13] = static_cast(h3 >> 16); result[14] = static_cast(h3 >> 8); result[15] = static_cast(h3); result[16] = static_cast(h4 >> 24); result[17] = static_cast(h4 >> 16); result[18] = static_cast(h4 >> 8); result[19] = static_cast(h4); result[20] = static_cast(h5 >> 24); result[21] = static_cast(h5 >> 16); result[22] = static_cast(h5 >> 8); result[23] = static_cast(h5); result[24] = static_cast(h6 >> 24); result[25] = static_cast(h6 >> 16); result[26] = static_cast(h6 >> 8); result[27] = static_cast(h6); result[28] = static_cast(h7 >> 24); result[29] = static_cast(h7 >> 16); result[30] = static_cast(h7 >> 8); result[31] = static_cast(h7); return result; } void ULowEntryHashingSha256Library::sha(const TArray& in, int64 offset) { int32 A = h0; int32 B = h1; int32 C = h2; int32 D = h3; int32 E = h4; int32 F = h5; int32 G = h6; int32 H = h7; int32 T; int32 T2; int32 r; for (r = 0; r < 16; r++) { w[r] = ((in[offset] << 24) | ((in[offset + 1] & 0xFF) << 16) | ((in[offset + 2] & 0xFF) << 8) | (in[offset + 3] & 0xFF)); offset += 4; } for (r = 16; r < 64; r++) { T = w[r - 2]; T2 = w[r - 15]; w[r] = (((s(T, 17) | (T << 15)) ^ (s(T, 19) | (T << 13)) ^ s(T, 10)) + w[r - 7] + ((s(T2, 7) | (T2 << 25)) ^ (s(T2, 18) | (T2 << 14)) ^ s(T2, 3)) + w[r - 16]); } for (r = 0; r < 64; r++) { T = (H + ((s(E, 6) | (E << 26)) ^ (s(E, 11) | (E << 21)) ^ (s(E, 25) | (E << 7))) + ((E & F) ^ (~E & G)) + k[r] + w[r]); T2 = (((s(A, 2) | (A << 30)) ^ (s(A, 13) | (A << 19)) ^ (s(A, 22) | (A << 10))) + ((A & B) ^ (A & C) ^ (B & C))); H = G; G = F; F = E; E = D + T; D = C; C = B; B = A; A = T + T2; } h0 += A; h1 += B; h2 += C; h3 += D; h4 += E; h5 += F; h6 += G; h7 += H; } int32 ULowEntryHashingSha256Library::s(const int32 a, const int32 b) { const uint32 A = a; const uint32 B = b; return (A >> B); } TArray ULowEntryHashingSha256Library::Hash(const TArray& Bytes) { ULowEntryHashingSha256Library instance = ULowEntryHashingSha256Library(); instance.initialize(); instance.update(Bytes, 0, Bytes.Num()); return instance.digest(); } TArray ULowEntryHashingSha256Library::Hash(const TArray& Bytes, int32 Index, int32 Length) { if (Bytes.Num() <= 0) { ULowEntryHashingSha256Library instance = ULowEntryHashingSha256Library(); instance.initialize(); return instance.digest(); } if (Index < 0) { Length += Index; Index = 0; } if (Length > (Bytes.Num() - Index)) { Length = Bytes.Num() - Index; } if (Length <= 0) { ULowEntryHashingSha256Library instance = ULowEntryHashingSha256Library(); instance.initialize(); return instance.digest(); } ULowEntryHashingSha256Library instance = ULowEntryHashingSha256Library(); instance.initialize(); instance.update(Bytes, Index, Length); return instance.digest(); }