Files
revive/crates/integration/contracts/SHA1.sol
T

241 lines
8.9 KiB
Solidity

// SPDX-License-Identifier: BSD-2-Clause
pragma solidity ^0.8.4;
contract SHA1 {
function sha1(bytes memory data) public pure returns (bytes20 ret) {
assembly {
// Get a safe scratch location
let scratch := mload(0x40)
// Get the data length, and point data at the first byte
let len := mload(data)
data := add(data, 32)
// Find the length after padding
let totallen := add(and(add(len, 1), 0xFFFFFFFFFFFFFFC0), 64)
switch lt(sub(totallen, len), 9)
case 1 {
totallen := add(totallen, 64)
}
let h := 0x6745230100EFCDAB890098BADCFE001032547600C3D2E1F0
function readword(ptr, off, count) -> result {
result := 0
if lt(off, count) {
result := mload(add(ptr, off))
count := sub(count, off)
if lt(count, 32) {
let mask := not(sub(exp(256, sub(32, count)), 1))
result := and(result, mask)
}
}
}
for {
let i := 0
} lt(i, totallen) {
i := add(i, 64)
} {
mstore(scratch, readword(data, i, len))
mstore(add(scratch, 32), readword(data, add(i, 32), len))
// If we loaded the last byte, store the terminator byte
switch lt(sub(len, i), 64)
case 1 {
mstore8(add(scratch, sub(len, i)), 0x80)
}
// If this is the last block, store the length
switch eq(i, sub(totallen, 64))
case 1 {
mstore(
add(scratch, 32),
or(mload(add(scratch, 32)), mul(len, 8))
)
}
// Expand the 16 32-bit words into 80
for {
let j := 64
} lt(j, 128) {
j := add(j, 12)
} {
let temp := xor(
xor(
mload(add(scratch, sub(j, 12))),
mload(add(scratch, sub(j, 32)))
),
xor(
mload(add(scratch, sub(j, 56))),
mload(add(scratch, sub(j, 64)))
)
)
temp := or(
and(
mul(temp, 2),
0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
),
and(
div(temp, 0x80000000),
0x0000000100000001000000010000000100000001000000010000000100000001
)
)
mstore(add(scratch, j), temp)
}
for {
let j := 128
} lt(j, 320) {
j := add(j, 24)
} {
let temp := xor(
xor(
mload(add(scratch, sub(j, 24))),
mload(add(scratch, sub(j, 64)))
),
xor(
mload(add(scratch, sub(j, 112))),
mload(add(scratch, sub(j, 128)))
)
)
temp := or(
and(
mul(temp, 4),
0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC
),
and(
div(temp, 0x40000000),
0x0000000300000003000000030000000300000003000000030000000300000003
)
)
mstore(add(scratch, j), temp)
}
let x := h
let f := 0
let k := 0
for {
let j := 0
} lt(j, 80) {
j := add(j, 1)
} {
switch div(j, 20)
case 0 {
// f = d xor (b and (c xor d))
f := xor(
div(x, 0x100000000000000000000),
div(x, 0x10000000000)
)
f := and(div(x, 0x1000000000000000000000000000000), f)
f := xor(div(x, 0x10000000000), f)
k := 0x5A827999
}
case 1 {
// f = b xor c xor d
f := xor(
div(x, 0x1000000000000000000000000000000),
div(x, 0x100000000000000000000)
)
f := xor(div(x, 0x10000000000), f)
k := 0x6ED9EBA1
}
case 2 {
// f = (b and c) or (d and (b or c))
f := or(
div(x, 0x1000000000000000000000000000000),
div(x, 0x100000000000000000000)
)
f := and(div(x, 0x10000000000), f)
f := or(
and(
div(x, 0x1000000000000000000000000000000),
div(x, 0x100000000000000000000)
),
f
)
k := 0x8F1BBCDC
}
case 3 {
// f = b xor c xor d
f := xor(
div(x, 0x1000000000000000000000000000000),
div(x, 0x100000000000000000000)
)
f := xor(div(x, 0x10000000000), f)
k := 0xCA62C1D6
}
// temp = (a leftrotate 5) + f + e + k + w[i]
let temp := and(
div(
x,
0x80000000000000000000000000000000000000000000000
),
0x1F
)
temp := or(
and(
div(x, 0x800000000000000000000000000000000000000),
0xFFFFFFE0
),
temp
)
temp := add(f, temp)
temp := add(and(x, 0xFFFFFFFF), temp)
temp := add(k, temp)
temp := add(
div(
mload(add(scratch, mul(j, 4))),
0x100000000000000000000000000000000000000000000000000000000
),
temp
)
x := or(
div(x, 0x10000000000),
mul(temp, 0x10000000000000000000000000000000000000000)
)
x := or(
and(
x,
0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF
),
mul(
or(
and(div(x, 0x4000000000000), 0xC0000000),
and(div(x, 0x400000000000000000000), 0x3FFFFFFF)
),
0x100000000000000000000
)
)
}
h := and(
add(h, x),
0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF
)
}
ret := mul(
or(
or(
or(
or(
and(
div(h, 0x100000000),
0xFFFFFFFF00000000000000000000000000000000
),
and(
div(h, 0x1000000),
0xFFFFFFFF000000000000000000000000
)
),
and(div(h, 0x10000), 0xFFFFFFFF0000000000000000)
),
and(div(h, 0x100), 0xFFFFFFFF00000000)
),
and(h, 0xFFFFFFFF)
),
0x1000000000000000000000000
)
}
}
}