Livt packages
Livt.Crypto
Version 1.0.5
Fixed-size cryptographic components for Livt, including AES, ChaCha20, SHA, MACs, and key derivation.
Published files (69)
src/hash/Sha256.lvt
namespace Livt.Crypto.Hash
using Livt.Lang.Annotations
// SHA-256 (NIST FIPS 180-4) — single-block, 512-bit input / 256-bit output.
//
// Usage (per message, one 512-bit block at a time):
// 1. Reset() — initialise H0..H7 to FIPS initial values
// 2. ProcessBlock(block) — compress one 64-byte block
// Repeat 2 for each block.
// 3. GetDigest() byte[32] — return current 256-bit digest
//
// Caller is responsible for SHA-256 padding (append 0x80, zeros, 64-bit big-endian
// bit-length) before calling ProcessBlock.
component Sha256
{
public const BLOCK_SIZE: int = 64
public const DIGEST_SIZE: int = 32
h: byte[32] // H0..H7: 8 × 4 bytes big-endian
W: byte[256] // Message schedule: 64 words × 4 bytes big-endian
// SHA-256 round constants K[0..63] split by byte position (big-endian).
// K0[i] = MSByte(K[i]), K1[i] = byte 1, K2[i] = byte 2, K3[i] = LSByte(K[i]).
const K0: byte[64] = [
0x42, 0x71, 0xb5, 0xe9, 0x39, 0x59, 0x92, 0xab,
0xd8, 0x12, 0x24, 0x55, 0x72, 0x80, 0x9b, 0xc1,
0xe4, 0xef, 0x0f, 0x24, 0x2d, 0x4a, 0x5c, 0x76,
0x98, 0xa8, 0xb0, 0xbf, 0xc6, 0xd5, 0x06, 0x14,
0x27, 0x2e, 0x4d, 0x53, 0x65, 0x76, 0x81, 0x92,
0xa2, 0xa8, 0xc2, 0xc7, 0xd1, 0xd6, 0xf4, 0x10,
0x19, 0x1e, 0x27, 0x34, 0x39, 0x4e, 0x5b, 0x68,
0x74, 0x78, 0x84, 0x8c, 0x90, 0xa4, 0xbe, 0xc6]
const K1: byte[64] = [
0x8a, 0x37, 0xc0, 0xb5, 0x56, 0xf1, 0x3f, 0x1c,
0x07, 0x83, 0x31, 0x0c, 0xbe, 0xde, 0xdc, 0x9b,
0x9b, 0xbe, 0xc1, 0x0c, 0xe9, 0x74, 0xb0, 0xf9,
0x3e, 0x31, 0x03, 0x59, 0xe0, 0xa7, 0xca, 0x29,
0xb7, 0x1b, 0x2c, 0x38, 0x0a, 0x6a, 0xc2, 0x72,
0xbf, 0x1a, 0x4b, 0x6c, 0x92, 0x99, 0x0e, 0x6a,
0xa4, 0x37, 0x48, 0xb0, 0x1c, 0xd8, 0x9c, 0x2e,
0x8f, 0xa5, 0xc8, 0xc7, 0xbe, 0x50, 0xf9, 0x71]
const K2: byte[64] = [
0x2f, 0x44, 0xfb, 0xdb, 0xc2, 0x11, 0x82, 0x5e,
0xaa, 0x5b, 0x85, 0x7d, 0x5d, 0xb1, 0x06, 0xf1,
0x69, 0x47, 0x9d, 0xa1, 0x2c, 0x84, 0xa9, 0x88,
0x51, 0xc6, 0x27, 0x7f, 0x0b, 0x91, 0x63, 0x29,
0x0a, 0x21, 0x6d, 0x0d, 0x73, 0x0a, 0xc9, 0x2c,
0xe8, 0x66, 0x8b, 0x51, 0xe8, 0x06, 0x35, 0xa0,
0xc1, 0x6c, 0x77, 0xbc, 0x0c, 0xaa, 0xca, 0x6f,
0x82, 0x63, 0x78, 0x02, 0xff, 0x6c, 0xa3, 0x78]
const K3: byte[64] = [
0x98, 0x91, 0xcf, 0xa5, 0x5b, 0xf1, 0xa4, 0xd5,
0x98, 0x01, 0xbe, 0xc3, 0x74, 0xfe, 0xa7, 0x74,
0xc1, 0x86, 0xc6, 0xcc, 0x6f, 0xaa, 0xdc, 0xda,
0x52, 0x6d, 0xc8, 0xc7, 0xf3, 0x47, 0x51, 0x67,
0x85, 0x38, 0xfc, 0x13, 0x54, 0xbb, 0x2e, 0x85,
0xa1, 0x4b, 0x70, 0xa3, 0x19, 0x24, 0x85, 0x70,
0x16, 0x08, 0x4c, 0xb5, 0xb3, 0x4a, 0x4f, 0xf3,
0xee, 0x6f, 0x14, 0x08, 0xfa, 0xeb, 0xf7, 0xf2]
new()
{
}
// -----------------------------------------------------------------------
// Public API
// -----------------------------------------------------------------------
// Reset initialises H0..H7 to SHA-256 initial hash values (FIPS 180-4 §5.3.3).
public fn Reset()
{
var init: byte[32] = [
0x6a, 0x09, 0xe6, 0x67,
0xbb, 0x67, 0xae, 0x85,
0x3c, 0x6e, 0xf3, 0x72,
0xa5, 0x4f, 0xf5, 0x3a,
0x51, 0x0e, 0x52, 0x7f,
0x9b, 0x05, 0x68, 0x8c,
0x1f, 0x83, 0xd9, 0xab,
0x5b, 0xe0, 0xcd, 0x19]
for (var i = 0; i < 32; i++)
{
this.h[i] = init[i]
}
}
// ProcessBlock compresses one 64-byte (512-bit) message block.
// Call Reset() before the first block. For multi-block messages call
// ProcessBlock once per block; do NOT call Reset() between blocks.
public fn ProcessBlock(msg: byte[64])
{
// Initialise working variables from current hash state.
var ha0: byte = this.h[0]; var ha1: byte = this.h[1]; var ha2: byte = this.h[2]; var ha3: byte = this.h[3]
var hb0: byte = this.h[4]; var hb1: byte = this.h[5]; var hb2: byte = this.h[6]; var hb3: byte = this.h[7]
var hc0: byte = this.h[8]; var hc1: byte = this.h[9]; var hc2: byte = this.h[10]; var hc3: byte = this.h[11]
var hd0: byte = this.h[12]; var hd1: byte = this.h[13]; var hd2: byte = this.h[14]; var hd3: byte = this.h[15]
var he0: byte = this.h[16]; var he1: byte = this.h[17]; var he2: byte = this.h[18]; var he3: byte = this.h[19]
var hf0: byte = this.h[20]; var hf1: byte = this.h[21]; var hf2: byte = this.h[22]; var hf3: byte = this.h[23]
var hg0: byte = this.h[24]; var hg1: byte = this.h[25]; var hg2: byte = this.h[26]; var hg3: byte = this.h[27]
var hh0: byte = this.h[28]; var hh1: byte = this.h[29]; var hh2: byte = this.h[30]; var hh3: byte = this.h[31]
var a0: byte = ha0; var a1: byte = ha1; var a2: byte = ha2; var a3: byte = ha3
var b0: byte = hb0; var b1: byte = hb1; var b2: byte = hb2; var b3: byte = hb3
var c0: byte = hc0; var c1: byte = hc1; var c2: byte = hc2; var c3: byte = hc3
var d0: byte = hd0; var d1: byte = hd1; var d2: byte = hd2; var d3: byte = hd3
var e0: byte = he0; var e1: byte = he1; var e2: byte = he2; var e3: byte = he3
var f0: byte = hf0; var f1: byte = hf1; var f2: byte = hf2; var f3: byte = hf3
var g0: byte = hg0; var g1: byte = hg1; var g2: byte = hg2; var g3: byte = hg3
var wh0: byte = hh0; var wh1: byte = hh1; var wh2: byte = hh2; var wh3: byte = hh3
// Copy first 16 words (64 bytes) from block into this.W[0..63].
this.W[0] = msg[0]; this.W[1] = msg[1]; this.W[2] = msg[2]; this.W[3] = msg[3]
this.W[4] = msg[4]; this.W[5] = msg[5]; this.W[6] = msg[6]; this.W[7] = msg[7]
this.W[8] = msg[8]; this.W[9] = msg[9]; this.W[10] = msg[10]; this.W[11] = msg[11]
this.W[12] = msg[12]; this.W[13] = msg[13]; this.W[14] = msg[14]; this.W[15] = msg[15]
this.W[16] = msg[16]; this.W[17] = msg[17]; this.W[18] = msg[18]; this.W[19] = msg[19]
this.W[20] = msg[20]; this.W[21] = msg[21]; this.W[22] = msg[22]; this.W[23] = msg[23]
this.W[24] = msg[24]; this.W[25] = msg[25]; this.W[26] = msg[26]; this.W[27] = msg[27]
this.W[28] = msg[28]; this.W[29] = msg[29]; this.W[30] = msg[30]; this.W[31] = msg[31]
this.W[32] = msg[32]; this.W[33] = msg[33]; this.W[34] = msg[34]; this.W[35] = msg[35]
this.W[36] = msg[36]; this.W[37] = msg[37]; this.W[38] = msg[38]; this.W[39] = msg[39]
this.W[40] = msg[40]; this.W[41] = msg[41]; this.W[42] = msg[42]; this.W[43] = msg[43]
this.W[44] = msg[44]; this.W[45] = msg[45]; this.W[46] = msg[46]; this.W[47] = msg[47]
this.W[48] = msg[48]; this.W[49] = msg[49]; this.W[50] = msg[50]; this.W[51] = msg[51]
this.W[52] = msg[52]; this.W[53] = msg[53]; this.W[54] = msg[54]; this.W[55] = msg[55]
this.W[56] = msg[56]; this.W[57] = msg[57]; this.W[58] = msg[58]; this.W[59] = msg[59]
this.W[60] = msg[60]; this.W[61] = msg[61]; this.W[62] = msg[62]; this.W[63] = msg[63]
// Extend message schedule W[16..63].
// Reads use indices < j (written by prior iterations or the copy above).
for (var j = 16; j < 64; j++)
{
var jm2: int = (j - 2) * 4
var jm7: int = (j - 7) * 4
var jm15: int = (j - 15) * 4
var jm16: int = (j - 16) * 4
var jm2p1: int = jm2 + 1
var jm2p2: int = jm2 + 2
var jm2p3: int = jm2 + 3
var jm7p1: int = jm7 + 1
var jm7p2: int = jm7 + 2
var jm7p3: int = jm7 + 3
var jm15p1: int = jm15 + 1
var jm15p2: int = jm15 + 2
var jm15p3: int = jm15 + 3
var jm16p1: int = jm16 + 1
var jm16p2: int = jm16 + 2
var jm16p3: int = jm16 + 3
var wm2b0: byte = this.W[jm2]; var wm2b1: byte = this.W[jm2p1]
var wm2b2: byte = this.W[jm2p2]; var wm2b3: byte = this.W[jm2p3]
var wm7b0: byte = this.W[jm7]; var wm7b1: byte = this.W[jm7p1]
var wm7b2: byte = this.W[jm7p2]; var wm7b3: byte = this.W[jm7p3]
var wm15b0: byte = this.W[jm15]; var wm15b1: byte = this.W[jm15p1]
var wm15b2: byte = this.W[jm15p2];var wm15b3: byte = this.W[jm15p3]
var wm16b0: byte = this.W[jm16]; var wm16b1: byte = this.W[jm16p1]
var wm16b2: byte = this.W[jm16p2];var wm16b3: byte = this.W[jm16p3]
var ls1: byte[4] = this.LilSigma1(wm2b0, wm2b1, wm2b2, wm2b3)
var ls1b0: byte = ls1[0]; var ls1b1: byte = ls1[1]; var ls1b2: byte = ls1[2]; var ls1b3: byte = ls1[3]
var ls0: byte[4] = this.LilSigma0(wm15b0, wm15b1, wm15b2, wm15b3)
var ls0b0: byte = ls0[0]; var ls0b1: byte = ls0[1]; var ls0b2: byte = ls0[2]; var ls0b3: byte = ls0[3]
var s1: byte[4] = this.AddWord(ls1b0, ls1b1, ls1b2, ls1b3, wm7b0, wm7b1, wm7b2, wm7b3)
var s1b0: byte = s1[0]; var s1b1: byte = s1[1]; var s1b2: byte = s1[2]; var s1b3: byte = s1[3]
var s2: byte[4] = this.AddWord(s1b0, s1b1, s1b2, s1b3, ls0b0, ls0b1, ls0b2, ls0b3)
var s2b0: byte = s2[0]; var s2b1: byte = s2[1]; var s2b2: byte = s2[2]; var s2b3: byte = s2[3]
var wj: byte[4] = this.AddWord(s2b0, s2b1, s2b2, s2b3, wm16b0, wm16b1, wm16b2, wm16b3)
var wjb0: byte = wj[0]; var wjb1: byte = wj[1]; var wjb2: byte = wj[2]; var wjb3: byte = wj[3]
var jbase: int = j * 4
var jbp1: int = jbase + 1
var jbp2: int = jbase + 2
var jbp3: int = jbase + 3
this.W[jbase] = wjb0
this.W[jbp1] = wjb1
this.W[jbp2] = wjb2
this.W[jbp3] = wjb3
}
// 64-round compression.
for (var i = 0; i < 64; i++)
{
var ki0: byte = this.K0[i]
var ki1: byte = this.K1[i]
var ki2: byte = this.K2[i]
var ki3: byte = this.K3[i]
var ibase: int = i * 4
var ibp1: int = ibase + 1
var ibp2: int = ibase + 2
var ibp3: int = ibase + 3
var w0: byte = this.W[ibase]
var w1: byte = this.W[ibp1]
var w2: byte = this.W[ibp2]
var w3: byte = this.W[ibp3]
var bsig1e: byte[4] = this.BigSigma1(e0, e1, e2, e3)
var bsig1e0: byte = bsig1e[0]; var bsig1e1: byte = bsig1e[1]
var bsig1e2: byte = bsig1e[2]; var bsig1e3: byte = bsig1e[3]
var cval: byte[4] = this.Ch(e0, e1, e2, e3, f0, f1, f2, f3, g0, g1, g2, g3)
var cval0: byte = cval[0]; var cval1: byte = cval[1]
var cval2: byte = cval[2]; var cval3: byte = cval[3]
// T1 = wh + BigSigma1(e) + Ch(e,f,g) + K[i] + W[i]
var t1a: byte[4] = this.AddWord(wh0, wh1, wh2, wh3, bsig1e0, bsig1e1, bsig1e2, bsig1e3)
var t1a0: byte = t1a[0]; var t1a1: byte = t1a[1]; var t1a2: byte = t1a[2]; var t1a3: byte = t1a[3]
var t1b: byte[4] = this.AddWord(t1a0, t1a1, t1a2, t1a3, cval0, cval1, cval2, cval3)
var t1b0: byte = t1b[0]; var t1b1: byte = t1b[1]; var t1b2: byte = t1b[2]; var t1b3: byte = t1b[3]
var t1c: byte[4] = this.AddWord(t1b0, t1b1, t1b2, t1b3, ki0, ki1, ki2, ki3)
var t1c0: byte = t1c[0]; var t1c1: byte = t1c[1]; var t1c2: byte = t1c[2]; var t1c3: byte = t1c[3]
var t1: byte[4] = this.AddWord(t1c0, t1c1, t1c2, t1c3, w0, w1, w2, w3)
var t10: byte = t1[0]; var t11: byte = t1[1]; var t12: byte = t1[2]; var t13: byte = t1[3]
var bsig0a: byte[4] = this.BigSigma0(a0, a1, a2, a3)
var bsig0a0: byte = bsig0a[0]; var bsig0a1: byte = bsig0a[1]
var bsig0a2: byte = bsig0a[2]; var bsig0a3: byte = bsig0a[3]
var mval: byte[4] = this.Maj(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3)
var mval0: byte = mval[0]; var mval1: byte = mval[1]
var mval2: byte = mval[2]; var mval3: byte = mval[3]
// T2 = BigSigma0(a) + Maj(a,b,c)
var t2: byte[4] = this.AddWord(bsig0a0, bsig0a1, bsig0a2, bsig0a3, mval0, mval1, mval2, mval3)
var t20: byte = t2[0]; var t21: byte = t2[1]; var t22: byte = t2[2]; var t23: byte = t2[3]
// Compute new e = d + T1 and new a = T1 + T2 before shifting.
var ne: byte[4] = this.AddWord(d0, d1, d2, d3, t10, t11, t12, t13)
var na: byte[4] = this.AddWord(t10, t11, t12, t13, t20, t21, t22, t23)
// Rotate: h=g, g=f, f=e, e=ne, d=c, c=b, b=a, a=na
wh0 = g0; wh1 = g1; wh2 = g2; wh3 = g3
g0 = f0; g1 = f1; g2 = f2; g3 = f3
f0 = e0; f1 = e1; f2 = e2; f3 = e3
e0 = ne[0]; e1 = ne[1]; e2 = ne[2]; e3 = ne[3]
d0 = c0; d1 = c1; d2 = c2; d3 = c3
c0 = b0; c1 = b1; c2 = b2; c3 = b3
b0 = a0; b1 = a1; b2 = a2; b3 = a3
a0 = na[0]; a1 = na[1]; a2 = na[2]; a3 = na[3]
}
// H_new[k] = H_old[k] + working_var[k]
var nh0: byte[4] = this.AddWord(ha0, ha1, ha2, ha3, a0, a1, a2, a3)
var nh1: byte[4] = this.AddWord(hb0, hb1, hb2, hb3, b0, b1, b2, b3)
var nh2: byte[4] = this.AddWord(hc0, hc1, hc2, hc3, c0, c1, c2, c3)
var nh3: byte[4] = this.AddWord(hd0, hd1, hd2, hd3, d0, d1, d2, d3)
var nh4: byte[4] = this.AddWord(he0, he1, he2, he3, e0, e1, e2, e3)
var nh5: byte[4] = this.AddWord(hf0, hf1, hf2, hf3, f0, f1, f2, f3)
var nh6: byte[4] = this.AddWord(hg0, hg1, hg2, hg3, g0, g1, g2, g3)
var nh7: byte[4] = this.AddWord(hh0, hh1, hh2, hh3, wh0, wh1, wh2, wh3)
// Assemble into a local array then write via for loop (§5).
var newH: byte[32]
newH[0] = nh0[0]; newH[1] = nh0[1]; newH[2] = nh0[2]; newH[3] = nh0[3]
newH[4] = nh1[0]; newH[5] = nh1[1]; newH[6] = nh1[2]; newH[7] = nh1[3]
newH[8] = nh2[0]; newH[9] = nh2[1]; newH[10] = nh2[2]; newH[11] = nh2[3]
newH[12] = nh3[0]; newH[13] = nh3[1]; newH[14] = nh3[2]; newH[15] = nh3[3]
newH[16] = nh4[0]; newH[17] = nh4[1]; newH[18] = nh4[2]; newH[19] = nh4[3]
newH[20] = nh5[0]; newH[21] = nh5[1]; newH[22] = nh5[2]; newH[23] = nh5[3]
newH[24] = nh6[0]; newH[25] = nh6[1]; newH[26] = nh6[2]; newH[27] = nh6[3]
newH[28] = nh7[0]; newH[29] = nh7[1]; newH[30] = nh7[2]; newH[31] = nh7[3]
for (var j = 0; j < 32; j++)
{
this.h[j] = newH[j]
}
}
// GetDigest returns the current 256-bit hash value as 32 bytes (big-endian).
public fn GetDigest() byte[32]
{
return this.h
}
// -----------------------------------------------------------------------
// Private helpers — all pure (no this.* writes except ProcessBlock).
// -----------------------------------------------------------------------
// AddWord: modular 32-bit addition in big-endian byte form.
inline fn AddWord[](a0: byte, a1: byte, a2: byte, a3: byte,
b0: byte, b1: byte, b2: byte, b3: byte) byte[4]
{
var a0i: int = a0 as int; var a1i: int = a1 as int
var a2i: int = a2 as int; var a3i: int = a3 as int
var b0i: int = b0 as int; var b1i: int = b1 as int
var b2i: int = b2 as int; var b3i: int = b3 as int
var sum3: int = a3i + b3i
var d3i: int = sum3 % 256
var c3: int = sum3 / 256
var sum2: int = a2i + b2i + c3
var d2i: int = sum2 % 256
var c2: int = sum2 / 256
var sum1: int = a1i + b1i + c2
var d1i: int = sum1 % 256
var c1: int = sum1 / 256
var sum0: int = a0i + b0i + c1
var d0i: int = sum0 % 256
var result: byte[4]
var rb0: byte = d0i as byte
var rb1: byte = d1i as byte
var rb2: byte = d2i as byte
var rb3: byte = d3i as byte
result[0] = rb0
result[1] = rb1
result[2] = rb2
result[3] = rb3
return result
}
// XorWord: bitwise XOR of two 32-bit words, byte by byte.
inline fn XorWord[](a0: byte, a1: byte, a2: byte, a3: byte,
b0: byte, b1: byte, b2: byte, b3: byte) byte[4]
{
var x0: byte = a0 ^ b0
var x1: byte = a1 ^ b1
var x2: byte = a2 ^ b2
var x3: byte = a3 ^ b3
var result: byte[4]
result[0] = x0; result[1] = x1; result[2] = x2; result[3] = x3
return result
}
// AndWord: bitwise AND of two 32-bit words, byte by byte.
inline fn AndWord[](a0: byte, a1: byte, a2: byte, a3: byte,
b0: byte, b1: byte, b2: byte, b3: byte) byte[4]
{
var x0: byte = a0 & b0
var x1: byte = a1 & b1
var x2: byte = a2 & b2
var x3: byte = a3 & b3
var result: byte[4]
result[0] = x0; result[1] = x1; result[2] = x2; result[3] = x3
return result
}
// Rotr: rotate right a 32-bit big-endian word by n bits (0 <= n <= 31).
@SuppressWarning("variable-divisor")
inline fn Rotr[](b0: byte, b1: byte, b2: byte, b3: byte, n: int) byte[4]
{
var q: int = n / 8
var r: int = n % 8
// Byte-level rotation: shift bytes right by q positions (circular).
var c0: byte = b0; var c1: byte = b1; var c2: byte = b2; var c3: byte = b3
if (q == 1)
{
c0 = b3; c1 = b0; c2 = b1; c3 = b2
}
if (q == 2)
{
c0 = b2; c1 = b3; c2 = b0; c3 = b1
}
if (q == 3)
{
c0 = b1; c1 = b2; c2 = b3; c3 = b0
}
// Bit-level rotation right by r bits within the 4 bytes.
var pow_r: int = 1
if (r >= 1) { pow_r = 2 }
if (r >= 2) { pow_r = 4 }
if (r >= 3) { pow_r = 8 }
if (r >= 4) { pow_r = 16 }
if (r >= 5) { pow_r = 32 }
if (r >= 6) { pow_r = 64 }
if (r >= 7) { pow_r = 128 }
var pow_8mr: int = 256 / pow_r
var c0i: int = c0 as int; var c1i: int = c1 as int
var c2i: int = c2 as int; var c3i: int = c3 as int
// Each byte shifts right r bits; the r low bits wrap from the PREVIOUS byte.
var d0i: int = c0i / pow_r + (c3i % pow_r) * pow_8mr
var d1i: int = c1i / pow_r + (c0i % pow_r) * pow_8mr
var d2i: int = c2i / pow_r + (c1i % pow_r) * pow_8mr
var d3i: int = c3i / pow_r + (c2i % pow_r) * pow_8mr
var result: byte[4]
var rr0: byte = d0i as byte
var rr1: byte = d1i as byte
var rr2: byte = d2i as byte
var rr3: byte = d3i as byte
result[0] = rr0
result[1] = rr1
result[2] = rr2
result[3] = rr3
return result
}
// Shr: logical right shift of a 32-bit big-endian word by n bits (0 <= n <= 31).
@SuppressWarning("variable-divisor")
inline fn Shr[](b0: byte, b1: byte, b2: byte, b3: byte, n: int) byte[4]
{
var q: int = n / 8
var r: int = n % 8
// Byte-level shift: shift bytes right by q positions, fill MSBytes with 0.
var c0: byte = b0; var c1: byte = b1; var c2: byte = b2; var c3: byte = b3
if (q == 1)
{
c0 = 0x00; c1 = b0; c2 = b1; c3 = b2
}
if (q == 2)
{
c0 = 0x00; c1 = 0x00; c2 = b0; c3 = b1
}
if (q == 3)
{
c0 = 0x00; c1 = 0x00; c2 = 0x00; c3 = b0
}
// Bit-level shift right by r bits; MSBits of d0 are 0 (no wrap from c3).
var pow_r: int = 1
if (r >= 1) { pow_r = 2 }
if (r >= 2) { pow_r = 4 }
if (r >= 3) { pow_r = 8 }
if (r >= 4) { pow_r = 16 }
if (r >= 5) { pow_r = 32 }
if (r >= 6) { pow_r = 64 }
if (r >= 7) { pow_r = 128 }
var pow_8mr: int = 256 / pow_r
var c0i: int = c0 as int; var c1i: int = c1 as int
var c2i: int = c2 as int; var c3i: int = c3 as int
var d0i: int = c0i / pow_r
var d1i: int = c1i / pow_r + (c0i % pow_r) * pow_8mr
var d2i: int = c2i / pow_r + (c1i % pow_r) * pow_8mr
var d3i: int = c3i / pow_r + (c2i % pow_r) * pow_8mr
var result: byte[4]
var rs0: byte = d0i as byte
var rs1: byte = d1i as byte
var rs2: byte = d2i as byte
var rs3: byte = d3i as byte
result[0] = rs0
result[1] = rs1
result[2] = rs2
result[3] = rs3
return result
}
// BigSigma0: ROTR_2 XOR ROTR_13 XOR ROTR_22 (used for working variable a).
fn BigSigma0[](b0: byte, b1: byte, b2: byte, b3: byte) byte[4]
{
var r2: byte[4] = this.Rotr(b0, b1, b2, b3, 2)
var r2b0: byte = r2[0]; var r2b1: byte = r2[1]; var r2b2: byte = r2[2]; var r2b3: byte = r2[3]
var r13: byte[4] = this.Rotr(b0, b1, b2, b3, 13)
var r13b0: byte = r13[0]; var r13b1: byte = r13[1]; var r13b2: byte = r13[2]; var r13b3: byte = r13[3]
var r22: byte[4] = this.Rotr(b0, b1, b2, b3, 22)
var r22b0: byte = r22[0]; var r22b1: byte = r22[1]; var r22b2: byte = r22[2]; var r22b3: byte = r22[3]
var x1: byte[4] = this.XorWord(r2b0, r2b1, r2b2, r2b3, r13b0, r13b1, r13b2, r13b3)
var x1b0: byte = x1[0]; var x1b1: byte = x1[1]; var x1b2: byte = x1[2]; var x1b3: byte = x1[3]
var result: byte[4] = this.XorWord(x1b0, x1b1, x1b2, x1b3, r22b0, r22b1, r22b2, r22b3)
return result
}
// BigSigma1: ROTR_6 XOR ROTR_11 XOR ROTR_25 (used for working variable e).
fn BigSigma1[](b0: byte, b1: byte, b2: byte, b3: byte) byte[4]
{
var r6: byte[4] = this.Rotr(b0, b1, b2, b3, 6)
var r6b0: byte = r6[0]; var r6b1: byte = r6[1]; var r6b2: byte = r6[2]; var r6b3: byte = r6[3]
var r11: byte[4] = this.Rotr(b0, b1, b2, b3, 11)
var r11b0: byte = r11[0]; var r11b1: byte = r11[1]; var r11b2: byte = r11[2]; var r11b3: byte = r11[3]
var r25: byte[4] = this.Rotr(b0, b1, b2, b3, 25)
var r25b0: byte = r25[0]; var r25b1: byte = r25[1]; var r25b2: byte = r25[2]; var r25b3: byte = r25[3]
var x1: byte[4] = this.XorWord(r6b0, r6b1, r6b2, r6b3, r11b0, r11b1, r11b2, r11b3)
var x1b0: byte = x1[0]; var x1b1: byte = x1[1]; var x1b2: byte = x1[2]; var x1b3: byte = x1[3]
var result: byte[4] = this.XorWord(x1b0, x1b1, x1b2, x1b3, r25b0, r25b1, r25b2, r25b3)
return result
}
// LilSigma0: ROTR_7 XOR ROTR_18 XOR SHR_3 (message schedule σ0).
fn LilSigma0[](b0: byte, b1: byte, b2: byte, b3: byte) byte[4]
{
var r7: byte[4] = this.Rotr(b0, b1, b2, b3, 7)
var r7b0: byte = r7[0]; var r7b1: byte = r7[1]; var r7b2: byte = r7[2]; var r7b3: byte = r7[3]
var r18: byte[4] = this.Rotr(b0, b1, b2, b3, 18)
var r18b0: byte = r18[0]; var r18b1: byte = r18[1]; var r18b2: byte = r18[2]; var r18b3: byte = r18[3]
var s3: byte[4] = this.Shr(b0, b1, b2, b3, 3)
var s3b0: byte = s3[0]; var s3b1: byte = s3[1]; var s3b2: byte = s3[2]; var s3b3: byte = s3[3]
var x1: byte[4] = this.XorWord(r7b0, r7b1, r7b2, r7b3, r18b0, r18b1, r18b2, r18b3)
var x1b0: byte = x1[0]; var x1b1: byte = x1[1]; var x1b2: byte = x1[2]; var x1b3: byte = x1[3]
var result: byte[4] = this.XorWord(x1b0, x1b1, x1b2, x1b3, s3b0, s3b1, s3b2, s3b3)
return result
}
// LilSigma1: ROTR_17 XOR ROTR_19 XOR SHR_10 (message schedule σ1).
fn LilSigma1[](b0: byte, b1: byte, b2: byte, b3: byte) byte[4]
{
var r17: byte[4] = this.Rotr(b0, b1, b2, b3, 17)
var r17b0: byte = r17[0]; var r17b1: byte = r17[1]; var r17b2: byte = r17[2]; var r17b3: byte = r17[3]
var r19: byte[4] = this.Rotr(b0, b1, b2, b3, 19)
var r19b0: byte = r19[0]; var r19b1: byte = r19[1]; var r19b2: byte = r19[2]; var r19b3: byte = r19[3]
var s10: byte[4] = this.Shr(b0, b1, b2, b3, 10)
var s10b0: byte = s10[0]; var s10b1: byte = s10[1]; var s10b2: byte = s10[2]; var s10b3: byte = s10[3]
var x1: byte[4] = this.XorWord(r17b0, r17b1, r17b2, r17b3, r19b0, r19b1, r19b2, r19b3)
var x1b0: byte = x1[0]; var x1b1: byte = x1[1]; var x1b2: byte = x1[2]; var x1b3: byte = x1[3]
var result: byte[4] = this.XorWord(x1b0, x1b1, x1b2, x1b3, s10b0, s10b1, s10b2, s10b3)
return result
}
// Ch: (e AND f) XOR ((NOT e) AND g)
fn Ch[](e0: byte, e1: byte, e2: byte, e3: byte,
f0: byte, f1: byte, f2: byte, f3: byte,
g0: byte, g1: byte, g2: byte, g3: byte) byte[4]
{
var ef: byte[4] = this.AndWord(e0, e1, e2, e3, f0, f1, f2, f3)
var ef0: byte = ef[0]; var ef1: byte = ef[1]; var ef2: byte = ef[2]; var ef3: byte = ef[3]
// NOT(e) byte-by-byte: 255 - e
var e0i: int = e0 as int
var ne0i: int = 255 - e0i
var ne0: byte = ne0i as byte
var e1i: int = e1 as int
var ne1i: int = 255 - e1i
var ne1: byte = ne1i as byte
var e2i: int = e2 as int
var ne2i: int = 255 - e2i
var ne2: byte = ne2i as byte
var e3i: int = e3 as int
var ne3i: int = 255 - e3i
var ne3: byte = ne3i as byte
var neg: byte[4] = this.AndWord(ne0, ne1, ne2, ne3, g0, g1, g2, g3)
var neg0: byte = neg[0]; var neg1: byte = neg[1]; var neg2: byte = neg[2]; var neg3: byte = neg[3]
var result: byte[4] = this.XorWord(ef0, ef1, ef2, ef3, neg0, neg1, neg2, neg3)
return result
}
// Maj: (a AND b) XOR (a AND c) XOR (b AND c)
fn Maj[](a0: byte, a1: byte, a2: byte, a3: byte,
b0: byte, b1: byte, b2: byte, b3: byte,
c0: byte, c1: byte, c2: byte, c3: byte) byte[4]
{
var ab: byte[4] = this.AndWord(a0, a1, a2, a3, b0, b1, b2, b3)
var ab0: byte = ab[0]; var ab1: byte = ab[1]; var ab2: byte = ab[2]; var ab3: byte = ab[3]
var ac: byte[4] = this.AndWord(a0, a1, a2, a3, c0, c1, c2, c3)
var ac0: byte = ac[0]; var ac1: byte = ac[1]; var ac2: byte = ac[2]; var ac3: byte = ac[3]
var bc: byte[4] = this.AndWord(b0, b1, b2, b3, c0, c1, c2, c3)
var bc0: byte = bc[0]; var bc1: byte = bc[1]; var bc2: byte = bc[2]; var bc3: byte = bc[3]
var x1: byte[4] = this.XorWord(ab0, ab1, ab2, ab3, ac0, ac1, ac2, ac3)
var x1b0: byte = x1[0]; var x1b1: byte = x1[1]; var x1b2: byte = x1[2]; var x1b3: byte = x1[3]
var result: byte[4] = this.XorWord(x1b0, x1b1, x1b2, x1b3, bc0, bc1, bc2, bc3)
return result
}
}