Search code examples
c#functionhashbase32

Converting an int to a pseudo-random string and vice versa


I need to create two C# functions, one (called f1) to convert an integer to a string and another (called f2) to convert that string to the starting integer. The strings should look like a random set of 5-character (letters and numbers). It must be ensured that there are no collisions (two possible integers for the same string) for at least the first 16 million integers (I'm not interested in converting too large numbers).

//Where the "BytesToBase32" function converts a byte array to base 32 ()
string IntToString(int id) {
    byte[] bytes = BitConverter.GetBytes(id);
    return Utils.BytesToBase32(new byte[] {
        (byte)(004 + 145 * bytes[0] + 113 * bytes[1] + 051 * bytes[2]),
        (byte)(166 + 237 * bytes[0] + 010 * bytes[1] + 212 * bytes[2]),
        (byte)(122 + 171 * bytes[0] + 135 * bytes[1] + 020 * bytes[2])
    });
}

It returns values like this:

  • 0 --> 0ij7k
  • 1 --> im9ia
  • 2 --> 4q0d0
  • 3 --> mtmnm
  • ...

As you can see the strings seem random (in other words it is not possible to understand that "0ij7k" comes before "im9ia" and vice versa).

The problem is that the function f2 cannot be obtained by simply solving the 3 equation system used by f1. Is there a simpler way to get f1 and f2?


Solution

  • In the comments I was wrong about the stream cipher. You actually need a block cipher, but the size of your block must be 24 bits (for 16 million integers). See this question and the answer: https://crypto.stackexchange.com/q/18988

    These types of ciphers are called Format-preserving encryption (FPE). One such FPE is called FF1.

    There is a C# implementation of FF1 on github: https://github.com/a-tze/FPE.Net