#include <iostream>
#include <array>
using namespace std;
#define uchar unsigned char
static std::uint32_t ror32(std::uint32_t value, int by) noexcept
{
return (value >> by) | (value << (32 - by));
}
static std::uint32_t shr32(std::uint32_t value, int by) noexcept { return value >> by; }
static std::uint32_t rol32(std::uint32_t value, int by) noexcept
{
return (value << by) | (value >> (32 - by));
}
int main() {
// your code goes here
return 0;
}
struct Sha256Algorithm
{
using underlying_type = std::uint32_t;
using message_length_type = std::uint64_t;
constexpr static std::size_t chunk_size = 64;
constexpr static std::size_t number_of_rounds = 64;
Sha256Algorithm() noexcept { clear(); }
void process_full_chunk(const std::array<uchar, chunk_size>& chunk) noexcept
{
std::uint32_t words[64];
// sha_fill_initial_words(&chunk[0], words);
for (std::size_t i = 16; i < number_of_rounds; ++i)
{
const auto w0 = words[i - 15];
const auto s0 = ror32(w0, 7) ^ ror32(w0, 18) ^ shr32(w0, 3);
const auto w1 = words[i - 2];
const auto s1 = ror32(w1, 17) ^ ror32(w1, 19) ^ shr32(w1, 10);
words[i] = words[i - 16] + s0 + words[i - 7] + s1;
}
std::uint32_t local[8];
std::copy(begin(), end(), std::begin(local));
for (std::size_t i = 0; i < number_of_rounds; ++i)
{
const auto a = local[0];
const auto b = local[1];
const auto c = local[2];
const auto s0 = ror32(a, 2) ^ ror32(a, 13) ^ ror32(a, 22);
const auto maj = (a & b) ^ (a & c) ^ (b & c);
const auto tmp1 = s0 + maj;
const auto e = local[4];
const auto s1 = ror32(e, 6) ^ ror32(e, 11) ^ ror32(e, 25);
const auto ch = (e & local[5]) ^ (~e & local[6]);
const auto tmp2 = local[7] + s1 + ch + round_constants[i] + words[i];
for (std::size_t j = 12; j > 0; --j)
{
local[j] = local[j - 1];
}
local[4] += tmp2;
local[0] = tmp1 + tmp2;
}
for (std::size_t i = 0; i < 8; ++i)
{
m_digest[i] += local[i];
}
}
void clear() noexcept
{
m_digest[0] = 0x6a09e667;
m_digest[1] = 0xbb67ae85;
m_digest[2] = 0x3c6ef372;
m_digest[3] = 0xa54ff53a;
m_digest[4] = 0x510e527f;
m_digest[5] = 0x9b05688c;
m_digest[6] = 0x1f83d9ab;
m_digest[7] = 0x5be0cd19;
}
constexpr static std::array<std::uint32_t, number_of_rounds> round_constants = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
std::uint32_t* begin() noexcept { return &m_digest[0]; }
std::uint32_t* end() noexcept { return &m_digest[8]; }
std::uint32_t m_digest[8];
};
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YXJyYXk+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CiNkZWZpbmUgdWNoYXIgdW5zaWduZWQgY2hhcgoKc3RhdGljIHN0ZDo6dWludDMyX3Qgcm9yMzIoc3RkOjp1aW50MzJfdCB2YWx1ZSwgaW50IGJ5KSBub2V4Y2VwdAp7CglyZXR1cm4gKHZhbHVlID4+IGJ5KSB8ICh2YWx1ZSA8PCAoMzIgLSBieSkpOwp9CnN0YXRpYyBzdGQ6OnVpbnQzMl90IHNocjMyKHN0ZDo6dWludDMyX3QgdmFsdWUsIGludCBieSkgbm9leGNlcHQgeyByZXR1cm4gdmFsdWUgPj4gYnk7IH0Kc3RhdGljIHN0ZDo6dWludDMyX3Qgcm9sMzIoc3RkOjp1aW50MzJfdCB2YWx1ZSwgaW50IGJ5KSBub2V4Y2VwdAp7CglyZXR1cm4gKHZhbHVlIDw8IGJ5KSB8ICh2YWx1ZSA+PiAoMzIgLSBieSkpOwp9CmludCBtYWluKCkgewoJLy8geW91ciBjb2RlIGdvZXMgaGVyZQoJcmV0dXJuIDA7Cn0KCnN0cnVjdCBTaGEyNTZBbGdvcml0aG0KewogICAgdXNpbmcgdW5kZXJseWluZ190eXBlID0gc3RkOjp1aW50MzJfdDsKICAgIHVzaW5nIG1lc3NhZ2VfbGVuZ3RoX3R5cGUgPSBzdGQ6OnVpbnQ2NF90OwogICAgY29uc3RleHByIHN0YXRpYyBzdGQ6OnNpemVfdCBjaHVua19zaXplID0gNjQ7CgogICAgY29uc3RleHByIHN0YXRpYyBzdGQ6OnNpemVfdCBudW1iZXJfb2Zfcm91bmRzID0gNjQ7CgogICAgU2hhMjU2QWxnb3JpdGhtKCkgbm9leGNlcHQgeyBjbGVhcigpOyB9CgogICAgdm9pZCBwcm9jZXNzX2Z1bGxfY2h1bmsoY29uc3Qgc3RkOjphcnJheTx1Y2hhciwgY2h1bmtfc2l6ZT4mIGNodW5rKSBub2V4Y2VwdAogICAgewogICAgICAgIHN0ZDo6dWludDMyX3Qgd29yZHNbNjRdOwoKLy8gICAgICAgICAgICBzaGFfZmlsbF9pbml0aWFsX3dvcmRzKCZjaHVua1swXSwgd29yZHMpOwoKICAgICAgICBmb3IgKHN0ZDo6c2l6ZV90IGkgPSAxNjsgaSA8IG51bWJlcl9vZl9yb3VuZHM7ICsraSkKICAgICAgICB7CiAgICAgICAgICAgIGNvbnN0IGF1dG8gdzAgPSB3b3Jkc1tpIC0gMTVdOwogICAgICAgICAgICBjb25zdCBhdXRvIHMwID0gcm9yMzIodzAsIDcpIF4gcm9yMzIodzAsIDE4KSBeIHNocjMyKHcwLCAzKTsKICAgICAgICAgICAgY29uc3QgYXV0byB3MSA9IHdvcmRzW2kgLSAyXTsKICAgICAgICAgICAgY29uc3QgYXV0byBzMSA9IHJvcjMyKHcxLCAxNykgXiByb3IzMih3MSwgMTkpIF4gc2hyMzIodzEsIDEwKTsKICAgICAgICAgICAgd29yZHNbaV0gPSB3b3Jkc1tpIC0gMTZdICsgczAgKyB3b3Jkc1tpIC0gN10gKyBzMTsKICAgICAgICB9CgogICAgICAgIHN0ZDo6dWludDMyX3QgbG9jYWxbOF07CiAgICAgICAgc3RkOjpjb3B5KGJlZ2luKCksIGVuZCgpLCBzdGQ6OmJlZ2luKGxvY2FsKSk7CgogICAgICAgIGZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBudW1iZXJfb2Zfcm91bmRzOyArK2kpCiAgICAgICAgewogICAgICAgICAgICBjb25zdCBhdXRvIGEgPSBsb2NhbFswXTsKICAgICAgICAgICAgY29uc3QgYXV0byBiID0gbG9jYWxbMV07CiAgICAgICAgICAgIGNvbnN0IGF1dG8gYyA9IGxvY2FsWzJdOwoKICAgICAgICAgICAgY29uc3QgYXV0byBzMCA9IHJvcjMyKGEsIDIpIF4gcm9yMzIoYSwgMTMpIF4gcm9yMzIoYSwgMjIpOwogICAgICAgICAgICBjb25zdCBhdXRvIG1haiA9IChhICYgYikgXiAoYSAmIGMpIF4gKGIgJiBjKTsKICAgICAgICAgICAgY29uc3QgYXV0byB0bXAxID0gczAgKyBtYWo7CgogICAgICAgICAgICBjb25zdCBhdXRvIGUgPSBsb2NhbFs0XTsKCiAgICAgICAgICAgIGNvbnN0IGF1dG8gczEgPSByb3IzMihlLCA2KSBeIHJvcjMyKGUsIDExKSBeIHJvcjMyKGUsIDI1KTsKICAgICAgICAgICAgY29uc3QgYXV0byBjaCA9IChlICYgbG9jYWxbNV0pIF4gKH5lICYgbG9jYWxbNl0pOwogICAgICAgICAgICBjb25zdCBhdXRvIHRtcDIgPSBsb2NhbFs3XSArIHMxICsgY2ggKyByb3VuZF9jb25zdGFudHNbaV0gKyB3b3Jkc1tpXTsKCiAgICAgICAgICAgIGZvciAoc3RkOjpzaXplX3QgaiA9IDEyOyBqID4gMDsgLS1qKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBsb2NhbFtqXSA9IGxvY2FsW2ogLSAxXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsb2NhbFs0XSArPSB0bXAyOwogICAgICAgICAgICBsb2NhbFswXSA9IHRtcDEgKyB0bXAyOwogICAgICAgIH0KCiAgICAgICAgZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IDg7ICsraSkKICAgICAgICB7CiAgICAgICAgICAgIG1fZGlnZXN0W2ldICs9IGxvY2FsW2ldOwogICAgICAgIH0KICAgIH0KCiAgICB2b2lkIGNsZWFyKCkgbm9leGNlcHQKICAgIHsKICAgICAgICBtX2RpZ2VzdFswXSA9IDB4NmEwOWU2Njc7CiAgICAgICAgbV9kaWdlc3RbMV0gPSAweGJiNjdhZTg1OwogICAgICAgIG1fZGlnZXN0WzJdID0gMHgzYzZlZjM3MjsKICAgICAgICBtX2RpZ2VzdFszXSA9IDB4YTU0ZmY1M2E7CiAgICAgICAgbV9kaWdlc3RbNF0gPSAweDUxMGU1MjdmOwogICAgICAgIG1fZGlnZXN0WzVdID0gMHg5YjA1Njg4YzsKICAgICAgICBtX2RpZ2VzdFs2XSA9IDB4MWY4M2Q5YWI7CiAgICAgICAgbV9kaWdlc3RbN10gPSAweDViZTBjZDE5OwogICAgfQoKICAgIGNvbnN0ZXhwciBzdGF0aWMgc3RkOjphcnJheTxzdGQ6OnVpbnQzMl90LCBudW1iZXJfb2Zfcm91bmRzPiByb3VuZF9jb25zdGFudHMgPSB7CiAgICAgICAgMHg0MjhhMmY5OCwgMHg3MTM3NDQ5MSwgMHhiNWMwZmJjZiwgMHhlOWI1ZGJhNSwgMHgzOTU2YzI1YiwgMHg1OWYxMTFmMSwgMHg5MjNmODJhNCwgMHhhYjFjNWVkNSwKICAgICAgICAweGQ4MDdhYTk4LCAweDEyODM1YjAxLCAweDI0MzE4NWJlLCAweDU1MGM3ZGMzLCAweDcyYmU1ZDc0LCAweDgwZGViMWZlLCAweDliZGMwNmE3LCAweGMxOWJmMTc0LAogICAgICAgIDB4ZTQ5YjY5YzEsIDB4ZWZiZTQ3ODYsIDB4MGZjMTlkYzYsIDB4MjQwY2ExY2MsIDB4MmRlOTJjNmYsIDB4NGE3NDg0YWEsIDB4NWNiMGE5ZGMsIDB4NzZmOTg4ZGEsCiAgICAgICAgMHg5ODNlNTE1MiwgMHhhODMxYzY2ZCwgMHhiMDAzMjdjOCwgMHhiZjU5N2ZjNywgMHhjNmUwMGJmMywgMHhkNWE3OTE0NywgMHgwNmNhNjM1MSwgMHgxNDI5Mjk2NywKICAgICAgICAweDI3YjcwYTg1LCAweDJlMWIyMTM4LCAweDRkMmM2ZGZjLCAweDUzMzgwZDEzLCAweDY1MGE3MzU0LCAweDc2NmEwYWJiLCAweDgxYzJjOTJlLCAweDkyNzIyYzg1LAogICAgICAgIDB4YTJiZmU4YTEsIDB4YTgxYTY2NGIsIDB4YzI0YjhiNzAsIDB4Yzc2YzUxYTMsIDB4ZDE5MmU4MTksIDB4ZDY5OTA2MjQsIDB4ZjQwZTM1ODUsIDB4MTA2YWEwNzAsCiAgICAgICAgMHgxOWE0YzExNiwgMHgxZTM3NmMwOCwgMHgyNzQ4Nzc0YywgMHgzNGIwYmNiNSwgMHgzOTFjMGNiMywgMHg0ZWQ4YWE0YSwgMHg1YjljY2E0ZiwgMHg2ODJlNmZmMywKICAgICAgICAweDc0OGY4MmVlLCAweDc4YTU2MzZmLCAweDg0Yzg3ODE0LCAweDhjYzcwMjA4LCAweDkwYmVmZmZhLCAweGE0NTA2Y2ViLCAweGJlZjlhM2Y3LCAweGM2NzE3OGYyfTsKCiAgICBzdGQ6OnVpbnQzMl90KiBiZWdpbigpIG5vZXhjZXB0IHsgcmV0dXJuICZtX2RpZ2VzdFswXTsgfQogICAgc3RkOjp1aW50MzJfdCogZW5kKCkgbm9leGNlcHQgeyByZXR1cm4gJm1fZGlnZXN0WzhdOyB9CgogICAgc3RkOjp1aW50MzJfdCBtX2RpZ2VzdFs4XTsKfTs=