From 70f386f9c67841f8beb0bfd828c4f79c09842195 Mon Sep 17 00:00:00 2001 From: Luchang Jin Date: Mon, 17 Oct 2016 14:18:58 -0400 Subject: [PATCH] switch to use Output Feedback Split mode https://github.com/waterret/RngState-OFS --- lib/lattice/rng/rng-state.h | 346 ++++++-------------------------- lib/lattice/rng/sha256.h | 348 +++++++++++++++++++++++++++++++++ lib/lattice/rng/show.h | 6 +- lib/lattice/rng/sprng-sha256.h | 6 +- 4 files changed, 414 insertions(+), 292 deletions(-) create mode 100644 lib/lattice/rng/sha256.h diff --git a/lib/lattice/rng/rng-state.h b/lib/lattice/rng/rng-state.h index 7222a96c..acef02fc 100644 --- a/lib/lattice/rng/rng-state.h +++ b/lib/lattice/rng/rng-state.h @@ -16,14 +16,19 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -// Code within namespace sha256 are from Stephan Brumme. -// see http://create.stephan-brumme.com/disclaimer.html +#pragma once -#ifndef RNG_STATE_RNG_STATE_H -#define RNG_STATE_RNG_STATE_H +#ifndef INCLUDE_RNG_STATE_H +#define INCLUDE_RNG_STATE_H #include "show.h" +#ifndef USE_OPENSSL +#include "sha256.h" +#else +#include +#endif + #include #include #include @@ -138,8 +143,12 @@ inline void exportRngState(uint32_t* v, const RngState& rs) for (int i = 0; i < 3; ++i) { splitTwoUint32(v[12 + i * 2], v[12 + i * 2 + 1], rs.cache[i]); } - const uint64_t* p = (const uint64_t*)&rs.gaussian; - splitTwoUint32(v[18], v[19], *p); + union { + double d; + uint64_t l; + } g; + g.d = rs.gaussian; + splitTwoUint32(v[18], v[19], g.l); v[20] = rs.cacheAvail; v[21] = rs.gaussianAvail; } @@ -155,8 +164,12 @@ inline void importRngState(RngState& rs, const uint32_t* v) for (int i = 0; i < 3; ++i) { rs.cache[i] = patchTwoUint32(v[12 + i * 2], v[12 + i * 2 + 1]); } - uint64_t g = patchTwoUint32(v[18], v[19]); - rs.gaussian = reinterpret_cast(g); + union { + double d; + uint64_t l; + } g; + g.l = patchTwoUint32(v[18], v[19]); + rs.gaussian = g.d; rs.cacheAvail = v[20]; rs.gaussianAvail = v[21]; } @@ -204,277 +217,18 @@ inline bool operator==(const RngState& rs1, const RngState& rs2) return 0 == memcmp(&rs1, &rs2, sizeof(RngState)); } -namespace sha256 { - - const size_t BlockSize = 512 / 8; - - const size_t HashBytes = 32; - - const size_t HashValues = HashBytes / 4; - - inline uint32_t rotate(uint32_t a, uint32_t c) - { - return (a >> c) | (a << (32 - c)); - } - - inline uint32_t swap(uint32_t x) - { - return (x >> 24) | - ((x >> 8) & 0x0000FF00) | - ((x << 8) & 0x00FF0000) | - (x << 24); - } - - inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g) - // mix functions for processBlock() - { - uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25); - uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g))) - return term1 + term2; - } - - inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c) - // mix functions for processBlock() - { - uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22); - uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c); - return term1 + term2; - } - - inline void processBlock(uint32_t newHash[8], const uint32_t oldHash[8], const uint8_t data[64]) - // process 64 bytes of data - // newHash and oldHash and be the same - { - // get last hash - uint32_t a = oldHash[0]; - uint32_t b = oldHash[1]; - uint32_t c = oldHash[2]; - uint32_t d = oldHash[3]; - uint32_t e = oldHash[4]; - uint32_t f = oldHash[5]; - uint32_t g = oldHash[6]; - uint32_t h = oldHash[7]; - // data represented as 16x 32-bit words - const uint32_t* input = (uint32_t*) data; - // convert to big endian - uint32_t words[64]; - int i; - for (i = 0; i < 16; i++) { -#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN) - words[i] = input[i]; -#else - words[i] = swap(input[i]); -#endif - } - uint32_t x,y; // temporaries - // first round - x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y; - // secound round - x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y; - // extend to 24 words - for (; i < 24; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - // third round - x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y; - // extend to 32 words - for (; i < 32; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - // fourth round - x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y; - // extend to 40 words - for (; i < 40; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - // fifth round - x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y; - // extend to 48 words - for (; i < 48; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - // sixth round - x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y; - // extend to 56 words - for (; i < 56; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - // seventh round - x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y; - // extend to 64 words - for (; i < 64; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - // eigth round - x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y; - // update hash - newHash[0] = a + oldHash[0]; - newHash[1] = b + oldHash[1]; - newHash[2] = c + oldHash[2]; - newHash[3] = d + oldHash[3]; - newHash[4] = e + oldHash[4]; - newHash[5] = f + oldHash[5]; - newHash[6] = g + oldHash[6]; - newHash[7] = h + oldHash[7]; - } - - inline void processInput( - uint32_t hash[8], - const uint32_t oldHash[8], const uint64_t numBytes, - const uint8_t* input, const size_t inputSize) - // process final block, less than 64 bytes - // newHash and oldHash and be the same - { - // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte - // - append "1" bit to message - // - append "0" bits until message length in bit mod 512 is 448 - // - append length as 64 bit integer - // process initial parts of input - std::memmove(hash, oldHash, 32); - const int nBlocks = inputSize / 64; - for (int i = 0; i < nBlocks; ++i) { - processBlock(hash, hash, input + i * 64); - } - // initialize buffer from input - const size_t bufferSize = inputSize - nBlocks * 64; - unsigned char buffer[BlockSize]; - std::memcpy(buffer, input + nBlocks * 64, bufferSize); - // number of bits - size_t paddedLength = bufferSize * 8; - // plus one bit set to 1 (always appended) - paddedLength++; - // number of bits must be (numBits % 512) = 448 - size_t lower11Bits = paddedLength & 511; - if (lower11Bits <= 448) { - paddedLength += 448 - lower11Bits; - } else { - paddedLength += 512 + 448 - lower11Bits; - } - // convert from bits to bytes - paddedLength /= 8; - // only needed if additional data flows over into a second block - unsigned char extra[BlockSize]; - // append a "1" bit, 128 => binary 10000000 - if (bufferSize < BlockSize) { - buffer[bufferSize] = 128; - } else { - extra[0] = 128; - } - size_t i; - for (i = bufferSize + 1; i < BlockSize; i++) { - buffer[i] = 0; - } - for (; i < paddedLength; i++) { - extra[i - BlockSize] = 0; - } - // add message length in bits as 64 bit number - uint64_t msgBits = 8 * (numBytes + inputSize); - // find right position - unsigned char* addLength; - if (paddedLength < BlockSize) { - addLength = buffer + paddedLength; - } else { - addLength = extra + paddedLength - BlockSize; - } - // must be big endian - *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF); - *addLength = (unsigned char)( msgBits & 0xFF); - // process blocks - processBlock(hash, hash, buffer); - // flowed over into a second block ? - if (paddedLength > BlockSize) { - processBlock(hash, hash, extra); - } - } - -} - inline void reset(RngState& rs) { std::memset(&rs, 0, sizeof(RngState)); rs.numBytes = 0; - rs.hash[0] = 0x6a09e667; - rs.hash[1] = 0xbb67ae85; - rs.hash[2] = 0x3c6ef372; - rs.hash[3] = 0xa54ff53a; - rs.hash[4] = 0x510e527f; - rs.hash[5] = 0x9b05688c; - rs.hash[6] = 0x1f83d9ab; - rs.hash[7] = 0x5be0cd19; + rs.hash[0] = 0; + rs.hash[1] = 0; + rs.hash[2] = 0; + rs.hash[3] = 0; + rs.hash[4] = 0; + rs.hash[5] = 0; + rs.hash[6] = 0; + rs.hash[7] = 0; rs.index = 0; rs.cache[0] = 0; rs.cache[1] = 0; @@ -490,19 +244,40 @@ inline void reset(RngState& rs, const std::string& seed) splitRngState(rs, rs, seed); } +inline void computeHashWithInput(uint32_t hash[8], const RngState& rs, const std::string& input) +{ + std::string data(32, ' '); + for (int i = 0; i < 8; ++i) { + data[i*4 + 0] = (rs.hash[i] >> 24) & 0xFF; + data[i*4 + 1] = (rs.hash[i] >> 16) & 0xFF; + data[i*4 + 2] = (rs.hash[i] >> 8) & 0xFF; + data[i*4 + 3] = rs.hash[i] & 0xFF; + } + data += input; +#ifndef USE_OPENSSL + sha256::computeHash(hash, (const uint8_t*)data.c_str(), data.length()); +#else + { + uint8_t rawHash[32]; + SHA256((unsigned char*)data.c_str(), data.length(), rawHash); + for (int i = 0; i < 8; ++i) { + hash[i] = (((uint32_t)rawHash[i*4 + 0]) << 24) + + (((uint32_t)rawHash[i*4 + 1]) << 16) + + (((uint32_t)rawHash[i*4 + 2]) << 8) + + ( (uint32_t)rawHash[i*4 + 3]); + } + } +#endif +} + inline void splitRngState(RngState& rs, const RngState& rs0, const std::string& sindex) // produce a new rng ``rs'' uniquely identified by ``rs0'' and ``sindex'' // will not affect old rng ``rs0'' // the function should behave correctly even if ``rs'' is actually ``rs0'' { - std::string data = ssprintf("[%lu] {%s}", rs0.index, sindex.c_str()); - const int nBlocks = (data.length() - 1) / 64 + 1; - data.resize(nBlocks * 64, ' '); - sha256::processBlock(rs.hash, rs0.hash, (const uint8_t*)data.c_str()); - for (int i = 1; i < nBlocks; ++i) { - sha256::processBlock(rs.hash, rs.hash, (const uint8_t*)data.c_str() + i * 64); - } - rs.numBytes = rs0.numBytes + nBlocks * 64; + std::string input = ssprintf("[%lu] {%s}", rs0.index, sindex.c_str()); + rs.numBytes = rs0.numBytes + 64 * ((32 + input.length() + 1 + 8 - 1) / 64 + 1); + computeHashWithInput(rs.hash, rs0, input); rs.index = 0; rs.cache[0] = 0; rs.cache[1] = 0; @@ -512,11 +287,6 @@ inline void splitRngState(RngState& rs, const RngState& rs0, const std::string& rs.gaussianAvail = false; } -inline void computeHashWithInput(uint32_t hash[8], const RngState& rs, const std::string& input) -{ - sha256::processInput(hash, rs.hash, rs.numBytes, (const uint8_t*)input.c_str(), input.length()); -} - inline uint64_t randGen(RngState& rs) { assert(0 <= rs.cacheAvail && rs.cacheAvail <= 3); diff --git a/lib/lattice/rng/sha256.h b/lib/lattice/rng/sha256.h new file mode 100644 index 00000000..dde443cf --- /dev/null +++ b/lib/lattice/rng/sha256.h @@ -0,0 +1,348 @@ +// vim: set ts=2 sw=2 expandtab: + +// Copyright (c) 2016 Luchang Jin +// All rights reserved. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// Code within namespace sha256 are originally from Stephan Brumme. +// see http://create.stephan-brumme.com/disclaimer.html + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CURRENT_DEFAULT_NAMESPACE_NAME +namespace CURRENT_DEFAULT_NAMESPACE_NAME { +#endif + +namespace sha256 { + + const size_t BlockSize = 512 / 8; + + const size_t HashBytes = 32; + + const size_t HashValues = HashBytes / 4; + + inline uint32_t rotate(uint32_t a, uint32_t c) + { + return (a >> c) | (a << (32 - c)); + } + + inline uint32_t swap(uint32_t x) + { + return (x >> 24) | + ((x >> 8) & 0x0000FF00) | + ((x << 8) & 0x00FF0000) | + (x << 24); + } + + inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g) + // mix functions for processBlock() + { + uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25); + uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g))) + return term1 + term2; + } + + inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c) + // mix functions for processBlock() + { + uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22); + uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c); + return term1 + term2; + } + + inline void processBlock(uint32_t newHash[8], const uint32_t oldHash[8], const uint8_t data[64]) + // process 64 bytes of data + // newHash and oldHash and be the same + { + // get last hash + uint32_t a = oldHash[0]; + uint32_t b = oldHash[1]; + uint32_t c = oldHash[2]; + uint32_t d = oldHash[3]; + uint32_t e = oldHash[4]; + uint32_t f = oldHash[5]; + uint32_t g = oldHash[6]; + uint32_t h = oldHash[7]; + // data represented as 16x 32-bit words + const uint32_t* input = (uint32_t*) data; + // convert to big endian + uint32_t words[64]; + int i; + for (i = 0; i < 16; i++) { +#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN) + words[i] = input[i]; +#else + words[i] = swap(input[i]); +#endif + } + uint32_t x,y; // temporaries + // first round + x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y; + x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y; + x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y; + x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y; + x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y; + x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y; + x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y; + x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y; + // secound round + x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y; + x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y; + x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y; + x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y; + x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y; + x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y; + x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y; + x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y; + // extend to 24 words + for (; i < 24; i++) + words[i] = words[i-16] + + (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + + words[i-7] + + (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); + // third round + x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y; + x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y; + x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y; + x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y; + x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y; + x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y; + x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y; + x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y; + // extend to 32 words + for (; i < 32; i++) + words[i] = words[i-16] + + (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + + words[i-7] + + (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); + // fourth round + x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y; + x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y; + x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y; + x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y; + x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y; + x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y; + x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y; + x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y; + // extend to 40 words + for (; i < 40; i++) + words[i] = words[i-16] + + (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + + words[i-7] + + (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); + // fifth round + x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y; + x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y; + x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y; + x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y; + x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y; + x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y; + x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y; + x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y; + // extend to 48 words + for (; i < 48; i++) + words[i] = words[i-16] + + (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + + words[i-7] + + (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); + // sixth round + x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y; + x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y; + x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y; + x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y; + x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y; + x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y; + x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y; + x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y; + // extend to 56 words + for (; i < 56; i++) + words[i] = words[i-16] + + (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + + words[i-7] + + (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); + // seventh round + x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y; + x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y; + x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y; + x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y; + x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y; + x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y; + x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y; + x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y; + // extend to 64 words + for (; i < 64; i++) + words[i] = words[i-16] + + (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + + words[i-7] + + (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); + // eigth round + x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y; + x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y; + x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y; + x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y; + x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y; + x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y; + x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y; + x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y; + // update hash + newHash[0] = a + oldHash[0]; + newHash[1] = b + oldHash[1]; + newHash[2] = c + oldHash[2]; + newHash[3] = d + oldHash[3]; + newHash[4] = e + oldHash[4]; + newHash[5] = f + oldHash[5]; + newHash[6] = g + oldHash[6]; + newHash[7] = h + oldHash[7]; + } + + inline void processInput( + uint32_t hash[8], + const uint32_t oldHash[8], const uint64_t numBytes, + const uint8_t* input, const size_t inputSize) + // process final block, less than 64 bytes + // newHash and oldHash and be the same + { + // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte + // - append "1" bit to message + // - append "0" bits until message length in bit mod 512 is 448 + // - append length as 64 bit integer + // process initial parts of input + std::memmove(hash, oldHash, 32); + const int nBlocks = inputSize / 64; + for (int i = 0; i < nBlocks; ++i) { + processBlock(hash, hash, input + i * 64); + } + // initialize buffer from input + const size_t bufferSize = inputSize - nBlocks * 64; + unsigned char buffer[BlockSize]; + std::memcpy(buffer, input + nBlocks * 64, bufferSize); + // number of bits + size_t paddedLength = bufferSize * 8; + // plus one bit set to 1 (always appended) + paddedLength++; + // number of bits must be (numBits % 512) = 448 + size_t lower11Bits = paddedLength & 511; + if (lower11Bits <= 448) { + paddedLength += 448 - lower11Bits; + } else { + paddedLength += 512 + 448 - lower11Bits; + } + // convert from bits to bytes + paddedLength /= 8; + // only needed if additional data flows over into a second block + unsigned char extra[BlockSize]; + // append a "1" bit, 128 => binary 10000000 + if (bufferSize < BlockSize) { + buffer[bufferSize] = 128; + } else { + extra[0] = 128; + } + size_t i; + for (i = bufferSize + 1; i < BlockSize; i++) { + buffer[i] = 0; + } + for (; i < paddedLength; i++) { + extra[i - BlockSize] = 0; + } + // add message length in bits as 64 bit number + uint64_t msgBits = 8 * (numBytes + inputSize); + // find right position + unsigned char* addLength; + if (paddedLength < BlockSize) { + addLength = buffer + paddedLength; + } else { + addLength = extra + paddedLength - BlockSize; + } + // must be big endian + *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF); + *addLength = (unsigned char)( msgBits & 0xFF); + // process blocks + processBlock(hash, hash, buffer); + // flowed over into a second block ? + if (paddedLength > BlockSize) { + processBlock(hash, hash, extra); + } + } + + inline void setInitialHash(uint32_t hash[8]) + { + hash[0] = 0x6a09e667; + hash[1] = 0xbb67ae85; + hash[2] = 0x3c6ef372; + hash[3] = 0xa54ff53a; + hash[4] = 0x510e527f; + hash[5] = 0x9b05688c; + hash[6] = 0x1f83d9ab; + hash[7] = 0x5be0cd19; + } + + inline void computeHash(uint32_t hash[8], const void* data, const size_t size) + { + uint32_t initHash[8]; + setInitialHash(initHash); + processInput(hash, initHash, 0, (const uint8_t*)data, size); + } + + inline void rawHashFromHash(uint8_t rawHash[HashBytes], const uint32_t hash[HashValues]) + { + uint8_t* current = rawHash; + for (size_t i = 0; i < HashValues; i++) { + *current++ = (hash[i] >> 24) & 0xFF; + *current++ = (hash[i] >> 16) & 0xFF; + *current++ = (hash[i] >> 8) & 0xFF; + *current++ = hash[i] & 0xFF; + } + } + + inline std::string showRawHash(const uint8_t rawHash[HashBytes]) + { + std::string result; + result.reserve(2 * HashBytes); + for (size_t i = 0; i < HashBytes; i++) { + static const char dec2hex[16+1] = "0123456789abcdef"; + result += dec2hex[(rawHash[i] >> 4) & 15]; + result += dec2hex[ rawHash[i] & 15]; + } + return result; + } + + inline std::string showHash(const uint32_t hash[8]) + { + unsigned char rawHash[HashBytes]; + rawHashFromHash(rawHash, hash); + return showRawHash(rawHash); + } + +} + +#ifdef CURRENT_DEFAULT_NAMESPACE_NAME +} +#endif diff --git a/lib/lattice/rng/show.h b/lib/lattice/rng/show.h index a44b3a86..190d8f4a 100644 --- a/lib/lattice/rng/show.h +++ b/lib/lattice/rng/show.h @@ -16,8 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#ifndef RNG_STATE_SHOW_H -#define RNG_STATE_SHOW_H +#pragma once + +#ifndef INCLUDE_SHOW_H +#define INCLUDE_SHOW_H #include #include diff --git a/lib/lattice/rng/sprng-sha256.h b/lib/lattice/rng/sprng-sha256.h index ec4c2020..d661c061 100644 --- a/lib/lattice/rng/sprng-sha256.h +++ b/lib/lattice/rng/sprng-sha256.h @@ -16,8 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#ifndef RNG_STATE_SPRNG_SHA256_H -#define RNG_STATE_SPRNG_SHA256_H +#pragma once + +#ifndef INCLUDE_SPRNG_SHA256_H +#define INCLUDE_SPRNG_SHA256_H #include "rng-state.h"