Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lightly alter a hash programmatically

At the moment I frequently have to do something in unittests with hashes and cryptographic signatures. Sometimes they get generated, and I just need to alter one slightly and prove that something no longer works. They are strings of hex-digits 0-9 and a-f of specific length. Here is a sample 64 long:

h = '702b31faad0246cc89a5dc782cdf5235a885d0f529fb30a4e1e70e00938df91a'

I want to change just one character somewhere in there.

You can't be sure that every digit 0 - 9 and a - f will be in there, although would guess it's at least 95% certain that they all are. If you could be sure, I would just run h = h.replace('a', 'b', 1) on it.

If you do it manually, you can just look at it and see the third digit is 2 and run:

new = list(h)
new[2] = '3'
h = ''.join(new)

But if you cannot see it and it needs to happen programmatically, what is a clean and certain way to change just one character in it somewhere?

like image 387
cardamom Avatar asked Aug 11 '26 06:08

cardamom


1 Answers

from random import randrange
h = '702b31faad0246cc89a5dc782cdf5235a885d0f529fb30a4e1e70e00938df91a'
i = randrange(len(h))
new_h = h[:i] + hex(int(h[i], 16) + randrange(1, 16))[-1:] + h[i+1:]

In words:

  • choose a random index i in h
  • split the string into the part before the index, the char at the index, and the rest
  • replace the char at the index with its hex value incremented by a random int between 1 and 15, modulo 16 (i.e., its rightmost hex character)
  • build the new string from the above pieces

Note that an increment by a value between 1 and 15 (included), followed by a modulo 16, never maps a hex digit onto itself. An increment by 0 or 16 would map it exactly onto itself.

like image 117
Walter Tross Avatar answered Aug 13 '26 00:08

Walter Tross



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!