Password encryption with passport.js - node.js

I'm building a single page app with express.js as backend. Currently I'm using passport.js local strategy for authentication, saving on db the encrypted password with bcrypt. During authentication, the password provided by the user is encrypted again and confronted with the one stored on db. However I'm currently sending the password to the server as clear text, and I'm understanding this is a really bad and unsecure practice. To do this correctly I'm understanding I have to:
create random bytes on the server and send them to the client
create random bytes on the client
concatenate the encrypted password and the the two set of bytes and encrypt all of them
send back to the server the encrypted object and the bytes generated on the client as clear text
reproduce the same encrypted object on the server and check for a valid authentication
I could do this again with bcrypt and some random generator on the client, but I have the strong feeling I should NOT implement this on my own. There's some integration with passport or some node library I'm not aware of?

You can use HTTPS (SSL) to encrypt the communication between server-client

Related

While using a socket to send and receive passwords, does it encrypt the data?

I'm trying to make a login and sign-up system (I am hashing and salting the password). When I send the password to the server I'm using socket.emit() to send and receive data. Does socket automatically encrypt and decrypt the data or should I make my own custom encryption and decryption algorithm using RSA?

Security of an authentication algorithm

I am making a little script in python, in which a client has to authenticates to the server. The idea is that an attacker cannot authenticate himself by listening to the network, without knowing the password.
Despite any good practices, I am trying to make my own secure authentication (it is only for personal use).
In my current algorithm, the client and the server share :
the password that authenticates the client
an encryption key
the encryption algorithm (AES with pycrypto)
It works as follows :
The server generates a token
The server encrypts the token
The encrypted token is sent to the client
The client decrypts the token
The client encrypts the set (password + token)
The encrypted set (password + token) is sent to the server
The server decrypts (password + token)
If the received information corresponds to the shared password and the token sent by the server, then the client is successfully authenticated.
In this algorithm, the client and the server share 2 secrets : the password and the encryption key.
I am wondering if it would be secure to do like this :
The server generates a token
The server sends the token to the client (in plain text)
The client encrypts the token, and returns it to the server
If the decrypted token is correct, the client is successfully authenticated.
In this case, the server and the client share only one secret (the encryption key). From my (small) knowledge of AES, I think that an attacker should not be able to guess the key with the token and the encrypted token, nor to guess the encrypted token without owning the key.
So my questions are: do you see any flaws in my algorithms? Is the second as secure as the first?
Thanks for your help
I am not a crypto expert (shout out to https://crypto.stackexchange.com), but AES is meant to assure confidentiality, and your method does not prevent non-repudiation. In other words, I can't read the contents of the token, but I can intercept your message and send the same one to the server to "authenticate" myself, right? (https://en.wikipedia.org/wiki/Replay_attack) Additionally, someone in the middle could modify your message and potentially cause problems, since again, AES assures confidentiality, but not integrity of the message. Aside from those core issues, there are subtle mistakes you can make when implementing this that can cause issues that are very difficult for you (and me) to detect, but possible for attackers to sniff out.
Perhaps when combined with an HMAC, you can overcome these weaknesses... but I would have to encourage you to not "roll your own" crypto scheme and perhaps all you need is HTTPS to secure the communication between the two devices (and a pre-shared token/key/password to prove identity). If you do decide to continue down this route, I would also encourage you to do significant research and having a security expert review your code/implementation before using in any sort of production environment. If this is just for fun/research, that's another story.

security - how to secure api key in HTTP GET request

I'm new to cryptography and I'm trying to prevent against man-in-the-middle-attack in a web service I'm developing. The way the web service work is that a user registers on the service using his email address and password and creates an application. Each application is given an application id and an application key. The application id is public (that's how the public communicates with that application) but the application key is private. The user credits his application by loading a pin (a 16 digit numeric string). Loading the pin is done via a HTTP Get request.
Now here is my question: how can the user do a HTTP GET request with his application id (the way the server identifies the application) and his application key (the way the server authenticates him) without compromising his application key?
Because our server has SSL (and I read that SSL protects against man-in-the-middle-attack), I was thinking about simply having users submit their application id and application key as parameters in the GET request, but after reading around, I decided this may not be secure. This is also because after doing the HTTP GET request to load the pin, the user may configure his account that we submit the server response via another HTTP GET request to a URL of his choice. And since we want to do an echo back of his application id and application key so he can authenticate that the request was really from us, I was worried his key might be compromised.
So I decided we should have the user do a md5 hash of his app id and app key to provide a hashed parameter and submit that instead of his app key in the GET request. Then on our server, since we already know the user's app id and app key, we can simply do an md5 hash of both and compare it with the hash parameter the user submitted. But then I also thought that may be insecure because if someone intercepts the hash parameter, the attacker can use that same hash parameter to submit several requests since the app id and app key is static. So in the long run, the hash parameter is no different from the app key.
Now I'm thinking, we should have the user do a md5 hash of his app id, his app key and the pin he wants to load to get the hash parameter. This way, since the pin is always different each time, even if an attacker intercepts a request, the authentication process would not be compromised for other requests because the attacker would not be able to reuse that hash with other requests.
For example, if a user has the following credentials:
1. app_id: 1234
2. app_key: bghuTHY678KIjs78
And a user wants to load the pin: 1234567890123456
He generates the hash by doing an md5 hash of "1234:bghuTHY678KIjs78:1234567890123456". That gives him 210a4c92d85473af9d5f48b4ee182ddd. Then he does a HTTP Get request to the address below:
https://example.com/process?app_id=1234&pin=123456789012&hash=210a4c92d85473af9d5f48b4ee182ddd
Is this method secure? Or should I simply just have the users submit their app id and app key in the HTTP GET request since we have SSL?
The user secret should never be sent over the network. Instead, ask the user to sign his requests using his secret. HMAC is the relevant algorithm.
By the way, MD5 is obsolete and insecure for all crypto needs.
Use Secure Remote Password (SRP6a) and register a password verifier and salt for the 16 digit pin. The pin you never send to the server (you can store it in browser local storage for convenience of the user). Then authenticate the client using SRP6a which results in a strong shared secret session key for each successful authentication. Then use HMAC SHA256 to sign API calls using the session key. See the thinbus-srp JavaScript library and its demos of using SRP6a to authenticate resulting in a session key. See the JWS "HS256" (HMAC with SHA-256, 256+ bit secret) algorithm and any library implementing that as an example of signing a web API with a shared secure key.
The SRP6a authentication protocol is a secure zero-knowledge password-proof where the server does not know the password. The server issues a random challenge to the client which generates a password-proof based on the challenge. The server uses the verifier the client provided for their password to check the password-proof. If the 16 digit pin uses uppercase letters like a standard software license key it is infeasible to run a dictionary attack on the verifier. Use the modern browser webcrypto secure random number generator to generate the pin at the browser. Even you won't be able to obtain the password.
The overhead of using SRP6a to authenticate is that you need the client to first fetch the server challenge. The benefit for your use case is that if the client provides a good password-proof based on the challenge the both the client and server share a secure session key. No-one intercepting the traffic can know the session key. With that shared secret you can sign and verify every API call and verify the signature at the server. No-one intercepting any part of any exchange between you and the client end-to-end from registration through to usage can gain any advantage.

Are cookies secure if they are never sent to a server

Is a cookie secure if it is only stored locally on the client's browser and never sent over the internet to a server?
Edit - Im making an encrypted file service, the way it works is that the user has two passwords, one for logging into his account and another for encrypting and decrypting their files. Upon logging in they are presented with a window that asks them for their decryption password. This password is stored in a cookie on the user's browser. A encrypted list of files is sent from the server and javascript uses the cookie to decrypt it(and encrypt uploaded files once in the browser and then php encrypts it on the server). Is this a secure way of doing things or is their a better way? P.S. I do use an SSL but I'm trying to add more security.
Yes, but how secure it is, it still depends on what information you stored in that cookie. For authentication, it's best to use session and server-side validation.

How can I secure online API for my app?

I'm creating an app for Windows Phone and Android. So right now Im building a webapi they both can use, but I want to secure it som non other then my applications can use it. How do I go about it? No one else then my apps is going to access these APIs.
I don't want to implement OAuth.
I've got two scenarios that I'm thinking of:
First (I store username and hashed password on the client):
basic-auth over https/ssl, thats it.
Second (I store accesstoken on the client):
basic-auth over https/ssl to receive a access token.
to get access token, user sends a request for requestoken a token that verifies that both the client and server knows the clientsecret.
for each call to the API the accesstoken has to be sent with to check access
The problem as I see the second approach is that the server sends accesstoken to the client, if anyone where to get this they would have the access of the user.
How is it done in the real world?
You could use a slight modification of First:
store username and password on client
basic-auth over https
Storing a password hash on the client, then sending the hash and comparing it with the hash in the database is equivalent to storing a plain text password in the database because the hash becomes the password. So, your apps should authenticate with a username and password like any human user would do.
But your concerns for the second approach apply too. If somebody intercepts the message, he has your credentials.
A more secure solution is HMAC authentication (now we're talking "real world").
a user has a secret key that is stored on server and client
each request gets canonicalized (transformed into a distinct string, which contains the request method, URI, parameters and timestamp)
the canonicalized request gets hashed with HMAC using the secret key, hash and user id are passed in the HTTP Authorization header
on the server, a hash is generated using the same algorithm (with timestamp from the HTTP Date header) and compared with the sent hash.
if the results are equal, the request is authenticated
An example is the Amazon S3 REST API - the linked documentation is also a good example how to implement it for your own API.

Resources