TAY
Fork of Crypto_light by
Diff: SHA2_32.cpp
- Revision:
- 0:7a1237bd2d13
- Child:
- 2:473bac39ae7c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SHA2_32.cpp Sat Sep 07 23:47:28 2013 +0000 @@ -0,0 +1,353 @@ +#include "SHA2_32.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +static const uint32_t K[] = +{ + 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 +}; + +static uint32_t rotLeft(uint32_t w, uint8_t n) +{ + return (w << n) | (w >> (32-n)); +} + +static uint32_t rotRight(uint32_t w, uint8_t n) +{ + return rotLeft(w,32-n); +} + +static uint32_t CH(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & y) ^ ((~x) & z); +} + +static uint32_t MAJ(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & y) ^ (x & z) ^ (y & z); +} + +static uint32_t BSIG0(uint32_t x) +{ + return rotRight(x,2) ^ rotRight(x,13) ^ rotRight(x,22); +} + +static uint32_t BSIG1(uint32_t x) +{ + return rotRight(x,6) ^ rotRight(x,11) ^ rotRight(x,25); +} + +static uint32_t SSIG0(uint32_t x) +{ + return rotRight(x,7) ^ rotRight(x,18) ^ (x >> 3); +} + +static uint32_t SSIG1(uint32_t x) +{ + return rotRight(x,17) ^ rotRight(x,19) ^ (x >> 10); +} + + +static const uint32_t H[] = +{ + // SHA-224 + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4, + + // SHA-256 + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +SHA2_32::SHA2_32(SHA_32_TYPE t): +type(t), +totalBufferLength(0), +bufferLength(0) +{ + switch(type) + { + case SHA_224: + h0 = H[0]; + h1 = H[1]; + h2 = H[2]; + h3 = H[3]; + h4 = H[4]; + h5 = H[5]; + h6 = H[6]; + h7 = H[7]; + break; + + case SHA_256: + h0 = H[8]; + h1 = H[9]; + h2 = H[10]; + h3 = H[11]; + h4 = H[12]; + h5 = H[13]; + h6 = H[14]; + h7 = H[15]; + break; + } +} + +void SHA2_32::add(uint8_t *in, uint32_t length) +{ + if(length < 64-bufferLength) + { + memcpy(&buffer[bufferLength], in, length); + bufferLength += length; + totalBufferLength += length; + return; + } + int offset = 64-bufferLength; + memcpy(&buffer[bufferLength], in, offset); + computeBlock(&h0,&h1,&h2,&h3,&h4,&h5,&h6,&h7,buffer); + while(length-offset > 64) + { + memcpy(buffer, &in[offset], 64); + computeBlock(&h0,&h1,&h2,&h3,&h4,&h5,&h6,&h7,buffer); + offset += 64; + } + if(offset > length) + offset -= 64; + bufferLength = length - offset; + memcpy(buffer, &in[offset], bufferLength); + totalBufferLength += length; +} + +void SHA2_32::computeDigest(uint8_t *digest) +{ + uint16_t padding; + if(totalBufferLength % 64 < 56) + padding = 56 - (totalBufferLength % 64); + else + padding = 56 + (64 - (totalBufferLength % 64)); + uint8_t val = 0x80; + add(&val, 1); + val = 0; + for(int i = 0; i < padding-1; ++i) + add(&val,1); + totalBufferLength -= padding; + uint64_t lengthBit = totalBufferLength * 8; + uint32_t lengthBitLow = lengthBit; + uint32_t lengthBitHigh = lengthBit >> 32; + uint8_t tmp[4]; + tmp[0] = lengthBitHigh >> 24; + tmp[1] = lengthBitHigh >> 16; + tmp[2] = lengthBitHigh >> 8; + tmp[3] = lengthBitHigh; + add(tmp, 4); + tmp[0] = lengthBitLow >> 24; + tmp[1] = lengthBitLow >> 16; + tmp[2] = lengthBitLow >> 8; + tmp[3] = lengthBitLow; + add(tmp, 4); + + digest[0] = h0 >> 24; + digest[1] = h0 >> 16; + digest[2] = h0 >> 8; + digest[3] = h0; + digest[4] = h1 >> 24; + digest[5] = h1 >> 16; + digest[6] = h1 >> 8; + digest[7] = h1; + digest[8] = h2 >> 24; + digest[9] = h2 >> 16; + digest[10] = h2 >> 8; + digest[11] = h2; + digest[12] = h3 >> 24; + digest[13] = h3 >> 16; + digest[14] = h3 >> 8; + digest[15] = h3; + digest[16] = h4 >> 24; + digest[17] = h4 >> 16; + digest[18] = h4 >> 8; + digest[19] = h4; + digest[20] = h5 >> 24; + digest[21] = h5 >> 16; + digest[22] = h5 >> 8; + digest[23] = h5; + digest[24] = h6 >> 24; + digest[25] = h6 >> 16; + digest[26] = h6 >> 8; + digest[27] = h6; + + if(type == SHA_256) + { + digest[28] = h7 >> 24; + digest[29] = h7 >> 16; + digest[30] = h7 >> 8; + digest[31] = h7; + } + + // reset state + switch(type) + { + case SHA_224: + h0 = H[0]; + h1 = H[1]; + h2 = H[2]; + h3 = H[3]; + h4 = H[4]; + h5 = H[5]; + h6 = H[6]; + h7 = H[7]; + break; + + case SHA_256: + h0 = H[8]; + h1 = H[9]; + h2 = H[10]; + h3 = H[11]; + h4 = H[12]; + h5 = H[13]; + h6 = H[14]; + h7 = H[15]; + break; + } + totalBufferLength = 0; + bufferLength = 0; +} + +void SHA2_32::computeBlock(uint32_t *h02, + uint32_t *h12, + uint32_t *h22, + uint32_t *h32, + uint32_t *h42, + uint32_t *h52, + uint32_t *h62, + uint32_t *h72, + uint8_t *buffer) +{ + uint32_t w[64]; + for(int t = 0; t < 16; ++t) + w[t] = (buffer[t*4] << 24) | (buffer[t*4+1] << 16) | (buffer[t*4+2] << 8) | buffer[t*4+3]; + for(int t = 16; t < 64; ++t) + w[t] = SSIG1(w[t-2]) + w[t-7] + SSIG0(w[t-15]) + w[t-16]; + + uint32_t a = *h02, b = *h12, c = *h22, d = *h32, e = *h42, f = *h52, g = *h62, h = *h72; + for(int t = 0; t < 64; ++t) + { + uint32_t T1 = h + BSIG1(e) + CH(e,f,g) + K[t] + w[t]; + uint32_t T2 = BSIG0(a) + MAJ(a,b,c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + *h02 += a; + *h12 += b; + *h22 += c; + *h32 += d; + *h42 += e; + *h52 += f; + *h62 += g; + *h72 += h; +} + +void SHA2_32::computeDigest(SHA_32_TYPE type, uint8_t *digest, uint8_t *in, uint32_t length) +{ + uint32_t h0 = H[type*8], h1 = H[type*8+1], h2 = H[type*8+2], h3 = H[type*8+3]; + uint32_t h4 = H[type*8+4], h5 = H[type*8+5], h6 = H[type*8+6], h7 = H[type*8+7]; + int offset = 0; + while(length - offset >= 64) + { + computeBlock(&h0, &h1, &h2, &h3, &h4, &h5, &h6, &h7, &in[offset]); + offset += 64; + } + uint8_t bufferLength = length-offset; + uint8_t buffer[64]; + memcpy(buffer, &in[offset],bufferLength); + uint16_t padding; + if(length % 64 < 56) + padding = 56 - (length % 64); + else + padding = 56 + (64 - (length % 64)); + buffer[bufferLength] = 0x80; + bufferLength++; + padding--; + while(padding > 0) + { + if(bufferLength == 64) + { + computeBlock(&h0, &h1, &h2, &h3, &h4, &h5, &h6, &h7, buffer); + bufferLength = 0; + } + buffer[bufferLength] = 0; + bufferLength++; + padding--; + } + uint64_t lengthBit = length * 8; + uint32_t lengthBitLow = lengthBit; + uint32_t lengthBitHigh = lengthBit >> 32; + uint8_t tmp[4]; + tmp[0] = lengthBitLow >> 24; + tmp[1] = lengthBitLow >> 16; + tmp[2] = lengthBitLow >> 8; + tmp[3] = lengthBitLow; + memcpy(&buffer[60], tmp, 4); + tmp[0] = lengthBitHigh >> 24; + tmp[1] = lengthBitHigh >> 16; + tmp[2] = lengthBitHigh >> 8; + tmp[3] = lengthBitHigh; + memcpy(&buffer[56], tmp, 4); + computeBlock(&h0, &h1, &h2, &h3, &h4, &h5, &h6, &h7, buffer); + + digest[0] = h0 >> 24; + digest[1] = h0 >> 16; + digest[2] = h0 >> 8; + digest[3] = h0; + digest[4] = h1 >> 24; + digest[5] = h1 >> 16; + digest[6] = h1 >> 8; + digest[7] = h1; + digest[8] = h2 >> 24; + digest[9] = h2 >> 16; + digest[10] = h2 >> 8; + digest[11] = h2; + digest[12] = h3 >> 24; + digest[13] = h3 >> 16; + digest[14] = h3 >> 8; + digest[15] = h3; + digest[16] = h4 >> 24; + digest[17] = h4 >> 16; + digest[18] = h4 >> 8; + digest[19] = h4; + digest[20] = h5 >> 24; + digest[21] = h5 >> 16; + digest[22] = h5 >> 8; + digest[23] = h5; + digest[24] = h6 >> 24; + digest[25] = h6 >> 16; + digest[26] = h6 >> 8; + digest[27] = h6; + + if(type == SHA_256) + { + digest[28] = h7 >> 24; + digest[29] = h7 >> 16; + digest[30] = h7 >> 8; + digest[31] = h7; + } +}