I want to check duplicates of secret information which is also already encrypted in our database(using ECC algorithm, one of the std curves). plaintexts can be phone numbers, zip codes, etc. Since it's not possible to query encrypted information without doing a full table scan or building on index on long ciphertext, I am thinking of doing something like
hmac(key, plaintext). However, since this is susceptible to a rainbow table attack, I am considering if it's better to perform
hmac(salt || key, plaintext).
Ofcourse, since this is for "duplicate" checking, I cannot randomly generate a salt, since each secret has to hash into the same hash value. So the idea is to generate, say, 128 salts(that I can rotate regularly) and pick salt using
salt = saltlist[crc32(plaintext) % 128], this gives some rainbow table protection + the ability to find duplicates, which still allowing every key and salt to be rotated. Since we have a finite set of salts, we can store it securely in a key store.
hmac(salt || key, plaintext)or
hmac(key, salt || plaintext)?
Does having 128 salts(or any constant value) even provide any additional protection. (if the number of values goes into millions)?
Does it even make sense to have an extra secret key, or just
hmac(oneof128salts, plaintext)provide the same amount of protection?
I am not sure if this is over-engineered?