1 1. Implementation von SHA256 inkl. UART gelaber (noch mit human Stuff)
3 <syntaxhighlight lang="cpp">
13 // put your setup code here, to run once:
15 Serial.println("Input");
19 recdata = Serial.read();
20 if (recdata == 0x0D && poscnt == 0) {
22 Serial.println("Input");
25 if (poscnt >=32 || recdata == 0x0D) {
27 Serial.print("Received: ");
28 Serial.println(input);
29 sha256(&summed, input, poscnt*8);
30 Serial.print("SHA256: ");
31 for (int i = 0; i <= 31; i++) {
32 Serial.print(summed[i], HEX);
37 Serial.print("Input");
40 input[poscnt] = recdata;
41 Serial.println(input);
55 uint32_t sha256_init_vector[]={
56 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
57 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 };
60 /*************************************************************************/
63 * \brief \c sh256_init initialises a sha256 context for hashing.
64 * \c sh256_init c initialises the given sha256 context for hashing
65 * @param state pointer to a sha256 context
68 void sha256_init(sha256_ctx_t *state){
70 memcpy(state->h, sha256_init_vector, 8*4);
73 /*************************************************************************/
76 * rotate x right by n positions
78 uint32_t rotr32( uint32_t x, uint8_t n){
79 return ((x>>n) | (x<<(32-n)));
83 /*************************************************************************/
85 // #define CHANGE_ENDIAN32(x) (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8))
87 uint32_t change_endian32(uint32_t x){
88 return (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8));
92 /*************************************************************************/
94 /* sha256 functions as macros for speed and size, cause they are called only once */
96 #define CH(x,y,z) (((x)&(y)) ^ ((~(x))&(z)))
97 #define MAJ(x,y,z) (((x)&(y)) ^ ((x)&(z)) ^ ((y)&(z)))
99 #define SIGMA0(x) (rotr32((x),2) ^ rotr32((x),13) ^ rotr32((x),22))
100 #define SIGMA1(x) (rotr32((x),6) ^ rotr32((x),11) ^ rotr32((x),25))
101 #define SIGMA_a(x) (rotr32((x),7) ^ rotr32((x),18) ^ ((x)>>3))
102 #define SIGMA_b(x) (rotr32((x),17) ^ rotr32((x),19) ^ ((x)>>10))
106 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
107 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
108 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
109 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
110 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
111 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
112 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
113 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
117 /*************************************************************************/
120 * block must be, 512, Bit = 64, Byte, long !!!
122 void sha256_nextBlock (sha256_ctx_t *state, const void* block){
123 uint32_t w[64]; /* this is 256, byte, large, */
128 #if defined LITTLE_ENDIAN
129 for (i=0; i<16; ++i){
130 w[i]= change_endian32(((uint32_t*)block)[i]);
132 #elif defined BIG_ENDIAN
133 memcpy((void*)w, block, 64);
135 for (i=16; i<64; ++i){
136 w[i] = SIGMA_b(w[i-2]) + w[i-7] + SIGMA_a(w[i-15]) + w[i-16];
139 /* init working variables */
140 memcpy((void*)a,(void*)(state->h), 8*4);
142 /* do the, fun stuff, */
143 for (i=0; i<64; ++i){
144 t1 = a[7] + SIGMA1(a[4]) + CH(a[4],a[5],a[6]) + k[i] + w[i];
145 t2 = SIGMA0(a[0]) + MAJ(a[0],a[1],a[2]);
146 memmove(&(a[1]), &(a[0]), 7*4); /* a[7]=a[6]; a[6]=a[5]; a[5]=a[4]; a[4]=a[3]; a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; */
151 /* update, the, state, */
155 state->length += 512;
159 /*************************************************************************/
162 * \brief function to process the last block being hashed
163 * @param state Pointer to the context in which this block should be processed.
164 * @param block Pointer to the message wich should be hashed.
165 * @param length is the length of only THIS block in BITS not in bytes!
166 * bits are big endian, meaning high bits come first.
167 * if you have a message with bits at the end, the byte must be padded with zeros
169 void sha256_lastBlock(sha256_ctx_t *state, const void* block, uint16_t length){
170 uint8_t lb[SHA256_BLOCK_BITS/8]; /* local block */
171 while(length>=SHA256_BLOCK_BITS){
172 sha256_nextBlock(state, block);
173 length -= SHA256_BLOCK_BITS;
174 block = (uint8_t*)block+SHA256_BLOCK_BYTES;
177 state->length += length;
178 memcpy (&(lb[0]), block, length/8);
180 /* set the final one bit */
181 if (length & 0x7){ // if we have single bits at the end
182 lb[length/8] = ((uint8_t*)(block))[length/8];
187 lb[length/8] |= 0x80>>(length & 0x7);
188 length =(length >> 3) + 1; /* from now on length contains the number of BYTES in lb*/
190 if (length>64-8){ /* not enouth space for 64bit length value */
191 memset((void*)(&(lb[length])), 0, 64-length);
192 sha256_nextBlock(state, lb);
193 state->length -= 512;
196 memset((void*)(&(lb[length])), 0, 56-length);
197 /* store the 64bit length value */
198 #if defined LITTLE_ENDIAN
199 /* this is now rolled up */
201 for (i=1; i<=8; ++i){
202 lb[55+i] = (uint8_t)(state->length>>(64- 8*i));
204 #elif defined BIG_ENDIAN
205 *((uint64_t)&(lb[56])) = state->length;
207 sha256_nextBlock(state, lb);
211 /*************************************************************************/
216 void sha256(sha256_hash_t *dest, const void* msg, uint32_t length){ /* length could be choosen longer but this is for µC */
219 while(length >= SHA256_BLOCK_BITS){
220 sha256_nextBlock(&s, msg);
221 msg = (uint8_t*)msg + SHA256_BLOCK_BITS/8;
222 length -= SHA256_BLOCK_BITS;
224 sha256_lastBlock(&s, msg, length);
225 sha256_ctx2hash(dest,&s);
230 /*************************************************************************/
232 void sha256_ctx2hash(sha256_hash_t *dest, const sha256_ctx_t *state){
233 #if defined LITTLE_ENDIAN
236 ((uint32_t*)dest)[i] = change_endian32(state->h[i]);
239 if (dest != state->h)
240 memcpy(dest, state->h, SHA256_HASH_BITS/8);