I need to alter email addresses of users to render them undeliverable (not ever a real address), however it needs to be reversible so that the original is visible or at least retrievable (without storing it elsewhere).
For example john#example.com -> NONAME_john#exampleNOTHING.com might work as it can be changed back.
However, the problem is that I cannot KNOW that the above-resulting address is not a real email address. Maybe there is a real address out there called NONAME_john#exampleNOTHING.com.
The requirements are that the address needs to be valid (in terms of having '#' and '.com' etc) but won't send.
Maybe my requirements are a contradiction and hence not possible? Does anyone know?
Your requirements are kind of a contradiction. The only way to make an addres unworkable is to render it practically invalid.
Note that "invalid" can mean at least three things;
it doesn't parse as an e-mail address (e.g. replace # by ⓐ)
the user name is invalid at that domain
the domain name is invalid
The point is that for 2 and 3 there is no easy way to know for sure if that is the case.
What you also could do is obfuscate the e-mail addres by applying a reversable transformation, like e.g. base64 encoding it. This falls under category 1 above.
For example in Python 3:
In [1]: import base64
In [2]: base64.b64encode('john#example.com'.encode('utf-8'))
Out[2]: b'am9obkBleGFtcGxlLmNvbQ=='
In [3]: base64.b64decode(b'am9obkBleGFtcGxlLmNvbQ==').decode('utf-8')
Out[3]: 'john#example.com'
Related
I have an application that stores information about a person onto a database, but when I try to use the URL to GET a user based on their email address users with a + in their email cannot be found.
Example URL that returns person:
https://www.someURL.com/api/people/johnsmith#someemail.com
Example URL that does not return person (returns null):
https://www.someURL.com/api/people/jane+doe#someemail.com
Both emails are in the database as written in the URL so it does not appear to be a typo issue, and I am using postman to test the GET method. Why am I not able to find them, and how can I make it so that they can be found even with the + character?
Working postman request
NOT working postman request
When I search with id I am able to find the person so I know the person exists.
Verification that person exists
My suggestion would be: change your server implementaion from GET to POST and provide an email as a String parameter within the body of request. It'll prevent this and any similar issue with escaping special characters in URI.
If it's not possible, try to frame email address with a single ' or double " quotes, depending on how your web server treats incoming request it may help as well.
Nice to know that "+" is not really a 'valid' character for a lot of email providers for a reason. For instance, Gmail will not let you to create an email address with anything but [A-z0-9] (alphanumeric) and dot (.) characters. I'm pretty sure they were tired of validating input emails with complex regular expression and just limited it to basic ones.
'+' is a reserved character in URIs, so in order to prevent it being interpreted as a space character you would need to percent-encode it. In your example, replace '+' with '%2B'.
https://www.someURL.com/api/people/jane%2Bdoe#someemail.com
There are other characters that are allowed in email addresses but are reserved characters in URIs, so it would be best to percent-encode the whole email address, just in case.
snatching my hair to fix this problem but I can't.
I am parsing id in url to pull data on next page according to that id. So rather than parsing id=123 I encrypted it something like process.php?token=TG4n6iv_aoO7sU3AngFY4WLSppLvueEoh-MnYE6k7NA, and decrypted it on process.php page by collecting it with $_GET, before using it in sql query. This is not proper URL, I need url like process.php?token=9878799889 and I need to decrypt this 9878799889 on process.php which would give me my original user id.
So here I can not use md5 or base64_encode which give me ugly string.
What would be best thing to do here?
id is unique so generated long digits should be unique as well and not easy to guess.
Right now I am using encrypt logarithm with salt. Actually want to parse like www.sitename.com/process/token/9878799889..this can be achieve with .htaccess so not worried about it..
Any help will be much appreciated..
What you could do is add an association table in your databse, which would contains a UUID as primary key (a randomly generated number) and your true ID reference (and other information you may want to store there, like a "valid until" date or other things...)
You'd have to generate the entry in that table as you parse the UUID
let's say INSERT INTO uuid_table (uuid, real_id) VALUES (9878799889, 123);
now when you process the url process.php?token=9878799889
you would only have to SELECT real_id FROM uuid_table WHERE uuid=9878799889;
it would retern the read id 123
You should also DELETE FROM uuid_table WHERE uuid=9878799889 when you're done.
Note that it would also work with md5 or base_64, but indeed it makes the url uglier.
I consider to setup a server to deal with URLs including email address such as
http://mydomain.com/me#mail.com
According to RFC 3986, I userstand # is reserved on authority part = //mydomain.com/,
but unreserved on path part /.......,
so currently I assume it's ok to use email address on pass.
Having said that, I still not sure if it is safe to use like
http://mydomain.com/me#mail.com
on production.
Please advise. Thanks.
It's fine—your interpretation of the RFC is correct, and there's no "risk" (in terms of browsers doing the wrong thing) for using an # in the URI portion.
Facebook sends email notifications when a new message has arrived in a facebook message thread. The email allows you to reply on it without going to Facebook.
I think it is being done by Facebook by generating a reply to email address that is linked to the message thread.
Example of such a reply-to email adress of a facebook email notification (I modified some characters, so it won't work):
m+51r6w8e000000bu1jfpbziio6jmfnvvtkaevxrgojnel8qv#reply.facebook.com
I'm trying to implement a similar feature in my rails app.
I'm still a newbie in rails and wondering how I should approach this issue.
I was trying to encrypt the id of my message thread using the encryptor gem, then using this as an email adress in the form: encryptedId#mydomain.com. Issue is that the encrypted output contains characters that are not allowed in an email address.
As I know little about encryption I googled and found the possibility to base64 encode the encrypted output. This is common practice for urls. But still, this has characters (for example %) that are not allowed in an email adress.
I found that RC4 should be an encrytpion algorythm that has hexadecimal output. But the encryptor gem gives me 1 non-hexadecimal character when using this algorythm, so it doesn't seem to work. Conclusion: I'm a bit stuck.
Maybe I'm looking to far. Are there other appoaches that I could consider?
EDIT: extra info: I'm trying to make the email address non-guessable.
Thanks!
If you are trying to keep your response email addresses non-predictable, you can create your email address out of a concatenation of:
some unique aspect of the message thread such as a row ID
a similar unique attribute of the user being sent the email
a MD5 encoded hash of both of those items plus a unique string known only by your system
a random salt to the MD5
So if user 7812 posts in thread 8299 you could make your base string
u7812t8299
then take that string "u7812t8299" plus the time the email was sent (say 12:31), and a string known to your system like "purpleumbrella"
Your result string is "u7812t82991231purpleumbrella". Using:
Digest::MD5.hexdigest("u7812t82991231purpleumbrella")
we get an MD5 hash of:
5822aceca1f70afdb06f53b5c7e4df99
now send the user an e-mail with a return address of
u7812t8299-1231-5822aceca1f70afdb06f53b5c7e4df99#yoursite
When you get an e-mail back to that address, your system will know that it's for user 7812 posting in thread 8299, and because only your system knows the password required to create the MD5 sum for this combination that would result in an MD5 string starting with 5822aceca1, you can verify to a certain extent that this is not a randomly generated email by someone trying to spam your system.
As part of a web application I need an auth-code to pass as a URL parameter.
I am currently using (in Rails) :
Digest::SHA1.hexdigest((object_id + rand(255)).to_s)
Which provides long strings like :
http://myapp.com/objects/1?auth_code=833fe7bdc789dff996f5de46075dcb409b4bb4f0
However it is too long and I think I might be able to "compress" this chain using more legal characters in an URL like the whole uppercase and lowercase alphabet in addition to numbers.
Do you have a code snipplet which does just that ?
your_auth_code = Digest::SHA1.hexdigest((object_id + rand(255)).to_s)
your_shortened_code = your_auth_code.to_i(16).to_s(36)
Converts your auth_code from base 16 (hexadecimal) to base 36 which uses [0-9a-z]
Personally I'd just cut the code in two if you feel it's too long.
Courtesy of a coworker of mine:
CHARS = [*'a'..'z'] + [*'A'..'Z'] + [*0..9]
def create_token
self.token = (0..9).map { CHARS[rand(CHARS.size)] }*''
end
There's also one that uses a bunch ascii characters from range 32+, but it isn't suitable for your use case (urls) due to illegal characters, but you might want to use for password salts, etc. This one courtesy of James Buck:
Array.new(32) { 32 + rand(95) }.pack("C*")
With those two snippets you can probably customize it for your needs.
What gpaul is getting at is that hash functions are still hash functions even if they're truncated, there's just a higher chance of collision though with only 10 bits it's still quite a low rate of collision. If you look at bit.ly for instance their hashes are completely miniscule but as you noted they're using base-32 instead of base-16, it doesn't really matter that much.
What's important is for you to ask what's at risk if people collide, because even with full SHA1 there's still the chance (cryptographically impossible). If there's really not a huge danger I think you could go down to 5-10 characters.
But the question still remains of why it matters. In your emails presumably you're sending a link which people just click on correct? There may be a better option entirely if you can tell us why the url is too long.
That is correct : my app has Users which click a link on an email containing an auth code.
When the user clicks the link, he ends up on the webapp but he is not redirected. The auth code will stay in the URL bar.
Each one of my users has an auth code. What's at stake if collision occur is that two users cannot be distinguished between each other.
Thanks to your very valuable input I was able to figure out what to type in google to get info on that topic : "base 62".
So I found the base62 gem : http://github.com/jtzemp/base62
And now, my formula is :
Digest::SHA1.hexdigest((object_id + rand(255)).to_s).to_i(16).base62_encode.slice(0..10)
which gives me an auth_code like : Fw1eDr701PY
Its a good compromise. If my app conquers the world, I can still add a DB lookup to avoid duplicates but for now I will stick to it.