I have a table in Postgres that stores phone numbers. Since phone numbers are considered PII, I cannot store them as plaintext.
For other PII fields, I use AES-256-CBC. However, the requirements are that phone numbers are
- part of a uniqueness constraint (with another column)
- searchable
Using AES in CBC mode with a different IV for each encryption defeats those requirements.
What would be the best way to implement searchable encryption for phone numbers?
I've read Is it easy to crack a hashed phone number?, which suggests using either an HMAC or encryption. However, their requirements do not include searching.
I've also read Effective ways to hash phone numbers? where answerers suggest using a KDF, again without searchability in mind.
2 ideas:
- Add an extra column that stores an HMAC hash of the phone number. Drawback, other than the additional storage overhead of the column, is information leakage: the same phone number will result in the same digest every time. (I could exchange the HMAC with some KDF such as PBKDF2, scrypt or Argon2 but use a pepper stored in the application instead of a different salt per phone number to still allow searching.)
- Use the same IV for every encryption under AES-256-CBC. This also results in information leakage as now the first encrypted block is the same if the phone numbers are the same (the small search space allows us to store them in < 16 bytes).