0

As part of an application I am developing, I am required to store user email adresses on a cloud DB. The email address is not required to be in plain text for the normal operation of the application.

So, to provide security, the email address is being encrypted and then stored in the database. The email address in the encrypted form will be the primary means of identifying users (it is the primary key).

Given these facts, which of the following encryption methods makes sense if the database server is vulnerable to attacks.

Method 1:

Encrypted-Email-Address = Asymmetric Cipher(Pub-Key2, 
               Asymmetric Cipher(Pub-Key1, Plain-text-Email-address))

No random padding will be used to allow for deterministic mapping between plain and cipher email addresses, hence encryption twice

OR

Method 2:

Encrypted-Email-Address = Symmetric Cipher(Key, Plain-text-Email-address)

Note that because decryption is not required for the normal operation, the private Keys in method 1 will be stored offline in the physical world. The encryption will need to be deterministic though because the email address is the primary key.

I did go through https://stackoverflow.com/questions/6980044/using-asymmetric-encryption-to-secure-passwords. But there the OP is looking to store a non primary key field, so I am unable to use it.

Are you aware of any better methodologies which solve this use case?

5
  • 7
    You should not be using the email address, encrypted or otherwise as a primary key. Email addresses (and other "natural" keys) can change. Use surrogate keys. This will completely remove the requirement that email addresses be encrypted deterministically, which is fundamentally incompatible with many common notions of cryptographic security. Sep 30, 2013 at 20:53
  • This backend supports a mobile application in the front, so there are usability issues. Identifying the user becomes a problem if he/she logs in using a different device because I can't ask the user to remember his/her surrogate key (or a username that they may have chosen). Users remember their email addresses. I don't even need to ask for the email address and instead source it from the mobile platform without them having to type anything for sign-up or log-in.
    – dvlpr
    Oct 1, 2013 at 4:34
  • I think you're both mixing up index and primary key. You can still index a column containing the hashed value of the email address while using a surrogate key as primary. It even makes sense from a performance point of view if the primary key is clustered. What @dvlpr means is that he wants to use the email address as the main identifier for the user.
    – Stephane
    Oct 1, 2013 at 8:47
  • I don't understand why you couldn't simply use a keyed hash (HMAC) of the email (after normalizing the case) as lookup key for the account. Assuming that is not the only element that will allow the user to authenticate (i.e. you have a password in addition to the email address) that seems to fit your requirement.
    – Stephane
    Oct 1, 2013 at 8:50
  • Authentication is through OAuth, so I am not storing the passwords. About HMAC and symmetric ciphers, I am paranoid about storing the key on the same server as the data when no active decryption is required as part of normal operations. Seems like that is something that could be avoided.
    – dvlpr
    Oct 1, 2013 at 12:46

2 Answers 2

0

As far as I can tell, you're using the email address for 2 separate purposes, so why not store it twice?

In one column, you could store a hashed version, much like you would store a password. That's deterministic, so you can use it to look up a user by their email address.

Though, as others have mentioned, it's not a good idea to use it as a primary key. Use a surrogate key (e.g. an auto-increment) and create a unique index on the email column.

Then in a second column, you'd have an asymmetrically-encrypted version that you can decrypt with an offline private key if you ever need to. This one would not need to be deterministic, so you can use standard asymmetric encryption.

3
  • Thanks for your response. But I think the problem is unsolvable. Hashing a small/predictable string like email address without a per-email salt is still vulnerable to enumeration attacks as @Tom Leek mentioned :( The real problem is that we can only pick two out of these three: 1. Asymmetric, 2. Deterministic and 3. Strong. I would have loved to pick all three, but looks like its just not possible at this time. I think I will probably use a symmetric cipher and try to protect the key as much as I can. I only wonder how facebook/twitter do it. They too use emails to identify users.
    – dvlpr
    Oct 4, 2013 at 6:58
  • @dvlpr Good point. To be honest, I think a lot of sites don't bother to protect the email - just checked a couple of test sites' DBs (Drupal and MediaWiki) and they've got plaintext email addresses in them...
    – just me
    Oct 4, 2013 at 9:32
  • @dvlpr you could use a keyed hash (HMAC) which won't be vulnerable to enumeration attacks unless the key was compromised as well. Aug 12, 2017 at 17:20
3

Email addresses are subject to enumeration. There are not so many email addresses. Any deterministic scheme which uses no secret (i.e. no key that a possible attacker knows of) will do nothing against that. I don't know what you suppose that the "double asymmetric encryption" with two public keys achieves; but I know that it does not fix that core problem. Public keys are public.

Symmetric encryption, with a key that the attacker does not have, can be deterministic and yet safe (if done properly) but this hardly applies to your situation, since while you don't need decryption, you do need to encrypt a lot, because the user's email address is what the user types in.

An additional problem with email addresses is that they are not always reproducible: users may employ different casings (case is not significant in the domain part, after the '@', but it may be significant in the local part), use variants (many people have '[email protected]' and '[email protected]' as valid addresses) and include "comments" (as in '[email protected]') with a site-specific notion of what constitutes a "comment". As @Stephen suggests, it is better to simply allocate an ID to each user and use that ID as primary key.

4
  • Thanks for your response. The reason I am trying to encrypt twice is because without random padding I know that asymmetric cipher is weak. Maybe the second asym() cipher will strengthen it (because the output of first is 2048 bits)? And when you say public keys are public do you mean that public keys come out of a small set which can be guessed by attackers? Because the public keys on the server are going to be afforded the same level of protection that a symmetric key will get. They will not be released to the public.
    – dvlpr
    Oct 1, 2013 at 5:20
  • Those enumeration attacks are practical. I recovered 28% of stackexchange emails and reversity recovered 45% from some forums thanks to gravatar publishing a hash of the email address. They apply to any deterministic function, but can be slowed down using a slow function, like scrypt, bcrypt or PBKDF2. Oct 1, 2013 at 7:55
  • Public keys are not meant to be hidden, and in many cases can be recomputed from observed messages. And whoever encrypts must know them, so they cannot be really secret. As for accumulating layers in hope of some "strengthening", it is like throwing a pinch of salt over your shoulder so as to bring good luck: what you suggest amounts to: "yeah, one pinch of salt does not work, but maybe throwing a whole bucket will do the trick ?"
    – Tom Leek
    Oct 1, 2013 at 10:56
  • Yup, I know that double encryption is a shot in the dark :( What it looks like is there is no established method for this scenario. Because this use case is real and does add value in terms of security.
    – dvlpr
    Oct 1, 2013 at 12:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .