#include // https://github.com/jasinb/sha1.git // STRUCT(Sha1Digest) // { // u32 digest[5]; // }; // static uint32_t rotl32(uint32_t x, int b) // { // return (x << b) | (x >> (32-b)); // } // // switch endianness // fn u32 sha1_get32(u8* p) // { // return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; // } // fn u32 sha1_f(int t, u32 b, u32 c, u32 d) // { // assert(0 <= t && t < 80); // // if (t < 20) // { // return (b & c) | ((~b) & d); // } // else if (t < 40) // { // return b ^ c ^ d; // } // else if (t < 60) // { // return (b & c) | (b & d) | (c & d); // } // else // //if (t < 80) // { // return b ^ c ^ d; // } // } // STRUCT(Sha1Context) // { // u8 block[64]; // u32 h[5]; // u64 bytes; // u32 cur; // }; // fn void sha1_reset(Sha1Context* ctx) // { // ctx->h[0] = 0x67452301; // ctx->h[1] = 0xefcdab89; // ctx->h[2] = 0x98badcfe; // ctx->h[3] = 0x10325476; // ctx->h[4] = 0xc3d2e1f0; // ctx->bytes = 0; // ctx->cur = 0; // } // fn void sha1_process_block(Sha1Context* ctx) // { // global_variable const u32 k[4] = // { // 0x5A827999, // 0x6ED9EBA1, // 0x8F1BBCDC, // 0xCA62C1D6 // }; // // u32 w[16]; // u32 a = ctx->h[0]; // u32 b = ctx->h[1]; // u32 c = ctx->h[2]; // u32 d = ctx->h[3]; // u32 e = ctx->h[4]; // u32 t; // // for (t = 0; t < 16; t++) // w[t] = sha1_get32((u8*)(&((uint32_t*)ctx->block)[t])); // // for (t = 0; t < 80; t++) // { // auto s = t & 0xf; // u32 temp; // if (t >= 16) // w[s] = rotate_left_u32(w[(s + 13) & 0xf] ^ w[(s + 8) & 0xf] ^ w[(s + 2) & 0xf] ^ w[s], 1); // // temp = rotate_left_u32(a, 5) + sha1_f(t, b,c,d) + e + w[s] + k[t/20]; // // e = d; d = c; c = rotate_left_u32(b, 30); b = a; a = temp; // } // // ctx->h[0] += a; // ctx->h[1] += b; // ctx->h[2] += c; // ctx->h[3] += d; // ctx->h[4] += e; // } // fn void sha1_write(Sha1Context* ctx, String bytes) // { // auto length = bytes.length; // ctx->bytes += length; // // const uint8_t* src = bytes.pointer; // while (length--) // { // // TODO: could optimize the first and last few bytes, and then copy // // 128 bit blocks with SIMD in between // ctx->block[ctx->cur++] = *src++; // if (ctx->cur == 64) // { // sha1_process_block(ctx); // ctx->cur = 0; // } // } // } // fn Sha1Digest sha1_get_digest(Sha1Context* ctx) // { // // append separator // ctx->block[ctx->cur++] = 0x80; // if (ctx->cur > 56) // { // // no space in block for the 64-bit message length, flush // memset(&ctx->block[ctx->cur], 0, 64 - ctx->cur); // sha1_process_block(ctx); // ctx->cur = 0; // } // // memset(&ctx->block[ctx->cur], 0, 56 - ctx->cur); // uint64_t bits = ctx->bytes * 8; // // // TODO a few instructions could be shaven // ctx->block[56] = (uint8_t)(bits >> 56 & 0xff); // ctx->block[57] = (uint8_t)(bits >> 48 & 0xff); // ctx->block[58] = (uint8_t)(bits >> 40 & 0xff); // ctx->block[59] = (uint8_t)(bits >> 32 & 0xff); // ctx->block[60] = (uint8_t)(bits >> 24 & 0xff); // ctx->block[61] = (uint8_t)(bits >> 16 & 0xff); // ctx->block[62] = (uint8_t)(bits >> 8 & 0xff); // ctx->block[63] = (uint8_t)(bits >> 0 & 0xff); // sha1_process_block(ctx); // // { // Sha1Digest ret; // int i; // for (i = 0; i < 5; i++) // ret.digest[i] = sha1_get32((u8*)&ctx->h[i]); // sha1_reset(ctx); // return ret; // } // } // fn Sha1Digest sha1_compute(String bytes) // { // Sha1Context ctx; // sha1_reset(&ctx); // sha1_write(&ctx, bytes); // return sha1_get_digest(&ctx); // }