Reactive emails are a solution to the long-lived problem of spam emails. Spam emails take advantage of one critical flaw of most email addresses: they can't be easily changed.
Reactive emails provide a system for generating unguessable yet recoverable emails that can be changed at any time. The idea is to use a separate reactive email for each service, so that if an email for one service ever gets leaked, you can easily generate a new email address and only need to update it for that one service. In other words, your email addresses are "reactive": they can be easily changed whenever they get leaked.
Reactive emails are generated via the following algorithm:
[Purpose].[Email Version Number].[Reactive Hash]@[Domain]
Purpose: A word representing the purpose the email is used for. Most of the time, this would be the name of the service you're using the email to register for (e.g. Amazon
).
The purpose is case-sensitive because amazon
will result in a different hash than Amazon
. For consistency, it's recommended to capitalize the purpose the same way the company/service does when they refer to themselves (e.g. LinkedIn
and not Linkedin
, eBay
and not ebay
).
Because spaces are not permitted in emails, any spaces in the purpose name should be replaced with a dot (e.g. Best.Buy
and not Best Buy
).
Since special characters are not permitted in emails, they should be replaced with the closest alphanumeric counterpart (e.g. Barnes.And.Noble
instead of Barnes & Noble
)
Email Version Number: The version number of the email, which must be an integer greater than 0. The version number allows for easy regeneration of an email address in case it gets leaked.
Reactive Hash: Each email contains an unguessable hash based on the Purpose, the Email Version Number, and a Reactive Hash Secret. The reactive hash should never contain a dot.
The reactive hash is the core of what makes reactive emails work. The reactive hash is an unguessable 4-letter string that is deterministically generated from every reactive email.
To generate the reactive hash, the SHA256 hash function is used on the combination of the email's purpose, version number, and your reactive hash secret:
SHA256(Purpose + "." + Email Version Number + "." + Reactive Hash Secret)
In addition to this hash, we also need a character set which includes the full set of characters that our final reactive hash contains. The character set is important because it needs to ensure that we don't accidentally generate a reactive hash that contains words or letter combinations resembling words (especially offensive words).
A character set for English that I've found is the following set of 8 characters: bdhmnqvz
.
Once we know the length n of our reactive hash character set, we can then convert the bits generated by the SHA256 function into a base-n number and then take the last 5 digits of the number (or in other words, finding the result of our base-n number modulus n^n padded with 0s to the left such that our final number contains 5 characters). For example, with the 8-letters character set bdhmnqnz
, we would convert the output of our SHA256 function into base 8, and take the last 5 digits of the base 8 number and map it using the following table:
Character in Raw Reactive Hash | Character in Final Reactive Hash |
---|---|
0 | b |
1 | d |
2 | h |
3 | m |
4 | n |
5 | q |
6 | v |
7 | z |
So, if the last 5 digits of our base 8 number was 65247
, then our final reactive hash would be vqhnz
.
If we're generating a reactive email for a new account on Amazon, our purpose string would be amazon
, our version number would be 1
, and our reactive hash secret can be any secret (which should be the same for all reactive emails):
Purpose: Amazon
Version Number: 1
Reactive Hash Secret: mysecret
Using the character set bdhmnqvz
, our raw reactive hash would then look as follows:
Raw Reactive Hash = Last 5 digits of base8(SHA256(Amazon.1.mysecret))
Raw Reactive Hash = Last 5 digits of base8(f415bffef05ef762ab79d4e6a8f555d4a679c2498f7c56f15cac7107169dc904)
Raw Reactive Hash = 40574 (base 8)
Using the raw reactive hash character map, our final reactive hash would look like:
Raw Reactive Hash = 40574 (base 8)
Final Reactive Hash = nbqzn
And thus, if our email domain is example.com
, our reactive email address for Amazon would be:
Reactive Email Formula = [Purpose][Email Version Number][Reactive Hash]@[Domain]
Final Reactive Email = [email protected]
Now, let's say this email accidentally got leaked publicly and spammers are suddenly flooding this email tons of spam. Luckily, reactive emails allow you to easily refresh your email by simply bumping the version number and generating a new unguessable reactive hash:
New Raw Reactive Hash = Last 5 characters of base8(SHA256(Amazon.2.mysecret))
New Raw Reactive Hash = 10773 (base 8)
Final Reactive Hash = dbzzm
Thus, our new reactive email for Amazon would be [email protected]
.
So, why are we using such an involved algorithm to generate reactive emails? Can't we just generate a random unguessable string and have the same effect?
The reason why reactive emails are designed this way is to provide a last-resort in case you lose access to your list of reactive emails. Since reactive emails are not meant to be memorized but rather stored on an email manager, such as a password manager like Bitwarden, it's possible that you may end up losing access to your list of reactive emails (e.g. if you forget your Bitwarden password).
The problem is, many sites depend on your email address for identifying your account. If you lose access to your email, you will end up losing access to many of your accounts with no way to recover them. However, since reactive emails are generated deterministically, you can easily recover the email you used for a certain account as long as you remember the Purpose string you used (which should be the service's name) and your reactive hash secret.