estranged
estranged

Reputation: 432

Hash multiple iterations of a value over itself

I am trying to write a function which calculates multiple iteration hashes of a specific value (and output each iteration in the meantime).

However, I can't get my head over how to perform, for instance, md5 hash function on itself multiple times. For instance:

a = hashlib.md5('fun').hexdigest()
b = hashlib.md5(a).hexdigest()
c = hashlib.md5(b).hexdigest()
d = hashlib.md5(c).hexdigest()
.......

I think the recursion is the solution, but I just can't seem to implement it properly. This is the general factorial recursion example, but how do I adapt it to hashes:

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

Upvotes: 1

Views: 1341

Answers (3)

chepner
chepner

Reputation: 531718

In general, you are looking for a loop like

while True:
    x = f(x)

where you repeatedly replace the input with the result of the most recent application.

For your specific example,

def iterated_hash(x):
    while True:
        x = hashlib.md5(x).hexdigest()
    return x

However, since you don't really want to do this an infinite number of times, you need to supply a count:

def iterated_hash(x, n):
    while True:
        if n == 0:
            return x
        x = hashlib.md5(x).hexdigest()

or with a for loop,

def iterated_hash(x, n):
    for _ in range(n):
        x = hashlib.md5(x).hexdigest()
    return x

(Practically speaking, you want to use the for loop, but it's nice to see how the for loop is just a finite special case of the more general infinite loop.)

Upvotes: 1

quamrana
quamrana

Reputation: 39404

Just iterate as many times as needed:

def make_hash(text, iterations):
    a = hashlib.md5(text).hexdigest()
    for _ in range(iterations):
        a = hashlib.md5(a).hexdigest()
    return a


a = make_hash('fun', 5)  # 5 iterations

Upvotes: 0

Hans Musgrave
Hans Musgrave

Reputation: 7131

This is a classic application of generators. Python allows a maximum of 500 recursions due to its unusually heavy stack. For anything which might be executed anywhere near that many times, iteration will often be faster. Using a generator allows you to break after any desired number of executions and allows flat usage of the desired logic in your code. The following example prints the output of 10 such executions.

from itertools import islice

def hashes(n):
    while True:
        n = hashlib.md5(n).hexdigest()
        yield n

for h in islice(hashes('fun'), 10):
    print(h)

Upvotes: 5

Related Questions