shithub: mc

ref: 2b1c13ce2d20ce2b4e68e1daf08a1679d94fe397
dir: /lib/crypto/sha256.myr/

View raw version
use std

pkg crypto =
	type sha256
	type sha224

	const sha256	: (data : byte[:] -> byte[32])
	const sha256init	: (st : sha256# -> void)
	const sha256add	: (st : sha256#, data : byte[:] -> void)
	const sha256fin	: (st : sha256# -> byte[32])

	const sha224	: (data : byte[:] -> byte[28])
	const sha224init	: (st : sha224# -> void)
	const sha224add	: (st : sha224#, data : byte[:] -> void)
	const sha224fin	: (st : sha224# -> byte[28])
;;

type sha256 = struct
	x	: uint32[8]
	tail	: byte[64]
	msglen	: uint64
;;

const sha256 = {data
	var st

	sha256init(&st)
	sha256add(&st, data)
	-> sha256fin(&st)
}

const sha256init = {st
	st.x[0] = 0x6A09E667
	st.x[1] = 0xBB67AE85
	st.x[2] = 0x3C6EF372
	st.x[3] = 0xA54FF53A
	st.x[4] = 0x510e527f
	st.x[5] = 0x9b05688c
	st.x[6] = 0x1f83d9ab
	st.x[7] = 0x5be0cd19
	st.msglen = 0
}

const sha256add = {st, data
	var n, ntail

	ntail = st.msglen % 64
	st.msglen += data.len
	if ntail > 0
		n = std.min(64 - ntail, data.len)
		std.slcp(st.tail[ntail:ntail + n], data[:n])
		data = data[n:]
		if n + ntail < 64
			-> void
		;;
		step(st.x[:], st.tail[:])
	;;

	while data.len >= 64
		step(st.x[:], data[:64])
		data = data[64:]
	;;

	ntail = st.msglen % 64
	std.slcp(st.tail[:ntail], data)
}

const sha256fin = {st
	var r : byte[32]

	tail(st.x[:], st.msglen, st.tail[:])

	pack(r[0:4], st.x[0])
	pack(r[4:8], st.x[1])
	pack(r[8:12], st.x[2])
	pack(r[12:16], st.x[3])
	pack(r[16:20], st.x[4])
	pack(r[20:24], st.x[5])
	pack(r[24:28], st.x[6])
	pack(r[28:32], st.x[7])
	-> r
}

type sha224 = struct
	x : uint32[8]
	tail : byte[64]
	msglen : uint64
;;

const sha224 = {data
	var st

	sha224init(&st)
	sha224add(&st, data)
	-> sha224fin(&st)
}

const sha224init = {st
	st.x[0] = 0xc1059ed8
	st.x[1] = 0x367cd507
	st.x[2] = 0x3070dd17
	st.x[3] = 0xf70e5939
	st.x[4] = 0xffc00b31
	st.x[5] = 0x68581511
	st.x[6] = 0x64f98fa7
	st.x[7] = 0xbefa4fa4
	st.msglen = 0
}

const sha224add = {st, data
	var n, ntail

	ntail = st.msglen % 64
	st.msglen += data.len
	if ntail > 0
		n = std.min(64 - ntail, data.len)
		std.slcp(st.tail[ntail:ntail + n], data[:n])
		data = data[n:]
		if n + ntail < 64
			-> void
		;;
		step(st.x[:], st.tail[:])
	;;

	while data.len >= 64
		step(st.x[:], data[:64])
		data = data[64:]
	;;

	ntail = st.msglen % 64
	std.slcp(st.tail[:ntail], data)
}

const sha224fin = {st
	var r : byte[28]

	tail(st.x[:], st.msglen, st.tail[:])

	pack(r[0:4], st.x[0])
	pack(r[4:8], st.x[1])
	pack(r[8:12], st.x[2])
	pack(r[12:16], st.x[3])
	pack(r[16:20], st.x[4])
	pack(r[20:24], st.x[5])
	pack(r[24:28], st.x[6])
	-> r
}


const tail = {x, msglen, tail
	var ntail

	/* append first padding block */
	ntail = msglen % 64
	tail[ntail++] = 0x80
	std.slfill(tail[ntail:], 0)
	if 64 - ntail < 8
		step(x, tail)
		std.slfill(tail, 0)
	;;

	/* append size block */
	tail[56] = ((msglen * 8) >> 56	: byte)
	tail[57] = ((msglen * 8) >> 48	: byte)
	tail[58] = ((msglen * 8) >> 40	: byte)
	tail[59] = ((msglen * 8) >> 32	: byte)
	tail[60] = ((msglen * 8) >> 24	: byte)
	tail[61] = ((msglen * 8) >> 16	: byte)
	tail[62] = ((msglen * 8) >> 8	: byte)
	tail[63] = ((msglen * 8) >> 0	: byte)
	step(x, tail)
}

const step = {x, msg
	var a, b, c, d, e, f, g, h
	var s00, s01, s02, s03, s04, s05, s06, s07
	var s08, s09, s10, s11, s12, s13, s14, s15
	var s16, s17, s18, s19, s20, s21, s22, s23
	var s24, s25, s26, s27, s28, s29, s30, s31
	var s32, s33, s34, s35, s36, s37, s38, s39
	var s40, s41, s42, s43, s44, s45, s46, s47
	var s48, s49, s50, s51, s52, s53, s54, s55
	var s56, s57, s58, s59, s60, s61, s62, s63

	a = x[0]
	b = x[1]
	c = x[2]
	d = x[3]
	e = x[4]
	f = x[5]
	g = x[6]
	h = x[7]

	s00 = unpack(msg[ 0: 4])
	s01 = unpack(msg[ 4: 8])
	s02 = unpack(msg[ 8:12])
	s03 = unpack(msg[12:16])
	s04 = unpack(msg[16:20])
	s05 = unpack(msg[20:24])
	s06 = unpack(msg[24:28])
	s07 = unpack(msg[28:32])
	s08 = unpack(msg[32:36])
	s09 = unpack(msg[36:40])
	s10 = unpack(msg[40:44])
	s11 = unpack(msg[44:48])
	s12 = unpack(msg[48:52])
	s13 = unpack(msg[52:56])
	s14 = unpack(msg[56:60])
	s15 = unpack(msg[60:64])

	s16 = s00 + s09 + (((s01 << 25) | (s01 >> 7)) ^ ((s01 << 14) | (s01 >> 18)) ^ (s01 >> 3)) + (((s14 << 15) | (s14 >> 17)) ^ ((s14 << (32- 19)) | (s14 >> 19)) ^ (s14 >> 10));
	s17 = s01 + s10 + (((s02 << 25) | (s02 >> 7)) ^ ((s02 << 14) | (s02 >> 18)) ^ (s02 >> 3)) + (((s15 << 15) | (s15 >> 17)) ^ ((s15 << (32- 19)) | (s15 >> 19)) ^ (s15 >> 10));
	s18 = s02 + s11 + (((s03 << 25) | (s03 >> 7)) ^ ((s03 << 14) | (s03 >> 18)) ^ (s03 >> 3)) + (((s16 << 15) | (s16 >> 17)) ^ ((s16 << (32- 19)) | (s16 >> 19)) ^ (s16 >> 10));
	s19 = s03 + s12 + (((s04 << 25) | (s04 >> 7)) ^ ((s04 << 14) | (s04 >> 18)) ^ (s04 >> 3)) + (((s17 << 15) | (s17 >> 17)) ^ ((s17 << (32- 19)) | (s17 >> 19)) ^ (s17 >> 10));
	s20 = s04 + s13 + (((s05 << 25) | (s05 >> 7)) ^ ((s05 << 14) | (s05 >> 18)) ^ (s05 >> 3)) + (((s18 << 15) | (s18 >> 17)) ^ ((s18 << (32- 19)) | (s18 >> 19)) ^ (s18 >> 10));
	s21 = s05 + s14 + (((s06 << 25) | (s06 >> 7)) ^ ((s06 << 14) | (s06 >> 18)) ^ (s06 >> 3)) + (((s19 << 15) | (s19 >> 17)) ^ ((s19 << (32- 19)) | (s19 >> 19)) ^ (s19 >> 10));
	s22 = s06 + s15 + (((s07 << 25) | (s07 >> 7)) ^ ((s07 << 14) | (s07 >> 18)) ^ (s07 >> 3)) + (((s20 << 15) | (s20 >> 17)) ^ ((s20 << (32- 19)) | (s20 >> 19)) ^ (s20 >> 10));
	s23 = s07 + s16 + (((s08 << 25) | (s08 >> 7)) ^ ((s08 << 14) | (s08 >> 18)) ^ (s08 >> 3)) + (((s21 << 15) | (s21 >> 17)) ^ ((s21 << (32- 19)) | (s21 >> 19)) ^ (s21 >> 10));
	s24 = s08 + s17 + (((s09 << 25) | (s09 >> 7)) ^ ((s09 << 14) | (s09 >> 18)) ^ (s09 >> 3)) + (((s22 << 15) | (s22 >> 17)) ^ ((s22 << (32- 19)) | (s22 >> 19)) ^ (s22 >> 10));
	s25 = s09 + s18 + (((s10 << 25) | (s10 >> 7)) ^ ((s10 << 14) | (s10 >> 18)) ^ (s10 >> 3)) + (((s23 << 15) | (s23 >> 17)) ^ ((s23 << (32- 19)) | (s23 >> 19)) ^ (s23 >> 10));
	s26 = s10 + s19 + (((s11 << 25) | (s11 >> 7)) ^ ((s11 << 14) | (s11 >> 18)) ^ (s11 >> 3)) + (((s24 << 15) | (s24 >> 17)) ^ ((s24 << (32- 19)) | (s24 >> 19)) ^ (s24 >> 10));
	s27 = s11 + s20 + (((s12 << 25) | (s12 >> 7)) ^ ((s12 << 14) | (s12 >> 18)) ^ (s12 >> 3)) + (((s25 << 15) | (s25 >> 17)) ^ ((s25 << (32- 19)) | (s25 >> 19)) ^ (s25 >> 10));
	s28 = s12 + s21 + (((s13 << 25) | (s13 >> 7)) ^ ((s13 << 14) | (s13 >> 18)) ^ (s13 >> 3)) + (((s26 << 15) | (s26 >> 17)) ^ ((s26 << (32- 19)) | (s26 >> 19)) ^ (s26 >> 10));
	s29 = s13 + s22 + (((s14 << 25) | (s14 >> 7)) ^ ((s14 << 14) | (s14 >> 18)) ^ (s14 >> 3)) + (((s27 << 15) | (s27 >> 17)) ^ ((s27 << (32- 19)) | (s27 >> 19)) ^ (s27 >> 10));
	s30 = s14 + s23 + (((s15 << 25) | (s15 >> 7)) ^ ((s15 << 14) | (s15 >> 18)) ^ (s15 >> 3)) + (((s28 << 15) | (s28 >> 17)) ^ ((s28 << (32- 19)) | (s28 >> 19)) ^ (s28 >> 10));
	s31 = s15 + s24 + (((s16 << 25) | (s16 >> 7)) ^ ((s16 << 14) | (s16 >> 18)) ^ (s16 >> 3)) + (((s29 << 15) | (s29 >> 17)) ^ ((s29 << (32- 19)) | (s29 >> 19)) ^ (s29 >> 10));
	s32 = s16 + s25 + (((s17 << 25) | (s17 >> 7)) ^ ((s17 << 14) | (s17 >> 18)) ^ (s17 >> 3)) + (((s30 << 15) | (s30 >> 17)) ^ ((s30 << (32- 19)) | (s30 >> 19)) ^ (s30 >> 10));
	s33 = s17 + s26 + (((s18 << 25) | (s18 >> 7)) ^ ((s18 << 14) | (s18 >> 18)) ^ (s18 >> 3)) + (((s31 << 15) | (s31 >> 17)) ^ ((s31 << (32- 19)) | (s31 >> 19)) ^ (s31 >> 10));
	s34 = s18 + s27 + (((s19 << 25) | (s19 >> 7)) ^ ((s19 << 14) | (s19 >> 18)) ^ (s19 >> 3)) + (((s32 << 15) | (s32 >> 17)) ^ ((s32 << (32- 19)) | (s32 >> 19)) ^ (s32 >> 10));
	s35 = s19 + s28 + (((s20 << 25) | (s20 >> 7)) ^ ((s20 << 14) | (s20 >> 18)) ^ (s20 >> 3)) + (((s33 << 15) | (s33 >> 17)) ^ ((s33 << (32- 19)) | (s33 >> 19)) ^ (s33 >> 10));
	s36 = s20 + s29 + (((s21 << 25) | (s21 >> 7)) ^ ((s21 << 14) | (s21 >> 18)) ^ (s21 >> 3)) + (((s34 << 15) | (s34 >> 17)) ^ ((s34 << (32- 19)) | (s34 >> 19)) ^ (s34 >> 10));
	s37 = s21 + s30 + (((s22 << 25) | (s22 >> 7)) ^ ((s22 << 14) | (s22 >> 18)) ^ (s22 >> 3)) + (((s35 << 15) | (s35 >> 17)) ^ ((s35 << (32- 19)) | (s35 >> 19)) ^ (s35 >> 10));
	s38 = s22 + s31 + (((s23 << 25) | (s23 >> 7)) ^ ((s23 << 14) | (s23 >> 18)) ^ (s23 >> 3)) + (((s36 << 15) | (s36 >> 17)) ^ ((s36 << (32- 19)) | (s36 >> 19)) ^ (s36 >> 10));
	s39 = s23 + s32 + (((s24 << 25) | (s24 >> 7)) ^ ((s24 << 14) | (s24 >> 18)) ^ (s24 >> 3)) + (((s37 << 15) | (s37 >> 17)) ^ ((s37 << (32- 19)) | (s37 >> 19)) ^ (s37 >> 10));
	s40 = s24 + s33 + (((s25 << 25) | (s25 >> 7)) ^ ((s25 << 14) | (s25 >> 18)) ^ (s25 >> 3)) + (((s38 << 15) | (s38 >> 17)) ^ ((s38 << (32- 19)) | (s38 >> 19)) ^ (s38 >> 10));
	s41 = s25 + s34 + (((s26 << 25) | (s26 >> 7)) ^ ((s26 << 14) | (s26 >> 18)) ^ (s26 >> 3)) + (((s39 << 15) | (s39 >> 17)) ^ ((s39 << (32- 19)) | (s39 >> 19)) ^ (s39 >> 10));
	s42 = s26 + s35 + (((s27 << 25) | (s27 >> 7)) ^ ((s27 << 14) | (s27 >> 18)) ^ (s27 >> 3)) + (((s40 << 15) | (s40 >> 17)) ^ ((s40 << (32- 19)) | (s40 >> 19)) ^ (s40 >> 10));
	s43 = s27 + s36 + (((s28 << 25) | (s28 >> 7)) ^ ((s28 << 14) | (s28 >> 18)) ^ (s28 >> 3)) + (((s41 << 15) | (s41 >> 17)) ^ ((s41 << (32- 19)) | (s41 >> 19)) ^ (s41 >> 10));
	s44 = s28 + s37 + (((s29 << 25) | (s29 >> 7)) ^ ((s29 << 14) | (s29 >> 18)) ^ (s29 >> 3)) + (((s42 << 15) | (s42 >> 17)) ^ ((s42 << (32- 19)) | (s42 >> 19)) ^ (s42 >> 10));
	s45 = s29 + s38 + (((s30 << 25) | (s30 >> 7)) ^ ((s30 << 14) | (s30 >> 18)) ^ (s30 >> 3)) + (((s43 << 15) | (s43 >> 17)) ^ ((s43 << (32- 19)) | (s43 >> 19)) ^ (s43 >> 10));
	s46 = s30 + s39 + (((s31 << 25) | (s31 >> 7)) ^ ((s31 << 14) | (s31 >> 18)) ^ (s31 >> 3)) + (((s44 << 15) | (s44 >> 17)) ^ ((s44 << (32- 19)) | (s44 >> 19)) ^ (s44 >> 10));
	s47 = s31 + s40 + (((s32 << 25) | (s32 >> 7)) ^ ((s32 << 14) | (s32 >> 18)) ^ (s32 >> 3)) + (((s45 << 15) | (s45 >> 17)) ^ ((s45 << (32- 19)) | (s45 >> 19)) ^ (s45 >> 10));
	s48 = s32 + s41 + (((s33 << 25) | (s33 >> 7)) ^ ((s33 << 14) | (s33 >> 18)) ^ (s33 >> 3)) + (((s46 << 15) | (s46 >> 17)) ^ ((s46 << (32- 19)) | (s46 >> 19)) ^ (s46 >> 10));
	s49 = s33 + s42 + (((s34 << 25) | (s34 >> 7)) ^ ((s34 << 14) | (s34 >> 18)) ^ (s34 >> 3)) + (((s47 << 15) | (s47 >> 17)) ^ ((s47 << (32- 19)) | (s47 >> 19)) ^ (s47 >> 10));
	s50 = s34 + s43 + (((s35 << 25) | (s35 >> 7)) ^ ((s35 << 14) | (s35 >> 18)) ^ (s35 >> 3)) + (((s48 << 15) | (s48 >> 17)) ^ ((s48 << (32- 19)) | (s48 >> 19)) ^ (s48 >> 10));
	s51 = s35 + s44 + (((s36 << 25) | (s36 >> 7)) ^ ((s36 << 14) | (s36 >> 18)) ^ (s36 >> 3)) + (((s49 << 15) | (s49 >> 17)) ^ ((s49 << (32- 19)) | (s49 >> 19)) ^ (s49 >> 10));
	s52 = s36 + s45 + (((s37 << 25) | (s37 >> 7)) ^ ((s37 << 14) | (s37 >> 18)) ^ (s37 >> 3)) + (((s50 << 15) | (s50 >> 17)) ^ ((s50 << (32- 19)) | (s50 >> 19)) ^ (s50 >> 10));
	s53 = s37 + s46 + (((s38 << 25) | (s38 >> 7)) ^ ((s38 << 14) | (s38 >> 18)) ^ (s38 >> 3)) + (((s51 << 15) | (s51 >> 17)) ^ ((s51 << (32- 19)) | (s51 >> 19)) ^ (s51 >> 10));
	s54 = s38 + s47 + (((s39 << 25) | (s39 >> 7)) ^ ((s39 << 14) | (s39 >> 18)) ^ (s39 >> 3)) + (((s52 << 15) | (s52 >> 17)) ^ ((s52 << (32- 19)) | (s52 >> 19)) ^ (s52 >> 10));
	s55 = s39 + s48 + (((s40 << 25) | (s40 >> 7)) ^ ((s40 << 14) | (s40 >> 18)) ^ (s40 >> 3)) + (((s53 << 15) | (s53 >> 17)) ^ ((s53 << (32- 19)) | (s53 >> 19)) ^ (s53 >> 10));
	s56 = s40 + s49 + (((s41 << 25) | (s41 >> 7)) ^ ((s41 << 14) | (s41 >> 18)) ^ (s41 >> 3)) + (((s54 << 15) | (s54 >> 17)) ^ ((s54 << (32- 19)) | (s54 >> 19)) ^ (s54 >> 10));
	s57 = s41 + s50 + (((s42 << 25) | (s42 >> 7)) ^ ((s42 << 14) | (s42 >> 18)) ^ (s42 >> 3)) + (((s55 << 15) | (s55 >> 17)) ^ ((s55 << (32- 19)) | (s55 >> 19)) ^ (s55 >> 10));
	s58 = s42 + s51 + (((s43 << 25) | (s43 >> 7)) ^ ((s43 << 14) | (s43 >> 18)) ^ (s43 >> 3)) + (((s56 << 15) | (s56 >> 17)) ^ ((s56 << (32- 19)) | (s56 >> 19)) ^ (s56 >> 10));
	s59 = s43 + s52 + (((s44 << 25) | (s44 >> 7)) ^ ((s44 << 14) | (s44 >> 18)) ^ (s44 >> 3)) + (((s57 << 15) | (s57 >> 17)) ^ ((s57 << (32- 19)) | (s57 >> 19)) ^ (s57 >> 10));
	s60 = s44 + s53 + (((s45 << 25) | (s45 >> 7)) ^ ((s45 << 14) | (s45 >> 18)) ^ (s45 >> 3)) + (((s58 << 15) | (s58 >> 17)) ^ ((s58 << (32- 19)) | (s58 >> 19)) ^ (s58 >> 10));
	s61 = s45 + s54 + (((s46 << 25) | (s46 >> 7)) ^ ((s46 << 14) | (s46 >> 18)) ^ (s46 >> 3)) + (((s59 << 15) | (s59 >> 17)) ^ ((s59 << (32- 19)) | (s59 >> 19)) ^ (s59 >> 10));
	s62 = s46 + s55 + (((s47 << 25) | (s47 >> 7)) ^ ((s47 << 14) | (s47 >> 18)) ^ (s47 >> 3)) + (((s60 << 15) | (s60 >> 17)) ^ ((s60 << (32- 19)) | (s60 >> 19)) ^ (s60 >> 10));
	s63 = s47 + s56 + (((s48 << 25) | (s48 >> 7)) ^ ((s48 << 14) | (s48 >> 18)) ^ (s48 >> 3)) + (((s61 << 15) | (s61 >> 17)) ^ ((s61 << (32- 19)) | (s61 >> 19)) ^ (s61 >> 10));

		
	h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x428a2f98 + s00;
	d += h;  h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c));
	g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x71374491 + s01;
	c += g;  g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b));
	f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0xb5c0fbcf + s02;
	b += f;  f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a));
	e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0xe9b5dba5 + s03;
	a += e;  e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h));
	d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x3956c25b + s04;
	h += d;  d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g));
	c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x59f111f1 + s05;
	g += c;  c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f));
	b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x923f82a4 + s06;
	f += b;  b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e));
	a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0xab1c5ed5 + s07;
	e += a;  a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d));
	h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0xd807aa98 + s08;
	d += h;  h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c));
	g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x12835b01 + s09;
	c += g;  g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b));
	f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x243185be + s10;
	b += f;  f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a));
	e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x550c7dc3 + s11;
	a += e;  e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h));
	d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x72be5d74 + s12;
	h += d;  d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g));
	c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x80deb1fe + s13;
	g += c;  c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f));
	b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x9bdc06a7 + s14;
	f += b;  b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e));
	a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0xc19bf174 + s15;
	e += a;  a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d));
	h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0xe49b69c1 + s16;
	d += h;  h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c));
	g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0xefbe4786 + s17;
	c += g;  g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b));
	f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x0fc19dc6 + s18;
	b += f;  f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a));
	e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x240ca1cc + s19;
	a += e;  e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h));
	d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x2de92c6f + s20;
	h += d;  d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g));
	c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x4a7484aa + s21;
	g += c;  c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f));
	b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x5cb0a9dc + s22;
	f += b;  b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e));
	a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x76f988da + s23;
	e += a;  a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d));
	h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x983e5152 + s24;
	d += h;  h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c));
	g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0xa831c66d + s25;
	c += g;  g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b));
	f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0xb00327c8 + s26;
	b += f;  f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a));
	e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0xbf597fc7 + s27;
	a += e;  e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h));
	d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0xc6e00bf3 + s28;
	h += d;  d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g));
	c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0xd5a79147 + s29;
	g += c;  c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f));
	b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x06ca6351 + s30;
	f += b;  b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e));
	a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x14292967 + s31;
	e += a;  a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d));
	h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x27b70a85 + s32;
	d += h;  h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c));
	g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x2e1b2138 + s33;
	c += g;  g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b));
	f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x4d2c6dfc + s34;
	b += f;  f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a));
	e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x53380d13 + s35;
	a += e;  e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h));
	d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x650a7354 + s36;
	h += d;  d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g));
	c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x766a0abb + s37;
	g += c;  c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f));
	b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x81c2c92e + s38;
	f += b;  b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e));
	a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x92722c85 + s39;
	e += a;  a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d));
	h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0xa2bfe8a1 + s40;
	d += h;  h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c));
	g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0xa81a664b + s41;
	c += g;  g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b));
	f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0xc24b8b70 + s42;
	b += f;  f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a));
	e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0xc76c51a3 + s43;
	a += e;  e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h));
	d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0xd192e819 + s44;
	h += d;  d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g));
	c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0xd6990624 + s45;
	g += c;  c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f));
	b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0xf40e3585 + s46;
	f += b;  b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e));
	a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x106aa070 + s47;
	e += a;  a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d));
	h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x19a4c116 + s48;
	d += h;  h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c));
	g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x1e376c08 + s49;
	c += g;  g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b));
	f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x2748774c + s50;
	b += f;  f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a));
	e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x34b0bcb5 + s51;
	a += e;  e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h));
	d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x391c0cb3 + s52;
	h += d;  d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g));
	c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x4ed8aa4a + s53;
	g += c;  c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f));
	b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x5b9cca4f + s54;
	f += b;  b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e));
	a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x682e6ff3 + s55;
	e += a;  a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d));
	h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x748f82ee + s56;
	d += h;  h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c));
	g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x78a5636f + s57;
	c += g;  g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b));
	f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x84c87814 + s58;
	b += f;  f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a));
	e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x8cc70208 + s59;
	a += e;  e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h));
	d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x90befffa + s60;
	h += d;  d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g));
	c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0xa4506ceb + s61;
	g += c;  c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f));
	b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0xbef9a3f7 + s62;
	f += b;  b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e));
	a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0xc67178f2 + s63;
	e += a;  a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d));

	x[0] += a
	x[1] += b
	x[2] += c
	x[3] += d
	x[4] += e
	x[5] += f
	x[6] += g
	x[7] += h
}

const unpack = {b
	var v : uint32

	v = 0
	v |= (b[0]	: uint32) << 24
	v |= (b[1]	: uint32) << 16
	v |= (b[2]	: uint32) << 8
	v |= (b[3]	: uint32) << 0
	-> v
}

const pack = {out, v
	out[0]  = (v >> 24	: byte)
	out[1]  = (v >> 16	: byte)
	out[2]  = (v >> 8	: byte)
	out[3]  = (v >> 0	: byte)
}