Toy one-way hash function for six digit number I need to copy some data from a secure server to my laptop to work on it with a program (this description is very vague, I know). The data have six digit employee numbers and we are strictly prohibited from downloading data with these.

I was wondering if there is a really simple hash function I could put in a spreadsheet to convert these employee numbers into a one way hash so I can download these? All I care about is being able to tell which data came from the same employee number. I am not terribly concerned about a few collisions either, the set is small enough I could look for those.

I was thinking some simple xor with an added salt or squaring and taking some digits but everything seems like it would be too guessable especially if there is a series of sequential employee numbers in a row.

For example, hash

123456 


to somerandomlookingstring, but I need to be sure the next result is

123457 


is not terribly similar, so not like: somerandomlookingstrifh

I feel like this is something hardcore crypto people may know off-hand, some mini ancestor of MD5, some evolution of ROT13, but light enough for thousands of spreadsheet cells.
A six digit integer gives you a possible one million possible IDs. Consider this python code that hashes every possible ID using a properly vetted, secure, cryptographic hash function:

import hashlib
import time

t0 = time.time()

for i in range(1000000):
    hashlib.blake2b(bin(i).encode("utf-8"))

t1 = time.time()

print(t1-t0)


It runs in around 400ms on my laptop. An attacker could generate a look-up table in less than a second that would map these output hashes back to the original employee numbers that they derive from.

In order to combat this, you'd have to use some kind of "hard" cryptographic hash like Argon2 or PBKDF2 in order to ramp up the computational complexity of generating a rainbow table.

But really this is just pushing the problem down the road and making it more difficult for yourself as well.

The better solution is to generate your own random lookup table and use that as a substitution in your spreadsheet. Consider:

import secrets

lookup = {}

for i in range(1000000):
        lookup[i] = secrets.randbelow(1000000)

# employee id "662893" is mapped to which masked value?
print(lookup[662893])


The code is not quite what you want as there's no padding to six digits and the reverse lookup is likely the more useful one, and it does not check for collisions, but it serves to make the point.

Tackling collisions can be done by selecting IDs from the set of unused IDs, or just increasing the length of the random values so that the probability of collisions becomes negligible.

In this scheme where each employee is mapped to a unique ID, an attacker has no way of computing the original employee ID from the masked value without the lookup table, as they were generated randomly.

If the small (2x) memory overhead of this solution is unacceptable, Maarten's solution of using a keyed hash function is also viable. Simply use a HMAC construction with a secure hash function and a 32 byte key, and the attacker would have no way of bruteforcing the inputs without knowing the key.