var 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]
function ch(x,y,z)
{
return (x & y) | (~x & z);
}
function maj(x,y,z)
{
return (x & y) | (x & z) | (y & z);
}
function sigma0(x)
{
return rotr(2, x) | rotr(13, x) | rotr(22, x)
}
function sigma1(x)
{
return rotr(6, x) | rotr(11, x) | rotr(25,x)
}
function lsigma0(x)
{
return rotr(7, x) | rotr(18, x) | shr(3, x);
}
function lsigma1(x)
{
return rotr(17, x) | rotr(19, x) | shr(10, x);
}
// rotate right
function rotr(n, x)
{
return (x >> n) | (x << (32-n));
}
// shift right
function shr(n, x)
{
return x >> n;
}
function pad(str)
{
var msg = new ByteArray();
// msg.length = 512/8;
msg.position = 0;
// write the characters
for( var i=0; i < str.length; i++ ) {
msg.writeByte( str.charCodeAt(i) );
}
// pad it with k zeroes
// (lmod512) +1+ k ≡ 448
var str_length_bits = str.length * 8;
var num_zeroes = 448 - 1 - (str_length_bits % 512);
// write a 1
msg.writeByte( 0x80 );
// we can only write bytes at a time, so let's see how many bytes it is
var num_zeroes_bytes = Math.floor(num_zeroes / 8);
// need to wrap to another block?
if( num_zeroes_bytes < 0 ) {
num_zeroes_bytes += 64
}
trace('num_zeroes_bytes', num_zeroes_bytes);
for( var i=0; i < num_zeroes_bytes; i++ ) {
msg.writeByte(0);
}
// 64 bit block that is the length of the message (in # of bits).
// we ignore the first 32 bits because I'm not sure how to bitwise
// shift a flash number to two 32-bit slices
msg.writeUnsignedInt(0);
// meaning our message can not be longer than (2**33)-1 in length
msg.writeUnsignedInt(str_length_bits);
return msg;
}
// do eeet
var str = "jakes";
var msg = pad(str);
for( var n = 0; n < msg.length; n++ )
{
trace( n + ' : ' + left_pad(msg[n].toString(2)) );
}
function left_pad(str, length=8, padstr='0')
{
while( str.length < length ) {
str = padstr + str;
}
return str;
}
// parse into n 512-bit (64 bytes, 16 words) blocks
// set initial hash value
var H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
var modVal = Math.pow(2, 32);
var block:ByteArray = new ByteArray();
var offset = 0;
msg.position = 0;
while(true)
{
try
{
// read the block
msg.readBytes(block, offset, 64);
trace('reading block from ' + offset);
offset += 64;
// construct the message schedule (64 32-bit words)
var W = [];
block.position = 0;
for( var t = 0; t < 64; t++ )
{
if( t <= 15 )
{
W[t] = block.readByte();
}
else
{
W[t] = lsigma1(W[t-2]) + W[t-7] + lsigma0(W[t-15]) + W[t-16];
}
}
// 8 working variables
var a:uint = H[0];
var b:uint = H[1];
var c:uint = H[2];
var d:uint = H[3];
var e:uint = H[4];
var f:uint = H[5];
var g:uint = H[6];
var h:uint = H[7];
for( t = 0; t < 64; t++ )
{
var T1:uint = h + sigma1(e) + ch(e,f,g) + K[t] + W[t];
//T1 = T1%modVal;
var T2:uint = sigma0(a) + maj(a,b,c);
//T2 = T2%modVal;
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = (T1 + T2);
//a = a%modVal;
}
// compute the i-th intermediate hash value of H(i)
H[0] = (a + H[0]) % modVal;
H[1] = (b + H[1]) % modVal;
H[2] = (c + H[2]) % modVal;
H[3] = (d + H[3]) % modVal;
H[4] = (e + H[4]) % modVal;
H[5] = (f + H[5]) % modVal;
H[6] = (g + H[6]) % modVal;
H[7] = (h + H[7]) % modVal;
}
catch(e)
{
trace('no more blocks, ending at byte ',offset, 'of', msg.length);
// no more bytes to read?
break;
}
}
// sha256('jakes') =
// 1e03a95d8dc846c1c64271998a9865ed1a46d962634df2c9cff5b095dc8b5aca
var hex = '';
for( n = 0; n < 8; n++ )
{
hex += left_pad(H[n].toString(16), 8) + ' ';
}
trace( hex.length + ': ' + hex);