Let's say that we want to develop a blogging service where only people with an @example.com email can contribute.

Prior to post submission, the user requests that a large random token be generated by the service and sent to their user@example.com email. This token is stored in the service's database and can then be used to verify that the person posting a certain message + token combination actually has control over an @example.com email address.

This works well as long as the user trusts that the service is not associating their email address with the token that they received. However, consider a scenario where a user would like to post something that cannot be traced back to them (by other users [this is easy], or by the service itself [the hard part]).

Is it possible to prove to the service that I own a certain email address (by knowing the contents of an email sent to the address) without allowing the service to associate that email address with a specific secret?

Currently, assuming a benevolent service, it is easy to allow posters to prove that they are the authors of an anonymous post by storing a "signature" alongside each post for all to see. This would be computed as hash(<posters_email_address>@example.com + <auth_token>) so that at any point, the original author could publicly announce their email and authorization token and the hashes could be checked. With this scheme, each poster is anonymous (if they choose to be) with respect to all other users / viewers of the platform, but critically, there is an unknown possibility that they are not anonymous to the platform (if it chooses to be malicious).

In summary, can we prove to a potentially malicious server that we received some sort of authorization (via access to an email address) in a way that prevents the service from associating that email address with the given token?

Edit: I have done some thinking and it appears as if the person who receives their token via email needs to do something to their token before they send it back to the server in order to make tracing that token back to them impossible. It must be modified in a way where it can't be compared to the original token, but still maintains some property where the server knows that there modified token is derived from some token that it issued.

Clarification: We are not administrators of the @example.com domain. There is nothing special about this domain other than the fact that we explicitly check that clients have an email registered there.

  • 1
    You could use SSO-style authentication, so that the owner/authenticator of example.com approves the connection, but the service provider(blogging service) does not need to know which email was used. – schroeder Jun 29 at 21:32
  • You could make it so the token is just a small number that a lot of users might have been given. For example, a six-digit number, like the login codes that one gets sent to their phone for 2FA. – mbomb007 Jun 30 at 21:29
  • Would a solution involving a trusted third party be acceptabel? (I was also thinking along the lines of your edit, but just the timing would make it relatively easy to make educated guesses about what token belongs to what email.) – Anders Jun 30 at 21:46
  • If example.com has published a DKIM record in their DNS, perhaps this can be used to solve the problem. The user signs some publicly-known value (e.g. the hash of the most recently mined bitcoin block) using the private key corresponding to the public key in the DKIM record for example.com, and submits the signature anonymously to the server. Then, the server verifies the signature, using the public key from the DKIM record. This proves that the user knows the private key corresponding to the public key in the DKIM record for example.com, but does not identify the individual user. – mti2935 Jun 30 at 22:46
  • 3
    IMO you cannot send any token to the users, because as soon as you send it you might be linking it to their address. Forget about sending anything to them. I'm afraid the only solution would involve a trusted third party (maybe the admin of example.com) and some kind of secret that only the account owners know (and the trusted third party), like a shared key, token, or password. The issue here is that you need them to authenticate (so a secret is needed) and at the same time the users need to feel sure they can't be distinguished (so the secret must be shared). – reed Jul 1 at 8:04

Ideally, you would have example.com provide a protocol to authenticate the users (such as OAuth2, as suggested above). Or simply a "registration password" that is available at some example.com intranet.

Lacking that ability, you would probably want some kind of blind signature. Ideally through a third party. Probably that could use a system similar to the old Mozilla Persona

Adding a trusted intermediary would solve the issue, although you are mostly replacing the platform being malicious with the intermediary being malicious and colliding with the (evil) platform.

An interesting solution would be to (ab)use DKIM signatures. We might assume that all our customers will sign outgoing mail (this will not be the case, but it ubiquitous enough to be a reasonable restriction). On registration, the website provides a token and requests to receive an email at finishregistration@website.com which is DKIM-signed by an example.com key with such token in the subject field.

On validation, it checks that the message indeed passes DKIM for a key by example.com, and then processes the token as usual with url links. For nerdy enough clients, you could allow them to upload the DKIM signed source email, so they can actually verify what they are sending.

The hard part here is that the From: field will contain the email address,¹ so you would need to instruct the users how send an email spoofing an empty sender, accept that people could send you the email with the from: field revealing their identity (maybe they won't care?) or provide a program which can do that on their behalf (so that in order not to give you their email address, they execute an untrusted binary of your choice, to which they provide their email credentials…). Plus, the server itself which shall sign them, may reject/"fixup" a spoofed/empty From:, or include the sender identity somewhere else inside the headers.

¹ and probably the full name, not to mention people that would not removing their email signature full of PII.

| improve this answer | |

You could use OAuth2 for this.

When the user wants to register, he enters his email, and the authorization service validates if they have an @example.com email. If so, it sends a link with a random token to the email with an expiration timestamp. The user clicks on the link, receives a random username (or creates one), and creates a password. No personal identification is used, and the email is not linked with the token at all: the address is used to send the token, and forgotten. The users table contains just the username and the properly salted and hashed password (no SHA1 nor MD5, please). If you want to allow people to sign their posts, you can store their public key, and the user keeps the private key safe on his computer.

Every time they want to post on the blog, they use OAuth2 protocol to login at the authorization server, get a token issued, and use the token to post at the blog. The blog service receives only an authorization token, no username, nothing.

At this point, even if the site turns malicious, there's no personal information saved anywhere, and the only information the blog receives is a random token with no identification whatsoever. If the user signs the post, there's no personal information either, unless the user signs something on another site that links his signature to his email.

But users need to trust the service anyway, because there's no way to be sure that the token is not based on the user email, that they won't store the token and the email somewhere, or the authorization server won't send an authorization token plus the email encoded somewhere.

Another downside (or upside) is that without saving the email, there's no way to prevent any user to create multiple accounts using the same email, as the server has no memory of which emails already have accounts. This can be seem as a bug or a feature.

| improve this answer | |
  • They could inspect the information requested to be turned by the OAuth2 provider (probably not too user friendly, unless the provider shows that as part of its UI). – Ángel Jul 8 at 22:45

I have a partial solution to show ownership of a post, but not to prove ownership of an email to the site.

Generate a random value R (or just use the post ID/hash or something), then sign it with secret key K. The encrypted key K(R) is then attached to the message alongside R.

Releasing the key K would then let users determine that the user is the one who made the post, because no one else should have the key K that decrypts the message K(R) to R. Of course, any future anonymous posts or ones that you don't want to out at the same time would need a different K.

This is basically what PGP signing uses.

The problem is that anyone could make a key/value pair, not just people at your domain, and the site cannot control this. You also cannot check that your key does not collide with anyone else's key (unless the site let you download all messages K(R), but that allows brute-force search of any/all of the keys), since the site would need to know the other keys and would know your key since it was sent in the query.

You also can't give the site any information or use any information given to you by the site, as that may allow the site to link your specific email with the post/account (even something like "add the digits in this number." Anything that can be used to prove that you received the email would by definition have to be unique or otherwise it could be faked/leaked and let anyone log in. Plus, you have no way to tell if it is actually anonymous or if the data would leak information to the site).

Never mind that you wouldn't want to give the site your email in the first place because it can and probably will be logged.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.