Need an expensive way to transform a password - cryptography

I'm working on a desktop app using NeutralinoJS (an Electron alternative).
The app has password authentication for users, but it won't have access to the internet, so the authentication must be done on the client-side.
The data used for authentication is stored in localStorage and therefore it can be accessed by anyone who has access to the client PC. So, I can not store passwords as is. I need to transform them using some computationally expensive webcrypto method/algorithm.
At first I was thinking to use digest
const hashToStore = crypto.subtle.digest(algorithm, data)
But the digest algorithms are fast and it would be easy to bruteforce the password.
Then I realized I need to generate a key and use encrypt method:
const key = crypto.subtle.generateKey(algorithm, extractable, keyUsages);
const result = crypto.subtle.encrypt(algorithm, key, data);
The problem here is that I need to store generated keys in localStorage as well as encrypted password. Here's the list of algorithms.
Which algorithm do I use? Any advice?

Related

Is using Laravel api_token authentication not like storing password in plain text?

I want to validate my RESTful API using token authentication. Two key options provided are https://github.com/tymondesigns/jwt-auth and Laravel's own inbuilt token authentication.
I'm unable to make jwt-auth work for me even if it looks the most promising, so I decide to check on Laravel's implementation.
It is pretty straightforward. Create an extra field api_token in users DB, generate a random string and store it against the users record IN PLAIN TEXT, then any request the user sends they should append the api_token, which you shall authenticate by checking its existence in the DB. Just that.
Isn't that like storing passwords in plain text because anyone who happens to have access to the DB is as good as authenticated? Isn't there an outright security risk there? Someone help me understand this one.
Also, how does one handle things like invalidating the token, giving the token an expiry period, and such?
for Similar Case I am not using any external plugin, while Laravel already ship a project called Lumen which is best suitable for Restfull web service,
I am storing the encrypted hash string as api_token in the user table,
and in my mobile application i let the users authenticate by username password first time and then i store the decrypted token in the mobile to maintain the user state for subsequent api calls, key point is i am storing the decrypted user token in the mobile and whenver i receive the token in server, i do comparison to match both of them using the same encryption function i have used before,...
in this case you have to come up with your own encryption algorithm since you need to use the same algorithm to decry-pt in the client,
or else an easy way is to copy the user password hash string in the api_token field and store the user password in the client side,
but you have to make sure the security of the client application,
if you consider native android, i will use sharedpreference in private mode which is secure....
if(Hash::check($password,$user->password)){
$response['success'] = 1;
$response['message'] = 'You have Connected to Server Successfully';
$response['api_token'] = $user->api_token;
}else{
$response['success'] = 0;
$response['message'] = 'Authentication Unsuccessful';
$response['api_token'] = '';
}

Storing API keys on server

I have a service where users each have an API key. I need to store the keys so that they can be used to validate API requests.
If I store the keys in plaintext in my database, I'm worried about the scenario of someone getting access to the db, grabbing all the plaintext api keys, then using them to impersonate others (there will likely be bigger problems if someone got access to the db, though).
This is similar to storing user passwords, where you just store the hash and validate using that - however most APIs let you view your API keys, which means they need to be stored in some recoverable way.
Is there a best practice for this?
The threat that someone gets the database and gets the keys means they can use the api keys to access the data in the database, which they already have, so no win there.
The threat that someone can access the database, get the passwords, means they can reuse those passwords on other web sites with the same user name because people tend to reuse their passwords.
Another reason having passwords in the clear or easily reversable is someone in your company could get a hold of the passwords, and start to do bad stuff acting as the user. Which IS a risk you might have if your API keys are in the clear.
Typically, HMAC is a solution for cryptographically computing a secure value from a single secret key, and some public value.
Have a look at HMAC. With HMAC, you can load a secret key into memory with the app (config file, read off of amazon KMS, typed in on app start, or however you want to get that secret key there).
In the database, store a token. Token = UUID() for example. The token should be unique to the user, the token could be versioned in case you need to regenerate, and the token could be random (like UUID). The token is not secret.
The API key is computed using the secret key (SK) and user token (UT) as follows:
API_SECRET = HMAC(SK, UT)
Then distribute that UT (More commonly called API_KEY) and API_SECRET to the user, and when the user tries to connect, you compute the API_SECRET:
Get user record from database (you're probably already asking the user to provide their username)
Compute the API_SECRET from the UT in the database:
API_SECRET_DB = HMAC(SK, UT)
Compare the computed API_SECRET_DB to the one provided in the request:
if (API_SECRET_DB == API_SECRET_FROM_REQUEST){
//login user
}
Bottom line, you only protect the Secret Key, and not every single credential.
I did an update to some library written in PHP which made it using an Impersonate Protection Algorithm (IPA). that lead to not saving the Token itself inside a database.
For more info check this https://github.com/vzool/api-hmac-guard
Hope it helps, Thanks

Worklight Online + Offline Authentication

I'm trying to achieve the following through Worklight.
My app has two sets of features. One set of features can be accessed only when the app is connected to the server and the user is authenticated. Another set of features can be accessed offline but they require data from an encrypted JSONStore.
I have a JSONStore on the client device which is initialized using a password. Therefore, the data in the store will be encrypted. Also, this JSONStore is synced to a database on the server through an adapter.
I have also setup another adapter which authenticates the user by using another set of credentials stored in a database. The user can be authenticated only when the app is online.
What I want to do is to unify these two approaches so that the user needn't enter two sets of credentials to access these two different sets of features. One possible solution that came to my mind is just to encrypt the JSONStore and perform the adapter authentication without the intervention of the user. But I don't think that it's secure.
Any advice or approach to solve this issue?
The following is just an idea, I'm not a security expert.
Requirements:
To use the offline features you must have been online and authenticated at least one time.
Your application must have an login view to input some credentials (e.g. username/email and password).
Steps:
First time the user inputs the correct credentials and successfully authenticates with the server: hash the credentials. For example: var myHash = md5(loginField.getUser() + loginField.getPassword()). You can find md5 JavaScript libraries on Github.
Use that hash to initialize the store. For example: WL.JSONStore.init(..., {password: myHash}).
Send the hash to the backend over HTTPS, you will need it if the user changes his/her credentials. No need to save the credentials or the hash on the device (loginField = null; myHash = null). Alternatively, you could just generate the hash on the server and store it, without having the client send it back, just make sure both client and server are using the same hashing algorithm.
When working offline, ask the user for his/her credentials, hash them and use it to access data inside the store.
If the user changes his/her credentials (e.g. via the web interface for your application), the hash will be different and store won't init. However, the user should've successfully authenticated with the server with the new/valid credentials. Ask the server for the old hash, init the store with the old hash, and change the password to init the store to the new hash based on the new/valid credentials. For example: WL.JSONStore.changePassword(oldHash, newHash).
Optional: You may want to consider using a salt. For example: var salt = Math.random(), myHash = md5(loginField.getUser() + loginField.getPassword() + salt).
You will need to store the salt somewhere so you can re-generate the hash once the user returns to the application. You should be able to init another unencrypted store to persist it. For example WL.JSONStore.init(..., {username: 'metadata'}).then(function(){/*add salt to store*/}). More information regarding using two stores here.

Use Authentication using 2 encrypted strings

so basically I am trying to log user in with a cookie and do not query DB to improve performance
here is a brief idea:
transmit everything via SSL
set a Global secret key A and secret key B
generate a random verification string on registration and password change
encrypt the verification string with A, store it in cookie
encrypt the verification string with B, store it in cookie
when user tries to login, I decrypt each string with A and B, compare if they match
I am wondering if it is a good idea
if it is:
how can I actually do the encryption in Java, using bouncycastle ASE-256, Digest or whatever?
how much does this encryption/decryption process affect the performance, when compared with authentication by storing a session variable in a super fast DB like Redis
if it is not:
what should I do..
You can simply encrypt a known value together with the authentication data, when you decrypt verify that the data is present in the authentication token (the cookie). No need to use two keys.
The speed difference with a database depends on the database configuration as well as the cryptography that is performed. I would rather opt for a proven scheme first and only invent your ownif performance leaves you no other choice.
Schemes as better verified on http://security.stackexchange.com.

Salted password hashes

I am trying to create a login system for a web application, but I am stuck on a couple of points. I am storing the password in my database using a sha2-512 hash with a 128 bit random salt.
However I currently have the password posted in plain text to my application using a html form, both when the account is created and when the user logs in. I know this is wrong.
Do I need to hash the password in the client? If so how do I take into account the salt which is currently generated and stored on the database?
NOTE: I am doing this to learn not to use in a production system
The best bet is generally just to use SSL. If you did need to hash on the client side, this is how I'd do it:
When you first store the password, hash the password with a stored salt as is commonly done.
When someone needs to login, send them the stored salt, along with a second, randomly generated salt.
The client will hash the plaintext password with the stored salt, then the random salt and send the hash to the server.
The server will hash the stored password with the random used in that request salt and compare.
This is secure because it ensures that the hash being transmitted is unique to the request (it uses a single-request random salt), so a login cannot be faked in the future simply by sending the hash again. It is not dangerous to send the client their stored salt, as it is assumed that password crackers will have access to the stored salt (if they get access to the db). Two hashes are required to prevent you from ever having to store the password as plaintext.
You should be using SSL to transmit the passwords encrypted so that a man-in-the-middle can't intercept the packets and read off what ever credential is being sent. Even if you pre-hash the password in the client, a man-in-the-middle can still just use that value to fake identity.
What really concerns me, though, is the use of SHA-512. A lot of people use cryptographic hashes for password storage, but popular opinion misses a very important point: These hashes were designed to be fast. That is, one of the requirements to become an SHA (or similar) hash is to be able to quickly hash large documents on embedded hardware.
This is the exact opposite of what you want for password storage, as it allows specialized routines on high performance GPUs to brute force passwords at a surprising and scary speed!
This is why some purpose built password storage hashes have been developed. The one I have been using is Bcrypt, which is slow enough to keep out brute force attacks, adjustable to couneract faster hardware in the future, and has the added bonus of handling the salting for you.
Hashing the password on the client would require the use of the salt on the client. This also exposes your algorithm for very easy hacking on the client side. The best thing to do is to perform this action over SSL (HTTPS) so that the entire transaction is encrypted and the authentication only happens on the server.
I.e.: Your user ID and password are transmitted encrypted from the client. The web server decrypts the data and passes it to your server-side authentication function where you look up the user and associated salt, perform password + salt + hash and compare it to the stored hash for a match. This means that the hash and then salt never need to be transmitted from the server at all.
You really need to be using SSL on any page where you are transmitting passwords. If you try to encrypt them on the client side it will be in javascript and very easily reverse-engineerable.