I have a need to anonymise phone numbers so that I can carry out testing and analysis work on telecoms data sets and comply with GDPR. I typically receive a batch of a few hundred thousand events containing phone numbers, and need to anonymise all the phone numbers in that batch under the following conditions:
A definable prefix of the number should remain the same - I should only transform the right-most n digits. n will typically be between 2 and 6
I should always transform the digits in the same way - abcd should always be mapped to efgh
The transformation should be one-to-one - efgh should be that output for only one input
I should only output digits
If I then receive a further batch of events condition 2 is removed - I can use a new transformation for a new batch.
I've considered two approaches to this requirement:
Randomly create a lookup table mapping each n digit string to another n digit string - I will do this for all n digit strings as a one-time exercise prior to encrypting a batch, and generate a new lookup table for a new batch
Use one of the Format Preserving Encryption algorithms - e.g. Format-preserving, Feistel-based encryption (FFX) as implemented in the PyFFX or libffx libraries, or FE1 in the botan library
In some cases I may need to reconstruct the original phone numbers in the future in which case I will store the encryption key or lookup table in some secure fashion. In some cases I know I will not need to reconstruct them in which case I will discard the key directly after encryption.
Is there any advantage to using approach 2 over approach 1? I can see the following possibilities:
Using a random number generator in 1 may be slightly less robust than using FPE
The encryption key for FPE can be substantially smaller than the mapping table in point 1 if there is a need to retain it
A publicly available FPE implementation may contain fewer vulnerabilities than a home-grown random lookup implementation
Are there any other considerations I should have in mind?