Reversible “hash” function from 64-bit integer to 64-bit integer

痴心易碎 提交于 2019-12-30 08:37:06

问题


What I need is a reversible function that transforms a long (64-bit integer) into another long number, in a way that seems "random" for a user (but actually is deterministic), so that 3 subsequent numbers are transformed into 3 numbers completely different to each other.

It is easy to do it without being reversible, but it turns out pretty difficult when it comes to this part.

Basically it's the same question as Reversible hash function?, but I need more than 2^32 distinct values.

Any ideas?

PS: I'm going to write it in Java, but the question itself is pretty generic.


回答1:


These are the basic requirements for a block cipher, which is usually implemented with a Feistel structure: https://en.wikipedia.org/wiki/Feistel_cipher

  1. Create a hash of the lower 32 bits and XOR it into the upper 32 bits
  2. Swap the lower and upper 32 bits
  3. Repeat a few times.



回答2:


You can use any 64-bit block cipher (for example, DES), and use encrypt for a "hash", and decrypt for an "reverse hash".




回答3:


If security is not your concern and you just need to visually randomize the numbers, a really fast solution is using a simple XOR with a fixed key in your code. To get it back, just XOR again with this 'secret' key.

If you are interested in security, but you have no space limitations, you may use bigger keys (eg a sliding XOR) or even an OTP. Here is a Java example of OTP.

I should also highlight the following two cases where already proposed solutions using certain symmetric encryption algorithms (even the simple XOR or OTP) may not work as expected.

  1. If we need to maintain the sign of the number
  2. If we need to maintain the size of the number (eg I have a 5digit number and I want to show its reversible-randomized 5 digit version (or at least close to its size (4-6))

To support the above requirements, a policy-based modified XOR/OTP, that applies only on the required bits, can be a good candidate.




回答4:


static long GMULL = 0x9E3779B97F4A7C15L;
static long GDIVL = 0xF1DE83E19937733DL;
static long GADDL = 0x0123456789ABCDEFL;
public static long golden64fwd(long key) {
    key *= GMULL;
    key += GADDL;
    return key;
}

public static long golden64rev(long key) {
    key -= GADDL;
    key *= GDIVL;
    return key;
}

static int GMULI = 0x9E3779B9;
static int GDIVI = 0x144CBC89;
static int GADDI = 0x01234567;
public static int golden32fwd(int key) {
    key *= GMULL;
    key += GADDL;
    return key;        
}

public static int golden32rev(int key) {
    key -= GADDI;
    key *= GDIVI;
    return key;        
}

So as far as hash properties are concerned it is at best average. GMUL[I,N] are the approximate golden ratio for 64 and 32 bit. GDIV[I,N] are the respective multiplicative inverses mod 2^size. GADD[I,N] is an odd number. There are numbers that are consecutive and their "hashed" values are also very close. But I doubt that there are three in a row.



来源:https://stackoverflow.com/questions/34465444/reversible-hash-function-from-64-bit-integer-to-64-bit-integer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!