From 55b8a9acb95bcde23bf53e0551698680877cce3a Mon Sep 17 00:00:00 2001
From: joe-conigliaro <joe-conigliaro@users.noreply.github.com>
Date: Wed, 17 Jul 2019 19:00:15 +1000
Subject: [PATCH] crypto.sha512

---
 vlib/crypto/crypto.v                     |  23 ++
 vlib/crypto/md5/md5.v                    |  15 +-
 vlib/crypto/md5/md5block_generic.v       |   6 +-
 vlib/crypto/sha1/sha1.v                  |  12 +-
 vlib/crypto/sha1/sha1block_generic.v     |   4 +-
 vlib/crypto/sha512/sha512.v              | 350 +++++++++++++++++++++++
 vlib/crypto/sha512/sha512_test.v         |   9 +
 vlib/crypto/sha512/sha512block_generic.v | 254 ++++++++++++++++
 8 files changed, 662 insertions(+), 11 deletions(-)
 create mode 100644 vlib/crypto/crypto.v
 create mode 100644 vlib/crypto/sha512/sha512.v
 create mode 100644 vlib/crypto/sha512/sha512_test.v
 create mode 100644 vlib/crypto/sha512/sha512block_generic.v

diff --git a/vlib/crypto/crypto.v b/vlib/crypto/crypto.v
new file mode 100644
index 0000000000..a86f86b3d9
--- /dev/null
+++ b/vlib/crypto/crypto.v
@@ -0,0 +1,23 @@
+module crypto
+
+enum Hash {
+	MD4
+	MD5
+	SHA1
+	SHA224
+	SHA256
+	SHA384
+	SHA512
+	MD5SHA1
+	RIPEMD160
+	SHA3_224
+	SHA3_256
+	SHA3_384
+	SHA3_512
+	SHA512_224
+	SHA512_256
+	BLAKE2s_256
+	BLAKE2b_256
+	BLAKE2b_384
+	BLAKE2b_512
+}
diff --git a/vlib/crypto/md5/md5.v b/vlib/crypto/md5/md5.v
index 0d170253d6..b17a8f5e12 100644
--- a/vlib/crypto/md5/md5.v
+++ b/vlib/crypto/md5/md5.v
@@ -48,7 +48,7 @@ fn (d mut Digest) reset() {
 	d.len = u64(0)
 }
 
-// New returns a new hash.Hash computing the MD5 checksum.
+// new returns a new hash.Hash computing the MD5 checksum.
 pub fn new() *Digest {
 	mut d := &Digest{}
 	d.reset()
@@ -65,7 +65,7 @@ pub fn (d mut Digest) write(p []byte) ?int {
 		}
 		d.nx += n
 		if d.nx == BlockSize {
-            block_generic(d, d.x)
+            block(d, d.x)
 			d.nx = 0
 		}
 		if n >= p.len {
@@ -76,7 +76,7 @@ pub fn (d mut Digest) write(p []byte) ?int {
 	}
 	if p.len >= BlockSize {
 		n := p.len &~ (BlockSize - 1)
-		block_generic(d, p.left(n))
+		block(d, p.left(n))
 		if n >= p.len {
 			p = []byte
 		} else {
@@ -130,14 +130,19 @@ pub fn (d mut Digest) checksum() []byte {
 	return digest
 }
 
-// Sum returns the MD5 checksum of the data.
-// pub fn Sum(data []byte) [Size]byte {
+// sum returns the MD5 checksum of the data.
 pub fn sum(data []byte) []byte {
 	mut d := new()
 	d.write(data)
 	return d.checksum()
 }
 
+fn block(dig &Digest, p []byte) {
+    // For now just use block_generic until we have specific
+	// architecture optimized versions
+    block_generic(dig, p)
+}
+
 pub fn (d &Digest) size() int { return Size }
 
 pub fn (d &Digest) block_size() int { return BlockSize }
\ No newline at end of file
diff --git a/vlib/crypto/md5/md5block_generic.v b/vlib/crypto/md5/md5block_generic.v
index 86611faa03..c22e431429 100644
--- a/vlib/crypto/md5/md5block_generic.v
+++ b/vlib/crypto/md5/md5block_generic.v
@@ -2,7 +2,9 @@
 // Use of this source code is governed by an MIT license
 // that can be found in the LICENSE file.
 
-// This is a generic implementation with no arch optimizations
+// This is the generic version with no architecture optimizations.
+// In its own file so that an architecture
+// optimized verision can be substituted
 
 module md5
 
@@ -126,4 +128,4 @@ fn block_generic(dig &Digest, p []byte) {
 	dig.s[1] = b
 	dig.s[2] = c
 	dig.s[3] = d
-}
\ No newline at end of file
+}
diff --git a/vlib/crypto/sha1/sha1.v b/vlib/crypto/sha1/sha1.v
index cd8aab0227..61f5f6bcd9 100644
--- a/vlib/crypto/sha1/sha1.v
+++ b/vlib/crypto/sha1/sha1.v
@@ -51,7 +51,7 @@ fn (d mut Digest) reset() {
 	d.len = u64(0)
 }
 
-// New returns a new Digest (implementing hash.Hash) computing the SHA1 checksum.
+// new returns a new Digest (implementing hash.Hash) computing the SHA1 checksum.
 pub fn new() &Digest {
 	mut d := &Digest{}
 	d.reset()
@@ -69,7 +69,7 @@ pub fn (d mut Digest) write(p []byte) ?int {
 		}
 		d.nx += n
 		if d.nx == Chunk {
-			block_generic(d, d.x)
+			block(d, d.x)
 			d.nx = 0
 		}
 		if n >= p.len {
@@ -80,7 +80,7 @@ pub fn (d mut Digest) write(p []byte) ?int {
 	}
 	if p.len >= Chunk {
 		n := p.len &~ (Chunk - 1)
-		block_generic(d, p.left(n))
+		block(d, p.left(n))
 		if n >= p.len {
 			p = []byte
 		} else {
@@ -142,6 +142,12 @@ pub fn sum(data []byte) []byte {
 	return d.checksum()
 }
 
+fn block(dig &Digest, p []byte) {
+    // For now just use block_generic until we have specific
+	// architecture optimized versions
+    block_generic(dig, p)
+}
+
 pub fn (d &Digest) size() int { return Size }
 
 pub fn (d &Digest) block_size() int { return BlockSize }
\ No newline at end of file
diff --git a/vlib/crypto/sha1/sha1block_generic.v b/vlib/crypto/sha1/sha1block_generic.v
index c96b8fb6e3..48cee2cd77 100644
--- a/vlib/crypto/sha1/sha1block_generic.v
+++ b/vlib/crypto/sha1/sha1block_generic.v
@@ -2,7 +2,9 @@
 // Use of this source code is governed by an MIT license
 // that can be found in the LICENSE file.
 
-// This is a generic implementation with no arch optimizations
+// This is the generic version with no architecture optimizations.
+// In its own file so that an architecture
+// optimized verision can be substituted
 
 module sha1
 
diff --git a/vlib/crypto/sha512/sha512.v b/vlib/crypto/sha512/sha512.v
new file mode 100644
index 0000000000..d28a57a458
--- /dev/null
+++ b/vlib/crypto/sha512/sha512.v
@@ -0,0 +1,350 @@
+// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
+// Use of this source code is governed by an MIT license
+// that can be found in the LICENSE file.
+
+// Package sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256
+// hash algorithms as defined in FIPS 180-4.
+
+// Adaped from https://github.com/golang/go/tree/master/src/crypto/sha256
+
+module sha512
+
+import math
+import crypto
+import encoding.binary
+
+const (
+	// Size is the size, in bytes, of a SHA-512 checksum.
+	Size = 64
+	// Size224 is the size, in bytes, of a SHA-512/224 checksum.
+	Size224 = 28
+	// Size256 is the size, in bytes, of a SHA-512/256 checksum.
+	Size256 = 32
+	// Size384 is the size, in bytes, of a SHA-384 checksum.
+	Size384 = 48
+	// BlockSize is the block size, in bytes, of the SHA-512/224,
+	// SHA-512/256, SHA-384 and SHA-512 hash functions.
+	BlockSize = 128
+)
+
+const (
+	Chunk     = 128
+	Init0     = 0x6a09e667f3bcc908
+	Init1     = 0xbb67ae8584caa73b
+	Init2     = 0x3c6ef372fe94f82b
+	Init3     = 0xa54ff53a5f1d36f1
+	Init4     = 0x510e527fade682d1
+	Init5     = 0x9b05688c2b3e6c1f
+	Init6     = 0x1f83d9abfb41bd6b
+	Init7     = 0x5be0cd19137e2179
+	Init0_224 = 0x8c3d37c819544da2
+	Init1_224 = 0x73e1996689dcd4d6
+	Init2_224 = 0x1dfab7ae32ff9c82
+	Init3_224 = 0x679dd514582f9fcf
+	Init4_224 = 0x0f6d2b697bd44da8
+	Init5_224 = 0x77e36f7304c48942
+	Init6_224 = 0x3f9d85a86a1d36c8
+	Init7_224 = 0x1112e6ad91d692a1
+	Init0_256 = 0x22312194fc2bf72c
+	Init1_256 = 0x9f555fa3c84c64c2
+	Init2_256 = 0x2393b86b6f53b151
+	Init3_256 = 0x963877195940eabd
+	Init4_256 = 0x96283ee2a88effe3
+	Init5_256 = 0xbe5e1e2553863992
+	Init6_256 = 0x2b0199fc2c85b8aa
+	Init7_256 = 0x0eb72ddc81c52ca2
+	Init0_384 = 0xcbbb9d5dc1059ed8
+	Init1_384 = 0x629a292a367cd507
+	Init2_384 = 0x9159015a3070dd17
+	Init3_384 = 0x152fecd8f70e5939
+	Init4_384 = 0x67332667ffc00b31
+	Init5_384 = 0x8eb44a8768581511
+	Init6_384 = 0xdb0c2e0d64f98fa7
+	Init7_384 = 0x47b5481dbefa4fa4
+)
+
+// digest represents the partial evaluation of a checksum.
+struct Digest {
+	// h        [8]uint64
+	// x        [chunk]byte
+mut:
+	h        []u64
+	x        []byte
+	nx       int
+	len      u64
+	function crypto.Hash
+}
+
+// Note: when u64 const is working uncomment this and remove reset() below
+// fn (d mut Digest) reset() {
+//     d.h = [u64(0); 8]
+//     d.x = [byte(0); Chunk]
+// 	switch d.function {
+// 	case crypto.Hash.SHA384:
+// 		d.h[0] = u64(Init0_384)
+// 		d.h[1] = u64(Init1_384)
+// 		d.h[2] = u64(Init2_384)
+// 		d.h[3] = u64(Init3_384)
+// 		d.h[4] = u64(Init4_384)
+// 		d.h[5] = u64(Init5_384)
+// 		d.h[6] = u64(Init6_384)
+// 		d.h[7] = u64(Init7_384)
+// 	case crypto.Hash.SHA512_224:
+// 		d.h[0] = u64(Init0_224)
+// 		d.h[1] = u64(Init1_224)
+// 		d.h[2] = u64(Init2_224)
+// 		d.h[3] = u64(Init3_224)
+// 		d.h[4] = u64(Init4_224)
+// 		d.h[5] = u64(Init5_224)
+// 		d.h[6] = u64(Init6_224)
+// 		d.h[7] = u64(Init7_224)
+// 	case crypto.Hash.SHA512_256:
+// 		d.h[0] = u64(Init0_256)
+// 		d.h[1] = u64(Init1_256)
+// 		d.h[2] = u64(Init2_256)
+// 		d.h[3] = u64(Init3_256)
+// 		d.h[4] = u64(Init4_256)
+// 		d.h[5] = u64(Init5_256)
+// 		d.h[6] = u64(Init6_256)
+// 		d.h[7] = u64(Init7_256)
+// 	default:
+// 		d.h[0] = u64(Init0)
+// 		d.h[1] = u64(Init1)
+// 		d.h[2] = u64(Init2)
+// 		d.h[3] = u64(Init3)
+// 		d.h[4] = u64(Init4)
+// 		d.h[5] = u64(Init5)
+// 		d.h[6] = u64(Init6)
+// 		d.h[7] = u64(Init7)
+// 	}
+// 	d.nx = 0
+// 	d.len = u64(0)
+// }
+
+// Note: when u64 const is working remove this and uncomment above
+fn (d mut Digest) reset() {
+    d.h = [u64(0); 8]
+    d.x = [byte(0); Chunk]
+	switch d.function {
+	case crypto.Hash.SHA384:
+		d.h[0] = u64(0xcbbb9d5dc1059ed8)
+		d.h[1] = u64(0x629a292a367cd507)
+		d.h[2] = u64(0x9159015a3070dd17)
+		d.h[3] = u64(0x152fecd8f70e5939)
+		d.h[4] = u64(0x67332667ffc00b31)
+		d.h[5] = u64(0x8eb44a8768581511)
+		d.h[6] = u64(0xdb0c2e0d64f98fa7)
+		d.h[7] = u64(0x47b5481dbefa4fa4)
+	case crypto.Hash.SHA512_224:
+		d.h[0] = u64(0x8c3d37c819544da2)
+		d.h[1] = u64(0x73e1996689dcd4d6)
+		d.h[2] = u64(0x1dfab7ae32ff9c82)
+		d.h[3] = u64(0x679dd514582f9fcf)
+		d.h[4] = u64(0x0f6d2b697bd44da8)
+		d.h[5] = u64(0x77e36f7304c48942)
+		d.h[6] = u64(0x3f9d85a86a1d36c8)
+		d.h[7] = u64(0x1112e6ad91d692a1)
+	case crypto.Hash.SHA512_256:
+		d.h[0] = u64(0x22312194fc2bf72c)
+		d.h[1] = u64(0x9f555fa3c84c64c2)
+		d.h[2] = u64(0x2393b86b6f53b151)
+		d.h[3] = u64(0x963877195940eabd)
+		d.h[4] = u64(0x96283ee2a88effe3)
+		d.h[5] = u64(0xbe5e1e2553863992)
+		d.h[6] = u64(0x2b0199fc2c85b8aa)
+		d.h[7] = u64(0x0eb72ddc81c52ca2)
+	default:
+        d.h[0] = u64(0x6a09e667f3bcc908)
+        d.h[1] = u64(0xbb67ae8584caa73b)
+        d.h[2] = u64(0x3c6ef372fe94f82b)
+        d.h[3] = u64(0xa54ff53a5f1d36f1)
+        d.h[4] = u64(0x510e527fade682d1)
+        d.h[5] = u64(0x9b05688c2b3e6c1f)
+        d.h[6] = u64(0x1f83d9abfb41bd6b)
+        d.h[7] = u64(0x5be0cd19137e2179)
+	}
+	d.nx = 0
+	d.len = u64(0)
+}
+
+fn _new(hash crypto.Hash) *Digest {
+	mut d := &Digest{function: hash}
+	d.reset()
+	return d
+}
+
+// new returns a new hash.Hash computing the SHA-512 checksum.
+pub fn new() *Digest {
+	return _new(crypto.Hash.SHA512)
+}
+
+// new512_224 returns a new hash.Hash computing the SHA-512/224 checksum.
+fn new512_224() *Digest {
+	return _new(crypto.Hash.SHA512_224)
+}
+
+// new512_256 returns a new hash.Hash computing the SHA-512/256 checksum.
+fn new512_256() *Digest {
+	return _new(crypto.Hash.SHA512_256)
+}
+
+// new384 returns a new hash.Hash computing the SHA-384 checksum.
+fn new384() *Digest {
+	return _new(crypto.Hash.SHA384)
+}
+
+fn (d mut Digest) write(p []byte) ?int {
+	nn := p.len
+	d.len += u64(nn)
+	if d.nx > 0 {
+		n := int(math.min(f64(d.x.len), f64(p.len)))
+		for i:=0; i<n; i++ {
+			d.x.set(i+d.nx, p[i])
+		}
+		d.nx += n
+		if d.nx == Chunk {
+			block(d, d.x)
+			d.nx = 0
+		}
+		if n >= p.len {
+			p = []byte
+		} else {
+			p = p.right(n)
+		}
+	}
+	if p.len >= Chunk {
+		n := p.len &~ (Chunk - 1)
+		block(d, p.left(n))
+		if n >= p.len {
+			p = []byte
+		} else {
+			p = p.right(n)
+		}
+	}
+	if p.len > 0 {
+		d.nx = int(math.min(f64(d.x.len), f64(p.len)))
+		for i:=0; i<d.nx; i++ {
+			d.x.set(i, p[i])
+		}
+	}
+	return nn
+}
+
+fn (d mut Digest) sum(b_in mut []byte) []byte {
+	// Make a copy of d so that caller can keep writing and summing.
+	mut d0 := *d
+	hash := d0.checksum()
+	switch d0.function {
+	case crypto.Hash.SHA384:
+		for b in hash.left(Size384) {
+            b_in << b
+        }
+	case crypto.Hash.SHA512_224:
+		for b in hash.left(Size224) {
+            b_in << b
+        }
+	case crypto.Hash.SHA512_256:
+		for b in hash.left(Size256) {
+            b_in << b
+        }
+	default:
+		for b in hash {
+            b_in << b
+        }
+	}
+    return *b_in
+}
+
+fn (d mut Digest) checksum() []byte {
+	// Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
+	mut len := d.len
+	mut tmp := [byte(0); 128]
+	tmp[0] = 0x80
+
+    if int(len)%128 < 112 {
+        d.write(tmp.left(112-int(len)%128))
+	} else {
+		d.write(tmp.left(128+112-int(len)%128))
+	}
+
+	// Length in bits.
+	len <<= u64(3)
+
+	binary.big_endian_put_u64(tmp, u64(0)) // upper 64 bits are always zero, because len variable has type u64
+    binary.big_endian_put_u64(tmp.right(8), len)
+	d.write(tmp.left(16))
+
+	if d.nx != 0 {
+		panic('d.nx != 0')
+	}
+
+	mut digest := [byte(0); Size]
+	
+    binary.big_endian_put_u64(digest, d.h[0])
+	binary.big_endian_put_u64(digest.right(8), d.h[1])
+	binary.big_endian_put_u64(digest.right(16), d.h[2])
+	binary.big_endian_put_u64(digest.right(24), d.h[3])
+	binary.big_endian_put_u64(digest.right(32), d.h[4])
+	binary.big_endian_put_u64(digest.right(40), d.h[5])
+	if d.function != crypto.Hash.SHA384 {
+		binary.big_endian_put_u64(digest.right(48), d.h[6])
+		binary.big_endian_put_u64(digest.right(56), d.h[7])
+	}
+
+	return digest
+}
+
+// sum512 returns the SHA512 checksum of the data.
+pub fn sum512(data []byte) []byte {
+	mut d := _new(crypto.Hash.SHA512)
+	d.write(data)
+	return d.checksum()
+}
+
+// sum384 returns the SHA384 checksum of the data.
+pub fn sum384(data []byte) []byte {
+	mut d := _new(crypto.Hash.SHA384)
+	d.write(data)
+	sum := d.checksum()
+    sum384 := sum.left(Size384)
+	return sum384
+}
+
+// sum512_224 returns the Sum512/224 checksum of the data.
+pub fn sum512_224(data []byte) []byte {
+	mut d := _new(crypto.Hash.SHA512_224)
+	d.write(data)
+	sum := d.checksum()
+    sum224 := sum.left(Size224)
+	return sum224
+}
+
+// Sum512_256 returns the Sum512/256 checksum of the data.
+pub fn sum512_256(data []byte) []byte {
+	mut d := _new(crypto.Hash.SHA512_256)
+	d.write(data)
+	sum := d.checksum()
+    sum256 := sum.left(Size256)
+	return sum256
+}
+
+fn block(dig &Digest, p []byte) {
+    // For now just use block_generic until we have specific
+	// architecture optimized versions
+    block_generic(dig, p)
+}
+
+pub fn (d &Digest) size() int {
+	switch d.function {
+	case crypto.Hash.SHA512_224:
+		return Size224
+	case crypto.Hash.SHA512_256:
+		return Size256
+	case crypto.Hash.SHA384:
+		return Size384
+	default:
+		return Size
+	}
+}
+
+pub fn (d &Digest) block_size() int { return BlockSize }
\ No newline at end of file
diff --git a/vlib/crypto/sha512/sha512_test.v b/vlib/crypto/sha512/sha512_test.v
new file mode 100644
index 0000000000..1e9354379a
--- /dev/null
+++ b/vlib/crypto/sha512/sha512_test.v
@@ -0,0 +1,9 @@
+// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
+// Use of this source code is governed by an MIT license
+// that can be found in the LICENSE file.
+
+import crypto.sha512
+
+fn test_crypto_sha512() {	 
+	assert sha512.sum512('This is a sha512 checksum.'.bytes()).hex() == '4143E55FCBA7E39B20F62A1368E5EB28F64A8859458886117AC66027832E0F9F5263DAEC688C439D2D0FA07059334668D39E59543039703DBB7E03EC9DA7F8D7'
+}
diff --git a/vlib/crypto/sha512/sha512block_generic.v b/vlib/crypto/sha512/sha512block_generic.v
new file mode 100644
index 0000000000..3171649680
--- /dev/null
+++ b/vlib/crypto/sha512/sha512block_generic.v
@@ -0,0 +1,254 @@
+// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
+// Use of this source code is governed by an MIT license
+// that can be found in the LICENSE file.
+
+// SHA512 block step.
+// This is the generic version with no architecture optimizations.
+// In its own file so that an architecture
+// optimized verision can be substituted
+
+module sha512
+
+const(
+	_K = [
+		0x428a2f98d728ae22,
+		0x7137449123ef65cd,
+		0xb5c0fbcfec4d3b2f,
+		0xe9b5dba58189dbbc,
+		0x3956c25bf348b538,
+		0x59f111f1b605d019,
+		0x923f82a4af194f9b,
+		0xab1c5ed5da6d8118,
+		0xd807aa98a3030242,
+		0x12835b0145706fbe,
+		0x243185be4ee4b28c,
+		0x550c7dc3d5ffb4e2,
+		0x72be5d74f27b896f,
+		0x80deb1fe3b1696b1,
+		0x9bdc06a725c71235,
+		0xc19bf174cf692694,
+		0xe49b69c19ef14ad2,
+		0xefbe4786384f25e3,
+		0x0fc19dc68b8cd5b5,
+		0x240ca1cc77ac9c65,
+		0x2de92c6f592b0275,
+		0x4a7484aa6ea6e483,
+		0x5cb0a9dcbd41fbd4,
+		0x76f988da831153b5,
+		0x983e5152ee66dfab,
+		0xa831c66d2db43210,
+		0xb00327c898fb213f,
+		0xbf597fc7beef0ee4,
+		0xc6e00bf33da88fc2,
+		0xd5a79147930aa725,
+		0x06ca6351e003826f,
+		0x142929670a0e6e70,
+		0x27b70a8546d22ffc,
+		0x2e1b21385c26c926,
+		0x4d2c6dfc5ac42aed,
+		0x53380d139d95b3df,
+		0x650a73548baf63de,
+		0x766a0abb3c77b2a8,
+		0x81c2c92e47edaee6,
+		0x92722c851482353b,
+		0xa2bfe8a14cf10364,
+		0xa81a664bbc423001,
+		0xc24b8b70d0f89791,
+		0xc76c51a30654be30,
+		0xd192e819d6ef5218,
+		0xd69906245565a910,
+		0xf40e35855771202a,
+		0x106aa07032bbd1b8,
+		0x19a4c116b8d2d0c8,
+		0x1e376c085141ab53,
+		0x2748774cdf8eeb99,
+		0x34b0bcb5e19b48a8,
+		0x391c0cb3c5c95a63,
+		0x4ed8aa4ae3418acb,
+		0x5b9cca4f7763e373,
+		0x682e6ff3d6b2b8a3,
+		0x748f82ee5defb2fc,
+		0x78a5636f43172f60,
+		0x84c87814a1f0ab72,
+		0x8cc702081a6439ec,
+		0x90befffa23631e28,
+		0xa4506cebde82bde9,
+		0xbef9a3f7b2c67915,
+		0xc67178f2e372532b,
+		0xca273eceea26619c,
+		0xd186b8c721c0c207,
+		0xeada7dd6cde0eb1e,
+		0xf57d4f7fee6ed178,
+		0x06f067aa72176fba,
+		0x0a637dc5a2c898a6,
+		0x113f9804bef90dae,
+		0x1b710b35131c471b,
+		0x28db77f523047d84,
+		0x32caab7b40c72493,
+		0x3c9ebe0a15c9bebc,
+		0x431d67c49c100d4c,
+		0x4cc5d4becb3e42b6,
+		0x597f299cfc657e2a,
+		0x5fcb6fab3ad6faec,
+		0x6c44198c4a475817,
+	]
+)
+
+fn block_generic(dig &Digest, p []byte) {
+	// Note: When u64 const is working remove this
+	_k := [
+		u64(0x428a2f98d728ae22),
+		u64(0x7137449123ef65cd),
+		u64(0xb5c0fbcfec4d3b2f),
+		u64(0xe9b5dba58189dbbc),
+		u64(0x3956c25bf348b538),
+		u64(0x59f111f1b605d019),
+		u64(0x923f82a4af194f9b),
+		u64(0xab1c5ed5da6d8118),
+		u64(0xd807aa98a3030242),
+		u64(0x12835b0145706fbe),
+		u64(0x243185be4ee4b28c),
+		u64(0x550c7dc3d5ffb4e2),
+		u64(0x72be5d74f27b896f),
+		u64(0x80deb1fe3b1696b1),
+		u64(0x9bdc06a725c71235),
+		u64(0xc19bf174cf692694),
+		u64(0xe49b69c19ef14ad2),
+		u64(0xefbe4786384f25e3),
+		u64(0x0fc19dc68b8cd5b5),
+		u64(0x240ca1cc77ac9c65),
+		u64(0x2de92c6f592b0275),
+		u64(0x4a7484aa6ea6e483),
+		u64(0x5cb0a9dcbd41fbd4),
+		u64(0x76f988da831153b5),
+		u64(0x983e5152ee66dfab),
+		u64(0xa831c66d2db43210),
+		u64(0xb00327c898fb213f),
+		u64(0xbf597fc7beef0ee4),
+		u64(0xc6e00bf33da88fc2),
+		u64(0xd5a79147930aa725),
+		u64(0x06ca6351e003826f),
+		u64(0x142929670a0e6e70),
+		u64(0x27b70a8546d22ffc),
+		u64(0x2e1b21385c26c926),
+		u64(0x4d2c6dfc5ac42aed),
+		u64(0x53380d139d95b3df),
+		u64(0x650a73548baf63de),
+		u64(0x766a0abb3c77b2a8),
+		u64(0x81c2c92e47edaee6),
+		u64(0x92722c851482353b),
+		u64(0xa2bfe8a14cf10364),
+		u64(0xa81a664bbc423001),
+		u64(0xc24b8b70d0f89791),
+		u64(0xc76c51a30654be30),
+		u64(0xd192e819d6ef5218),
+		u64(0xd69906245565a910),
+		u64(0xf40e35855771202a),
+		u64(0x106aa07032bbd1b8),
+		u64(0x19a4c116b8d2d0c8),
+		u64(0x1e376c085141ab53),
+		u64(0x2748774cdf8eeb99),
+		u64(0x34b0bcb5e19b48a8),
+		u64(0x391c0cb3c5c95a63),
+		u64(0x4ed8aa4ae3418acb),
+		u64(0x5b9cca4f7763e373),
+		u64(0x682e6ff3d6b2b8a3),
+		u64(0x748f82ee5defb2fc),
+		u64(0x78a5636f43172f60),
+		u64(0x84c87814a1f0ab72),
+		u64(0x8cc702081a6439ec),
+		u64(0x90befffa23631e28),
+		u64(0xa4506cebde82bde9),
+		u64(0xbef9a3f7b2c67915),
+		u64(0xc67178f2e372532b),
+		u64(0xca273eceea26619c),
+		u64(0xd186b8c721c0c207),
+		u64(0xeada7dd6cde0eb1e),
+		u64(0xf57d4f7fee6ed178),
+		u64(0x06f067aa72176fba),
+		u64(0x0a637dc5a2c898a6),
+		u64(0x113f9804bef90dae),
+		u64(0x1b710b35131c471b),
+		u64(0x28db77f523047d84),
+		u64(0x32caab7b40c72493),
+		u64(0x3c9ebe0a15c9bebc),
+		u64(0x431d67c49c100d4c),
+		u64(0x4cc5d4becb3e42b6),
+		u64(0x597f299cfc657e2a),
+		u64(0x5fcb6fab3ad6faec),
+		u64(0x6c44198c4a475817)
+	]
+	
+	mut w := [u64(0); 80]
+	mut h0 := dig.h[0]
+	mut h1 := dig.h[1]
+	mut h2 := dig.h[2]
+	mut h3 := dig.h[3]
+	mut h4 := dig.h[4]
+	mut h5 := dig.h[5]
+	mut h6 := dig.h[6]
+	mut h7 := dig.h[7]
+	for p.len >= Chunk {
+		for i := 0; i < 16; i++ {
+			j := i * 8
+			w[i] = u64(u64(u64(p[j])<<u64(56)) | u64(u64(p[j+1])<<u64(48)) | u64(u64(p[j+2])<<u64(40)) | u64(u64(p[j+3])<<u64(32)) |
+				u64(u64(p[j+4])<<u64(24)) | u64(u64(p[j+5])<<u64(16)) | u64(u64(p[j+6])<<u64(8)) | u64(p[j+7]))
+		}
+		for i := 16; i < 80; i++ {
+			v1 := w[i-2]
+			t1 := (u64(v1>>u64(19)) | u64(v1<<u64(64-19))) ^ u64(u64(v1>>u64(61)) | u64(v1<<u64(64-61))) ^ u64(v1 >> u64(6))
+			v2 := w[i-15]
+			t2 := (u64(v2>>u64(1)) | u64(v2<<u64(64-1))) ^ u64(u64(v2>>u64(8)) | u64(v2<<u64(64-8))) ^ u64(v2 >> u64(7))
+
+			w[i] = t1 + w[i-7] + t2 + w[i-16]
+		}
+
+		mut a := h0
+		mut b := h1
+		mut c := h2
+		mut d := h3
+		mut e := h4
+		mut f := h5
+		mut g := h6
+		mut h := h7
+
+		for i := 0; i < 80; i++ {
+			// t1 := h + (u64(u64(e>>u64(14)) | u64(e<<u64(64-14))) ^ u64(u64(e>>u64(18)) | u64(e<<u64(64-18))) ^ u64(u64(e>>u64(41)) | u64(e<<u64(64-41)))) + ((e & f) ^ (~e & g)) + u64(_K[i]) + w[i]
+			// Note: When u64 const is working replace this line with the one above
+			t1 := h + (u64(u64(e>>u64(14)) | u64(e<<u64(64-14))) ^ u64(u64(e>>u64(18)) | u64(e<<u64(64-18))) ^ u64(u64(e>>u64(41)) | u64(e<<u64(64-41)))) + ((e & f) ^ (~e & g)) + u64(_k[i]) + w[i]
+			t2 := (u64(u64(a>>u64(28)) | u64(a<<u64(64-28))) ^ u64(u64(a>>u64(34)) | u64(a<<u64(64-34))) ^ u64(u64(a>>u64(39)) | u64(a<<u64(64-39)))) + ((a & b) ^ (a & c) ^ (b & c))
+			h = g
+			g = f
+			f = e
+			e = d + t1
+			d = c
+			c = b
+			b = a
+			a = t1 + t2
+		}
+
+		h0 += a
+		h1 += b
+		h2 += c
+		h3 += d
+		h4 += e
+		h5 += f
+		h6 += g
+		h7 += h
+
+		if Chunk >= p.len {
+			p = []byte
+		} else {
+			p = p.right(Chunk)
+		}
+	}
+
+	dig.h[0] = h0
+	dig.h[1] = h1
+	dig.h[2] = h2
+	dig.h[3] = h3
+	dig.h[4] = h4
+	dig.h[5] = h5
+	dig.h[6] = h6
+	dig.h[7] = h7
+}