The message M is input into a hash function, as Mn where n is the iteration of the function (M0, M1...Mn). Mn will here be referred to as just M.
M maps to bit x = (M+R)%bits(M) in M, R is the output string constructed by the hash function. This bit is sliced from M, and the bit to the right of x is the new leftmost end of the binary string. The bit x is inserted in the output string R at position y = (M+R)%bits(R), and is the new leftmost end of the binary string R, and this bit x/y is transformed with a XOR operation, x⊕(M+R)%2.
The process is repeated for every bit in M.
To easier see the steps in the hash function, think of M as being wrapped into a circle, with the leftmost bit as the start site. This start site shifts similar to turning a vault knob, while extracting bits from M to construct the output R.
import math
import random
def vaultKnob(message, message_length, output, output_length):
x = (message+output)%message_length
bit = message>>(message_length-x-1) & 1
message = message>>(message_length-x) | message<<(x) & (1 << message_length-1) - 1
message_length -= 1
if output_length is not 0:
y = (message+output)%output_length
output = output>>(output_length-y) | output<<(y) & (1 << output_length) - 1
bit^=(message+output)%2
bit = bit<<output_length
output = bit | output
output_length+=1
return message, message_length, output, output_length
message = random.getrandbits(256)
message_length = int(math.log(message, 2))+1
output = 0
output_length = 0
print('{0:#0{width}b}'.format(message, width=2+message_length))
for n in range(message_length):
message, message_length, output, output_length = vaultKnob(message, message_length, output, output_length)
print('{0:#0{width}b}'.format(output, width=2+output_length))