[stupid-crypto] push by ben@links.org - Start using a struct for SHA-256. on 2010-03-14 02:59 GMT

0 views
Skip to first unread message

stupid...@googlecode.com

unread,
Mar 13, 2010, 10:00:37 PM3/13/10
to stupi...@googlegroups.com
Revision: bba972e6c9
Author: Ben Laurie <be...@google.com>
Date: Sat Mar 13 18:58:34 2010
Log: Start using a struct for SHA-256.
http://code.google.com/p/stupid-crypto/source/detail?r=bba972e6c9

Added:
/test/sha256-struct.stupid
Modified:
/src/grammar.y

=======================================
--- /dev/null
+++ /test/sha256-struct.stupid Sat Mar 13 18:58:34 2010
@@ -0,0 +1,197 @@
+"EXPECT:";
+
+struct sha256 (
+ array(uint32, 8) h
+);
+
+function (array(uint8, 32) output) sha256(array(uint8, 64) message, uint32
message_bits ) {
+"This code adapted from Wikipedia pseudocode";
+
+"message must include enough space for padding to happen";
+
+"Note 2: All constants in this pseudo code are in big endian";
+
+"Initialize variables";
+"(first 32 bits of the fractional parts of the square roots of the first 8
primes 2..19):";
+ struct sha256 state = ((0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19));
+
+
+"Initialize table of round constants";
+"(first 32 bits of the fractional parts of the cube roots of the first 64
primes 2..311):";
+array(uint32, 64) 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);
+
+uint32 pad_byte = 0;
+uint32 pad_bit = 0;
+uint32 tmp = 0;
+uint32 tmp2 = 0;
+array(uint32, 64) w =
+ (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+uint32 i = 0;
+uint32 s0 = 0;
+uint32 s1 = 0;
+uint32 a = 0;
+uint32 b = 0;
+uint32 c = 0;
+uint32 d = 0;
+uint32 e = 0;
+uint32 f = 0;
+uint32 g = 0;
+uint32 h = 0;
+uint32 maj = 0;
+uint32 t1 = 0;
+uint32 t2 = 0;
+uint32 ch = 0;
+
+"Pre-processing:";
+"append the bit '1' to the message";
+
+"note that we're using a 32-bit length for now";
+"all the op32, op8 etc are _without_ wrap (where applicable) - i.e. wrap
is an error";
+"they also require left and right to both be the correct type and size";
+"also, we have no precedence, it is up to you to bracket things";
+"rshift is with zero padding";
+
+pad_bit = 7 minus32 (message_bits mod32 8);
+pad_byte = (message_bits plus32 1) rshift32 3;
+message[pad_byte] = message[pad_byte] or8 (1 lshift8 pad_bit);
+
+"append k bits '0', where k is the minimum number >= 0 such that the
+resulting message length (in bits) is congruent to 448 (mod 512)";
+
+"eq32 and friends return a boolean value (which is not even a bit)";
+
+if (pad_bit eq32 0) {
+ pad_bit = 7;
+ pad_byte = pad_byte plus32 1;
+} else {
+ pad_bit = pad_bit minus32 1;
+}
+
+"bor is like C || (i.e. RHS is only executed if LHS is false)";
+
+"448/8 = 56";
+while (((pad_byte mod32 64) ne32 56) bor (pad_bit ne32 7)) {
+ message[pad_byte] = message[pad_byte] and8 (not8 (1 lshift8
pad_bit));
+ if (pad_bit eq32 0) {
+ pad_bit = 7;
+ pad_byte = pad_byte plus32 1;
+ } else {
+ pad_bit = pad_bit minus32 1;
+ }
+}
+
+"append length of message (before pre-processing), in bits, as 64-bit
big-endian integer";
+
+message[pad_byte] = 0;
+message[pad_byte plus32 1] = 0;
+message[pad_byte plus32 2] = 0;
+message[pad_byte plus32 3] = 0;
+
+message[pad_byte plus32 7] = mask32to8 message_bits;
+tmp = message_bits rshift32 8;
+message[pad_byte plus32 6] = mask32to8 tmp;
+tmp = tmp rshift32 8;
+message[pad_byte plus32 5] = mask32to8 tmp;
+tmp = tmp rshift32 8;
+message[pad_byte plus32 4] = mask32to8 tmp;
+
+"for each chunk (we only have one, so don't bother with the loop for now)";
+
+" break chunk into sixteen 32-bit big-endian words w[0..15]";
+tmp = 0;
+while(tmp ne32 16) {
+ tmp2 = tmp lshift32 2;
+ w[tmp] = ((widen8to32 message[tmp2]) lshift32 24)
+ plus32 ((widen8to32 message[tmp2 plus32 1]) lshift32 16)
+ plus32 ((widen8to32 message[tmp2 plus32 2]) lshift32 8)
+ plus32 (widen8to32 message[tmp2 plus32 3]);
+ tmp = tmp plus32 1;
+}
+
+" Extend the sixteen 32-bit words into sixty-four 32-bit words";
+i = 16;
+while(i ne32 64) {
+ s0 = (w[i minus32 15] rrotate32 7) xor32 (w[i minus32 15] rrotate32
18) xor32 (w[i minus32 15] rshift32 3);
+ s1 = (w[i minus32 2] rrotate32 17) xor32 (w[i minus32 2] rrotate32 19)
xor32 (w[i minus32 2] rshift32 10);
+ w[i] = w[i minus32 16] plus32 s0 plus32 w[i minus32 7] plus32 s1;
+ i = i plus32 1;
+}
+
+" Initialize hash value for this chunk:";
+
+a = state.h[0];
+b = state.h[1];
+c = state.h[2];
+d = state.h[3];
+e = state.h[4];
+f = state.h[5];
+g = state.h[6];
+h = state.h[7];
+
+" Main loop:";
+
+i = 0;
+while(i ne32 64) {
+ s0 = (a rrotate32 2) xor32 (a rrotate32 13) xor32 (a rrotate32 22);
+ maj = (a and32 b) xor32 (a and32 c) xor32 (b and32 c);
+ t2 = s0 plus32 maj;
+ s1 = (e rrotate32 6) xor32 (e rrotate32 11) xor32 (e rrotate32 25);
+ ch = (e and32 f) xor32 ((not32 e) and32 g);
+ t1 = h plus32 s1 plus32 ch plus32 k[i] plus32 w[i];
+ h = g;
+ g = f;
+ f = e;
+ e = d plus32 t1;
+ d = c;
+ c = b;
+ b = a;
+ a = t1 plus32 t2;
+ i = i plus32 1;
+}
+
+" Add this chunk's hash to result so far:";
+
+state.h[0] = state.h[0] plus32 a;
+state.h[1] = state.h[1] plus32 b;
+state.h[2] = state.h[2] plus32 c;
+state.h[3] = state.h[3] plus32 d;
+state.h[4] = state.h[4] plus32 e;
+state.h[5] = state.h[5] plus32 f;
+state.h[6] = state.h[6] plus32 g;
+state.h[7] = state.h[7] plus32 h;
+
+"end of outer loop (when we do it)";
+
+"Produce the final hash value (big-endian):
+digest = hash = h0 append h1 append h2 append h3 append h4 append h5
append h6 append h7";
+
+ i = 0;
+ while(i ne32 8) {
+ output[i lshift32 2] = mask32to8 (state.h[i] rshift32 24);
+ output[(i lshift32 2) plus32 1] = mask32to8 (state.h[i] rshift32 16);
+ output[(i lshift32 2) plus32 2] = mask32to8 (state.h[i] rshift32 8);
+ output[(i lshift32 2) plus32 3] = mask32to8 state.h[i];
+ i = i plus32 1;
+ }
+
+}
=======================================
--- /src/grammar.y Sat Mar 13 16:10:17 2010
+++ /src/grammar.y Sat Mar 13 18:58:34 2010
@@ -33,9 +33,9 @@

abstract_decl : type vardecl
{ new Stupid::AbstractDeclare($_[1], $_[2]); }
- | 'array' '(' type ',' VALUE ')'
+ | 'array' '(' type ',' VALUE ')' vardecl
{ new Stupid::AbstractDeclare(
- new Stupid::Type::Array($_[3], $_[5])); }
+ new Stupid::Type::Array($_[3], $_[5]), $_[7]); }
;

function : 'function' '(' arglist ')' WORD '(' arglist ')'
@@ -182,14 +182,18 @@
{ $_[2]; }
;

-val_list : val_list ',' VALUE
+val_list : val_list ',' value
{ $_[1]->append($_[3]); $_[1]; }
- | VALUE
+ | value
{ my $t = new Stupid::ArrayValue(); $t->append($_[1]); $t; }
| STRING
{ Stupid::ArrayFromString($_[1]); }
;

+value : arrayval
+ | VALUE
+ ;
+
vardecl : WORD
;

Reply all
Reply to author
Forward
0 new messages