Reversible hash function?

前端 未结 5 1407
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-30 01:41

I need a reversible hash function (obviously the input will be much smaller in size than the output) that maps the input to the output in a random-looking way. Basically, I

5条回答
  •  遥遥无期
    2020-11-30 02:16

    Another simple solution is to use multiplicative inverses (see Eri Clippert's blog):

    we showed how you can take any two coprime positive integers x and m and compute a third positive integer y with the property that (x * y) % m == 1, and therefore that (x * z * y) % m == z % m for any positive integer z. That is, there always exists a “multiplicative inverse”, that “undoes” the results of multiplying by x modulo m.

    We take a large number e.g. 4000000000 and a large co-prime number e.g. 387420489:

    def rhash(n):
        return n * 387420489 % 4000000000
    
    >>> rhash(12)
    649045868
    

    We first calculate the multiplicative inverse with modinv which turns out to be 3513180409:

    >>> 3513180409 * 387420489 % 4000000000
    1
    

    Now, we can define the inverse:

    def un_rhash(h):
        return h * 3513180409 % 4000000000
    
    >>> un_rhash(649045868)  # un_rhash(rhash(12))
    12
    

    Note: This answer is fast to compute and works for numbers up to 4000000000, if you need to handle larger numbers choose a sufficiently large number (and another co-prime).


    You may want to do this with hexidecimal (to pack the int):

    def rhash(n):
        return "%08x" % (n * 387420489 % 4000000000)
    
    >>> rhash(12)
    '26afa76c'
    
    def un_rhash(h):
        return int(h, 16) * 3513180409 % 4000000000
    
    >>> un_rhash('26afa76c')  # un_rhash(rhash(12))
    12
    

    If you choose a relatively large co-prime then this will seem random, be non-sequential and also be quick to calculate.

提交回复
热议问题