-
-
Save RagePit/02cfa6568d8bf0a4933cd7f3ec42d948 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.19; | |
/// @author @rage_pit | |
/// @notice Not written to be particularly readable | |
library SHA256 { | |
/** | |
Taken from: | |
https://eips.ethereum.org/assets/eip-2680/sha256-384-512.pdf | |
https://gist.github.com/hak8or/8794351 | |
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf | |
Thanks to https://sha256algorithm.com/ | |
*/ | |
uint constant H_OFFSET = 0; | |
uint constant K_OFFSET = 32; | |
uint constant BLOCK_OFFSET = 288; | |
// NOT AUDITED FOR PRODUCTION | |
function hash(bytes memory _input) internal pure returns(bytes32 output) { | |
bytes memory input = _input; | |
assembly { | |
let len := mload(input) | |
let dataPtr := add(input, 0x20) | |
// pad message with 0b1 | |
mstore(add(len, dataPtr), shl(248, 0x80)) | |
// pad with zeros to nearest multiple of 64 bytes | |
let pad := mod(len, 64) | |
let k := add(len, sub(56, pad)) | |
switch lt(pad, 56) | |
case 0 { k := add(k, 64) } | |
//zero out to end of padding | |
calldatacopy(add(dataPtr, add(len, 1)), calldatasize(), k) | |
// end padding with message length | |
mstore(add(k, dataPtr), shl(192, mul(8, len))) | |
// number of rounds | |
let N := add(div(k, 64), 1) | |
// pointer to the end of the padded message | |
let START := add(dataPtr, mul(N, 64)) | |
// To avoid stack-too-deep we store the intermidiate hashes, and constant K values in memory | |
// Copied from SHA256 spec | |
mstore(add(START, H_OFFSET), 0x6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19) | |
mstore(add(START, add(K_OFFSET, 0)), 0x428a2f9871374491b5c0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5) | |
mstore(add(START, add(K_OFFSET, 32)), 0xd807aa9812835b01243185be550c7dc372be5d7480deb1fe9bdc06a7c19bf174) | |
mstore(add(START, add(K_OFFSET, 64)), 0xe49b69c1efbe47860fc19dc6240ca1cc2de92c6f4a7484aa5cb0a9dc76f988da) | |
mstore(add(START, add(K_OFFSET, 96)), 0x983e5152a831c66db00327c8bf597fc7c6e00bf3d5a7914706ca635114292967) | |
mstore(add(START, add(K_OFFSET, 128)), 0x27b70a852e1b21384d2c6dfc53380d13650a7354766a0abb81c2c92e92722c85) | |
mstore(add(START, add(K_OFFSET, 160)), 0xa2bfe8a1a81a664bc24b8b70c76c51a3d192e819d6990624f40e3585106aa070) | |
mstore(add(START, add(K_OFFSET, 192)), 0x19a4c1161e376c082748774c34b0bcb5391c0cb34ed8aa4a5b9cca4f682e6ff3) | |
mstore(add(START, add(K_OFFSET, 224)), 0x748f82ee78a5636f84c878148cc7020890befffaa4506cebbef9a3f7c67178f2) | |
function H(start, i) -> a { a := shr(224, mload(add(start, add(H_OFFSET, mul(4, i))))) } | |
function setH(start, i, n) { | |
let off := add(start, add(H_OFFSET, mul(4, i))) | |
mstore(off, or(shl(224, n), and(mload(off), 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff))) | |
} | |
function K(start, i) -> a { a := shr(224, mload(add(start, add(K_OFFSET, mul(4, i))))) } | |
function W(blockPtr, i) -> a { a := mload(add(blockPtr, mul(i, 32))) } | |
function setW(blockPtr, i, word) { mstore(add(blockPtr, mul(i, 32)), word) } | |
function ROTRIGHT(word, bits) -> a { a := or(shr(bits, word), shl(sub(32, bits), word)) } | |
function SSIG0(x) -> a { a := xor(xor(ROTRIGHT(x,7), ROTRIGHT(x,18)), shr(3, x)) } | |
function SSIG1(x) -> a { a := xor(xor(ROTRIGHT(x,17), ROTRIGHT(x,19)), shr(10, x)) } | |
function EP0(x) -> a { a := and(xor(xor(ROTRIGHT(x,2), ROTRIGHT(x,13)), ROTRIGHT(x,22)), 0xffffffff) } | |
function EP1(x) -> a { a := and(xor(xor(ROTRIGHT(x,6), ROTRIGHT(x,11)), ROTRIGHT(x,25)), 0xffffffff) } | |
function CH(x, y, z) -> a { a := xor(and(x, y), and(and(not(x), 0xffffffff), z)) } | |
function MAJ(x, y, z) -> a { a := xor(xor(and(x, y), and(x, z)), and(y, z)) } | |
for {let i := 0} lt(i, N) {i := add(i, 1)} { | |
let B := add(START, BLOCK_OFFSET) | |
// Preparing the message schedule | |
for {let t := 0} lt(t, 16) {t := add(t, 1)} { | |
let word := shr(224, mload(add(dataPtr, add(mul(t, 4), mul(i, 64))))) | |
setW(B, t, word) | |
} | |
for {let t := 16} lt(t, 64) {t := add(t, 1)} { | |
let w := add(add(add( | |
SSIG1(W(B, sub(t,2))), | |
W(B, sub(t,7))), | |
SSIG0(W(B, sub(t,15)))), | |
W(B, sub(t,16))) | |
setW(B, t, and(w, 0xffffffff)) | |
} | |
// Init | |
let a := H(START, 0) | |
let b := H(START, 1) | |
let c := H(START, 2) | |
let d := H(START, 3) | |
let e := H(START, 4) | |
let f := H(START, 5) | |
let g := H(START, 6) | |
let h := H(START, 7) | |
for {let t := 0} lt(t, 64) {t := add(t, 1)} { | |
let temp1 := add(h, add(EP1(e), add(CH(e,f,g), add(K(START,t), W(B,t))))) | |
let temp2 := add(EP0(a), MAJ(a,b,c)) | |
h := g | |
g := f | |
f := e | |
e := and(add(d, temp1), 0xffffffff) | |
d := c | |
c := b | |
b := a | |
a := and(add(temp1, temp2), 0xffffffff) | |
} | |
setH(START, 0, and(add(a, H(START, 0)), 0xffffffff)) | |
setH(START, 1, and(add(b, H(START, 1)), 0xffffffff)) | |
setH(START, 2, and(add(c, H(START, 2)), 0xffffffff)) | |
setH(START, 3, and(add(d, H(START, 3)), 0xffffffff)) | |
setH(START, 4, and(add(e, H(START, 4)), 0xffffffff)) | |
setH(START, 5, and(add(f, H(START, 5)), 0xffffffff)) | |
setH(START, 6, and(add(g, H(START, 6)), 0xffffffff)) | |
setH(START, 7, and(add(h, H(START, 7)), 0xffffffff)) | |
} | |
output := mload(add(START, H_OFFSET)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment