algorithmsecuritymappingobfuscationanonymity

Mapping a value to an other value and back


Imagine a value, say '1234'. I want to map that value to an other value, say 'abcd'. The constrains:

  1. The length of the target value is equal to the start value
  2. The mapping should be unique. E.g. 1234 should only map to abcd and viseversa
  3. The mapping process should be (very) difficult to guess. E.g. multiplying by 2 does count
  4. The mapping should be reversible
  5. The start value is an integer
  6. The target value can be of any type

This should be a basic algorithm, eventually I'll write it in Ruby but that is of no concern here.

I was thinking along the following lines:

SECRET = 1234
def to(int)
  SECRET + int * 2
end

def fro(int)
  (int - SECRET)  / 2
end

Obviously this violates constrains 1 and 3.

The eventual goal is to anonymize records in my database. I might be over thinking this.


Solution

  • First off, I rather think your objectives are too ambitious: why constraint 6?

    Second, what you need is technically a bijection from the domain of integers.

    Third, your constraint 3 goes against Kerkhoff's principle. You'd be better off with a well-known algorithm governed by a secret key, where the secret key is hard to derive even if you know the results for a large set of integers.

    Fourth, what are you anonymizing against? If you are dealing with personal information, how will you protect against statistical analysis revealing that Xyzzy is actually John Doe, based on the relations to other data? There's some research on countering such attack vectors (google for e.g. 'k-anonymization').

    Fifth, use existing cryptographic primitives rather than trying to invent your own. Encryption algorithms exist (e.g. AES in cipher-block-chaining mode) that are well-tested -- AES is well supported by all modern platforms, presumably Ruby as well. However, encryption still doesn't give records anonymity in any strong sense.