How to do encryption and decryption in query string value? - encryption

I want to use an two way algorithm(means i should both encrypt and decrypt). The below is my
Scenario:
I have a application where user can register by providing their First name, Last name and Email address. Once the data is stored in DB a mail will be sent to Registered User's Registered email address with the below content
Please click the link to configure your account:
http://mysitename.com?somepage.aspx?enc=EmailaddresinencyptedFormat
what i am doing is attaching registered user's registered email address in query string in encrypted format. user will click the following link and will be redirected to a configuration page where user enters his/her username,secretquestion. Then the input data and the encrypted emailaddress in the querystring will be passed to service and the service will decrypt them and validate the emailaddress.
Required:
What algorithm can be used to encrypt and decrpt? let me know BEST algorithm for this scenario.
Please help me out

Instead of encrypting the email address, place in the database a sufficiently large, 100% random value (such as a GUID or UUID), and associate it with a salted hash of the email address of the person who signed up. Send the GUID to the user in the link. Then, when they finish, you can saltedly hash the email they filled in on the second link and match it to the email address.
Since it is random there is no possibility of guessing random urls and stumbling across other people's registrations, and even if the database leaks only salted hashed emails are exposed, which cannot be decrypted into an email.
http://www.martinstoeckli.ch/php/php.html#bcrypt is a good resource on what hashing is and what it's for.

Related

Set password and verify email in one step

Lots of questions about email verification here on SO, but none seem to cover my scenario.
We would like to add users ourselves after an intake meeting. Our representative has a form to enter some details like company name, VAT number, contact data (which contains an email field), ... This data is saved in Firestore.
After this, an email is sent to the supplied email address which contains a link that takes the user to a form where his/her email address is displayed with a password and a password confirmation input field. When submitting this field, the user is created.
But now the user receives an email asking to confirm their email address. I assume, for security and privacy reasons, there's no way I can set the user's email address as verified.
I've looked at customizing the verification email, but that doesn't seem to solve my problem.
Creating the user with a random password after the intake meeting also doesn't seem to be a solution, as the user still has to verify and then reset the password in 2 steps. Or can I somehow redirect after the email verification to the 'set password' page? That would be an acceptable solution.
Is there any way to achieve the desired flow described above?
As a general workflow, you could achieve this using a Cloud Function along with either database system. You can also make use of App Check to further secure this process.
Representative adds base user information in their portal. Store the data securely in the database of your choice.
Send the user an invite email containing a short-lived verification token linked with the email added by the representative (this could be generated and fired off using an onCreate Cloud Function once the invitee's data is added to the database). This token should follow some standard like JWT so you can deserialize the contained email address or be exchangeable for the underlying email address.
When user clicks/copies the link to their browser, present them with an input form asking for the desired email and password. Note: the email field should be editable! The rep may have used an email the new user doesn't want to use with your platform.
If the token is still valid and not consumed, continue with the next steps.
If the token has expired and not consumed, send another email to reconfirm their email and restart this step.
If the token is already consumed, show an error and don't continue.
Submit the email, password and emailed token to your backend via a Callable Cloud Function.
Sign the user in using the authentication token returned by the function on success. Show an error otherwise.
In the callable function for creating the user:
Confirm the request comes from your app (if using App Check)
Confirm the validity of the emailed token
Pull the data the representative entered from the database linked with the emailed token's original email address.
Using that data, the updated email, the new password, and emailVerified=true, call the createUser API.
Using the User ID from the returned UserRecord, create the user's profile data in the database and also create a Custom Authentication Token.
Once their data has been created and the token generated, return the authentication token as the result of the request.

En/decrypt data using password without database admin being able to decrypt it

This is a more conceptual question, but I'm trying to have some content be made available only to a specific user at a time. To do so, I thought about using a users password as an encryption key. However, the problem with that is that if I encrypt it using the plaintext password, I won't be able to encrypt anything as I'm obviously storing a hashed version in my database. If I encrypt it using the hashed password, then any database admin will be able to read the content of every user.
So basically, I need some kind of public/private key concept where I can encrypt it with a users public key but only they have access to their private key to decrypt it. Using actual RSA keys will be annoying in terms of usability though, as a user would have to write down their private key somewhere.
Is there a clever way for me to store data in a way that only a specific user can see it, somehow accessible through a password they set without being able to see their data as a server admin?
Example, assuming a website:
Random person chooses a receiver person, writes a message. That message should be stored in encrypted form in the database, using some form of public key.
Receiver person enters their password (Not a huge RSA key, optimally, but a standard passphrase), on the server side this password will be treated as some form of private key in order to deencrypt the data and send it back to the client.
So basically, I want to treat a simple passphrase as a private key, and generate a corresponding public key for it.
It looks like you want to use the same password for both authentication and for encryption.
Lets assume that only hashes of passwords are stored in a database (as it should be).
Issues:
"Remember me" function of web/mobile/desktop app will render encryption function impossible because user can log-in without password via token.
Admin can intercept login request to know user's password while it is transmitted in plain-text over https (simple infrastructure reconfiguration allows admin to sniff on traffic).
There is a way to secure transfers by using the same password in case:
you change your authentication procedure in a way that user sends to the server hashes only instead of plain-text password
and will save plain-text password at client side (for "remember me" scenario)
Then you could generate key pair during registration and save encrypted private key at server.
This way you will have access to your private key even after client side reinstallation (web/mobile/desktop).
So upon login you request your private key from server and use password which was used for authentication to decrypt your private key.
If you trust that admin(or whoever else) will not be able to meddle with software (especially in key exchange phase) then you have a way to implement the feature you need.
This will be hacker-proof solution until someone patches your code and every user in system gets wrong public keys of other users.

Plain text password vs autologin

A customer of ours complained about login password recovery using plain text password. The only workaround I know is auto-login with encripted username and passord in the query string.
What other options exist to increase the password recovery security?
Thanks.
You can send them a URL that lets them reset the password themselves.
You could create a database table that stores, at the very minimum, a user id and a hash value.
Send the user a link that includes the hash, and on the receiving page look up the associated information and allow the user to reset the password to the account. Which I'm hoping you store in the database as a hash value. Plain text passwords should never be stored or sent out.
Just be sure that the link either expires or is deactivated once the password is changed. Otherwise someone could visit that link whenever they want and change the password.
Along the same lines as Brandon's excellent answer, here is what we do:
Do not store passwords in plain text, or even a decryptable value. Always store passwords using a 1-way hashing algorithm. This means only the user can ever know what the plain-text password is.
When a user forgets their password, present them with a form where they enter their email address, and click submit.
When they submit their email address, create a table row with 2 major pieces: The first is a password reset token (we use a Guid for this). The token should be timestamped, so that you know when it was created, and when it expires (ours expire within 2 hours of submission). The second piece is a secret code that the user will have to enter in order to reset their password.
Send an email to the user, with a link to a page that will accept the token and secret code. When they click the link (or visit the page and enter the code manually), you can then present them with a page that lets them change their password without knowing its previous value.
Using a time-constrained token is a good idea, because if the user's email account is later compromised, the criminals can't use the email to reset the password -- assuming of course that the email account is not compromised within 2 hours of the password reset request.
I wouldn't send out the actual password of the account in plain text to the user's email address. The reason for this is because if someone hacked the users email address now they have their actual password. Most likely this password will be used for other systems as well.
The alternative is to send an encrypted querystring that links to that user and allow them to change their password based on some sort of security question or demographics you have specific to that user.
Facebook uses a matching of friends images to names. If you have their DOB and address you could use that (not that secure). Or you could set up specific security question and answers which would be better.

About Email Verification - What methods

I just wanted to ask the procedure of email verification, whats the best method. So far i have a class that stores the information from the register.aspx form, then i send out an email to the user, but what should i send him, should i send the user a guid?.
Also my membership class that stores the register data is stored in a session, is this a good idea, becuase if the user session times out then the membership class will be nothing and the user will be prompted to register again in a Session Timeout webpage, is this a good method?
But what if i send the user a guid and then store the user data to the database with the guid and then check the email guid with the corresponding user guid in the database, what should i do?
Also i have a Regular expression that checks that the email is valid, its not that good yet and i havent tested it properly, is there free email verification api's out there?
I am using ASP.NET VB.
Here is what I would do:
1) Ask for user's email
2) Validate the email using Regex
3) If valid, create a Timestamp (DateTime.Now), append with user's Id and any other useful information that I need. We can use some appropriate delimiters.
4) Encrypt the data and build a URL with the encrypted token and email to user
5) When user clicks, decrypt the information, check the timestamp (perhaps there is a timeout required) and use user's Id to get its data from database.
This is in addition to the already accepted answer - I wouldn't limit the email validation to checking the Regex syntax only.
There's a free email verification API I've been using that checks a number of factors, including syntax, typos, SMTP & MX-Records (which verifies the actual existence of the email address), if its a free or disposable email, etc.
They're offering a thousand monthly requests for free - mailboxlayer.com
Save the data to the database, including the GUID. Set the status of the record to "inactive". Send the email, with a link back that includes the GUID. When the link is clicked, set the registration record to "active". Only "active" records can log in.
You can't effectively validate an email address with a regexp - search this site for explanations of why.
In .Net you should validate email addresses like this. See this question for details.
MailAddress address = new MailAddress(input)
This throws an exception if the email address is invalid.

Securing temporary passwords sent through e-mail to users?

I have a simple web application set up where admins can create users. Users do not create themselves. All an admin has to do is enter a username and an e-mail and a temporary password is sent to the user for them to login. This e-mail is sent in plain text format. If the user is logging on for the first time, they are required to change their password and enter a security question and answer. The user obviously has to know their temporary password in order to login for the first time and this is the only way I know of letting them know (through e-mail). The other option would be to have the admin call the user and tell them over the phone or in person their temporary password, but this is not practical. How could I handle a situation like this?
I typically use a temporary url based on an invite record on the back end. Essentially you create an invite record and generate a hash based on some information perhaps the users email address, a timestamp and a random value. Store the hash as part of the invite record and then send them a url with the hash as the parameter.
When they click the link lookup the invite and validate that it exists and has not been used - then allow them to setup their password and invalidate the invite.
It gets rid of the need to send any sort of password and you can set an expiry on your invite records if you want as well.
The scenario you describe is very common- emailing a temporary password and requiring it to be changed on first login. Unless you have a specific problem with this model I see no reason not to use it. Having an admin call users can get complicated- I would avoid this at all costs.
You can generate a custom url with a password and user hash as argument where the user has to log itself. The hash will be difficult to retrieve if the attacker does not have the information

Resources