Skip to content

Commit b43d2b2

Browse files
authored
Create verushash.py
1 parent edf7c37 commit b43d2b2

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

hashes/verushash.py

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import hashlib
2+
3+
def verushash(data):
4+
"""
5+
Compute VerusHash of the input data.
6+
VerusHash alternates between SHA-256 and Keccak-256 in a specific sequence.
7+
8+
Args:
9+
data (bytes): The input data to be hashed.
10+
11+
Returns:
12+
bytes: The VerusHash result as a byte string.
13+
"""
14+
def sha256(data):
15+
"""Compute SHA-256 hash of the input data using hashlib."""
16+
return hashlib.sha256(data).digest()
17+
18+
def keccak256(data):
19+
"""Compute Keccak-256 hash of the input data using a custom implementation."""
20+
# Keccak-256 parameters
21+
ROUNDS = 24
22+
RATE = 1088 # Rate in bits (1600 - 2*256)
23+
CAPACITY = 512 # Capacity in bits (2*256)
24+
STATE_SIZE = 1600 # State size in bits (5x5x64)
25+
26+
# Padding
27+
PADDING = 0x06
28+
DELIMITER = 0x80
29+
30+
# Initialize the state
31+
state = [0] * (STATE_SIZE // 8) # State in bytes
32+
33+
# Absorb phase
34+
block_size = RATE // 8
35+
padded_data = data + bytes([PADDING]) + bytes([0] * (block_size - (len(data) + 1) % block_size))
36+
padded_data += bytes([DELIMITER])
37+
38+
for i in range(0, len(padded_data), block_size):
39+
block = padded_data[i:i + block_size]
40+
for j in range(len(block)):
41+
state[j] ^= block[j]
42+
state = keccak_f(state)
43+
44+
# Squeeze phase
45+
output = bytearray()
46+
while len(output) < 32: # 256 bits = 32 bytes
47+
output.extend(state[:block_size])
48+
state = keccak_f(state)
49+
50+
return bytes(output[:32])
51+
52+
def keccak_f(state):
53+
"""Keccak-f permutation function."""
54+
# Convert state to a 5x5x64 array
55+
lanes = [[0] * 5 for _ in range(5)]
56+
for x in range(5):
57+
for y in range(5):
58+
index = 8 * (x + 5 * y)
59+
lane = int.from_bytes(state[index:index + 8], byteorder='little')
60+
lanes[x][y] = lane
61+
62+
# Perform 24 rounds of Keccak-f
63+
for round in range(ROUNDS):
64+
lanes = keccak_round(lanes, round)
65+
66+
# Convert lanes back to bytes
67+
state = bytearray()
68+
for y in range(5):
69+
for x in range(5):
70+
state.extend(lanes[x][y].to_bytes(8, byteorder='little'))
71+
72+
return state
73+
74+
def keccak_round(lanes, round):
75+
"""Perform one round of Keccak-f."""
76+
# Theta step
77+
c = [lanes[x][0] ^ lanes[x][1] ^ lanes[x][2] ^ lanes[x][3] ^ lanes[x][4] for x in range(5)]
78+
d = [c[(x - 1) % 5] ^ ((c[(x + 1) % 5] << 1 | c[(x + 1) % 5] >> 63) for x in range(5)]
79+
for x in range(5):
80+
for y in range(5):
81+
lanes[x][y] ^= d[x]
82+
83+
# Rho and Pi steps
84+
x, y = 1, 0
85+
current = lanes[x][y]
86+
for t in range(24):
87+
x, y = y, (2 * x + 3 * y) % 5
88+
current, lanes[x][y] = lanes[x][y], (current << ((t + 1) * (t + 2) // 2) | current >> (64 - ((t + 1) * (t + 2) // 2))
89+
90+
# Chi step
91+
for y in range(5):
92+
t = [lanes[x][y] for x in range(5)]
93+
for x in range(5):
94+
lanes[x][y] = t[x] ^ (~t[(x + 1) % 5] & t[(x + 2) % 5])
95+
96+
# Iota step
97+
lanes[0][0] ^= ROUND_CONSTANTS[round]
98+
99+
return lanes
100+
101+
# Round constants for Keccak-f
102+
ROUND_CONSTANTS = [
103+
0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
104+
0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
105+
0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
106+
0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
107+
0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
108+
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
109+
0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
110+
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
111+
]
112+
113+
# Step 1: Compute SHA-256 of the input data
114+
hash1 = sha256(data)
115+
116+
# Step 2: Compute Keccak-256 of the SHA-256 result
117+
hash2 = keccak256(hash1)
118+
119+
# Step 3: Compute SHA-256 of the Keccak-256 result
120+
hash3 = sha256(hash2)
121+
122+
# Step 4: Compute Keccak-256 of the final SHA-256 result
123+
final_hash = keccak256(hash3)
124+
125+
return final_hash
126+
127+
# Example usage
128+
if __name__ == "__main__":
129+
# Input data (can be a block header or any other data)
130+
input_data = b"Hello, VerusHash!"
131+
132+
# Compute VerusHash
133+
result = verushash(input_data)
134+
135+
# Print the result as a hexadecimal string
136+
print("VerusHash:", result.hex())

0 commit comments

Comments
 (0)