I want to create a change password page for user. I encrypt the password when I save the user in Database (mongodb).
User.virtual('password')
.set(function(password) {
this._password = password;
this.salt = this.makeSalt();
this.hashed_password = this.encryptPassword(password);
})
.get(function() { return this._password; });
User.method('authenticate', function(plainText) {
return this.encryptPassword(plainText) === this.hashed_password;
});
User.method('makeSalt', function() {
return Math.round((new Date().valueOf() * Math.random())) + '';
});
User.method('encryptPassword', function(password) {
return crypto.createHmac('sha1', this.salt).update(password).digest('hex');
});
I don't know how to decrypt it in order to get the original password back. any help will be appreciated.
The password is hashed, not encrypted, and you can't get the original back -- that's the whole point of hashing, it's a one-way function. You shouldn't ever need to get the original back, as you have no legitimate use for it. To validate a user, you hash the password that they give you in the same way as the stored one, then compare the hashes.
I think the best solution here would be to allow the user to answer some security questions and then be able to reset the password by clicking a link sent to the email in their profile. They might end up setting it to the same password, but that is not your concern. This allows you to not having to worry about unhashing the password.
Of course this is harder if you did not provide for this in the original sign-up form. But if your service isn't actually launched yet, this should be very easy to implement.
Related
I store the API-Keys as hashes in a database.
...
async function createToken(userId:number) {
...
const salt=await bcrypt.genSalt(15)
const hash=await bcrypt.hash(token, salt)
await db.store({userId,hash})
}
async function verifyToken(token:string){
const userId= //I don't know the UserID since only the token is sent as HTTP header
const hashes= db.get(userId)
for(const hash of hashes) {
if(await bcrypt.compare(token, hash)) {
return true
}
}
return false
}
How do I verify the token validity without knowing the userID?
The only option I see is to loop through all DB records, and try if the produced hash for that record matches. But this results potentially in thousands of hashes checked before I find the right one.
I may reduce this to only the tokens belonging to a specific UserID. However, this would require my users to also send there userID which I don't want them to do.
Seems like you are using bcrypt hashes as token to authenticate the users, but that's not the actual purpose of such hashes. If you need to use a token, why not use something like JWT. It can hold the user information, and can be verified without a single db call.
Let's imagine I have an MongoDB document that includes the following data:
{
"username": "test123",
"password": "$2b$10$M2Y3ELsgfvA4KHxdCJkezeHZ1kKgtOA2Jiq4kuwqcRJSovGBu9nLm"
}
The password is hashed using bcrypt. Using MongoDB's official Node driver, I can find the username with:
collection.findOne({ username: req.body.username });
But how can I find the username, then check the password value of the same document (the password related to the username), and finally return the password?
PS. I know the title is very confusing, if you can think of a better way to express it, please comment below.
It's bad practice to send encrypted passwords to the database. It has some security issues. I guess you want to get the user by its username, figure out if it's the right user that you fetched by comparing its password also (password hashes), then do something with that user - for example, return password or so, as you mentioned (I don't see why would you expose password back to anyone).
For encryption, I'm using bcryptjs package, but it's pretty similar. Its function compare() takes the raw password for the first argument, and takes hashed password from the database as the second argument. It hashes the raw password and compares it with the given hash. If hashes match, the password is valid. For a code, you would have something like:
const bcrypt = require('bcryptjs');
// ...
const user = await collection.findOne({ username: req.body.username });
if (!user) throw new Error('User doesn\'t exist');
// first argument "password" is a raw password to compare with the one in the document
const passwordValid = await bcrypt.compare(password, user.password);
if (!passwordValid) throw new Error('Invalid password');
// do whatever you want to do with validated user
// if you want password to return, raw "password" is the one that's in the database also (hash)
im trying to implement function for "user change password".
i want to do:
1.user choose new password.
2.user needs to enter his current password to varificate.
3.if the user currentPassword correct -> change the password.
the problem: i dont know how to get his current password to check if its correct
in my client side i save his hashPassword ("lfds7fdhas784n23489h42")
so i cant do something like:
if state.user.password===currentPassword because i dont have its state password
i need to somhow get his passwsord from the server and check it, or maybe i need to send the
currentPassword to the back end and check it there ,but i dont know how to implement it...
code:
the Form to update password (in shortcut for better understanding):
<TextInput
placeholder"NewPassword"
onChangeText={setNewPass}/>
<TextInput
placeholder"currentPassword"
onChangeText={setCurrentPass}/>
updateUserPssword(state.userId, token, param, value);
the Function for update the password:
const updateUserPssword = dispatch => async (userId, token, newPass, currentPass) => {
try {
const res = await indexApi.put(
`/user/${userId}`,
{
password: newPass,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
}
For summary, the flow of reset password operation is like:
Step 1: User fills in currentPassword, newPassword and confirmedNewPassword in your React App. What you can validate here is only the similatiry of newPassword and confirmNewPassword.
Step 2: When the newPassword and comfirmedNewPassword are similar you send a request to server with data like this : { current: currentPassword, new: newPassword }
Your main concern is how to do that with axios. Below is an example:
axios.post('/reset-password', {
current: currentPassword,
new: newPassword
})
.then(function (response) {
// success case handle here
})
.catch(function (error) {
// error case handle here
});
When your server gets this request, basically, the following steps should be done
Step 1: Use hash function to hash the currentPassword
Step 2: Compare with hashed password of this user in DB
Step 2.1: If the 2 hashed passwords match, hash the newPassword and save the hashed value to DB
Step 2.2: If the 2 hashed passwords do not match, response error to your React App. (something like: passwords do not match)
You should manipulate all your actions on passwords on the server-side. That's the right flow
User types new password (Don't hash)
User types same password for confirmation (you can compare only this on client-side, if fieldA.value == fieldB.value)
User types old password
You send new password and old password as plain, to the server without hash.
Server hashes your old password with the same SALT and compares if generated hash is equal to the hash is stored in the database. That's the KEY MOMENT, you don't need to decode a stored password and compare the plain.
P.S Every time hashing something with the same salt gives you the
same result.
// Pseudo code
decodeHash(passwordInDatabase) == oldPassword // incorrect + impossible
hash(oldPassword) == passwordInDatabase // correct
If it's equal, back-end hash your new password and update in the database.
Return success or error message from back-end.
I'm writing an application which needs to have personally identifiable information removed/absent at all times from the database. Given that someone may use their real name in their username, and that an email address may be present in their AspUserIdentity records, I have decided one solution might be to hash these values. In simple terms: when someone logs in with a username, I hash the username they entered and see if that hash exists in the database; if it does, then I log them in. This is easy to do and works just fine by modifying the Login and Register methods in the AccountController. But now I am left with no knowledge of the entered username...
I could just store the username in session, but that seems jankety. What I'd like to do is to update the cookie that gets sent down upon successful login to use the username they entered (and not the hashed value stored in the DB). That way User.Identity.GetUserName() returns the plain text username (and not the hashed username). To the client the process ought to be transparent (and to me as the programmer too).
The question is: how? What's the best place to do this? I'm still relatively green when it comes to the latest ASP.NET Identity stuff. I see in Startup.Auth there's a lot of juicy stuff related to cookies, but I don't see anywhere I can modify the cookie itself upon login and prior to it being sent down.
Is all of this deep within Owin itself?
Thanks in advance,
When user logs in and you compare the hash of username, you can add their real username as a claim to the identity. This is serialised into cookie and available with the user on every request, but not persisted in a DB:
public async Task SignIn(string userName, string password, bool rememberMe)
{
var hashedUsername = getMyHash(username)
var loggedInUser = await userManager.FindAsync(hashedUsername, password);
if (loggedInUser == null)
{
// failed to login
return FailedToLogin(); // whatever you do there
}
// Ok, from now on we have user who provided correct username and password.
// and because correct username/password was given, we reset count for incorrect logins. This is for user lockout
await userManager.ResetAccessFailedCountAsync(loggedInUser.Id);
if (!loggedInUser.EmailConfirmed)
{
return EmailIsNotConfirmed(); // email is not confirmed - display a message
}
if (await userManager.IsLockedOutAsync(loggedInUser.Id))
{
return UserLockedOut(); // user is locked out - display a message
}
var identity = await userManager.CreateIdentityAsync(loggedInUser);
identity.AddClaim(new Claim("OriginalUsername", originalUsername));
var authenticationManager = context.GetOwinContext().Authentication;
authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = rememberMe }, identity);
//TODO redirect to a home page
}
Then when you need to display an actual username, not a hash do this:
public static String GetOriginalUsername(this IPrincipal principal)
{
if (principal == null)
{
return String.Empty;
}
var claimsPrincipal = principal as ClaimsPrincipal;
if (claimsPrincipal == null)
{
return String.Empty;
}
var originalUsernameClaim = principal.Claims.SingleOrDefault(c => c.Type == "OriginalUsername");
if (originalUsernameClaim == null)
{
return String.Empty;
}
return originalUsernameClaim.Value;
}
And call this method on User.GetOriginalUsername() in *.cshtml files or in Controllers. Or HttpContext.Current.User.GetOriginalUsername() if you need it somewhere else.
I am trying to figure out how to salt and hash a password in nodejs using the crypto module. I am able to create the hashed password doing this:
UserSchema.pre('save', function(next) {
var user = this;
var salt = crypto.randomBytes(128).toString('base64');
crypto.pbkdf2(user.password, salt, 10000, 512, function(err, derivedKey) {
user.password = derivedKey;
next();
});
});
However I am confused about how to later validate the password.
UserSchema.methods.validPassword = function(password) {
// need to salt and hash this password I think to compare
// how to I get the salt?
}
In whatever persistence mechanism (database) you're using, you would store the resulting hash alongside the salt and number of iterations, both of which would be plaintext. If each password uses different salt (which you should do), you must also save that information.
You would then compare the new plain text password, hash that using the same salt (and iterations), then compare the byte sequence with the stored one.
To generate the password (pseudo)
function hashPassword(password) {
var salt = crypto.randomBytes(128).toString('base64');
var iterations = 10000;
var hash = pbkdf2(password, salt, iterations);
return {
salt: salt,
hash: hash,
iterations: iterations
};
}
To validate password (pseudo)
function isPasswordCorrect(savedHash, savedSalt, savedIterations, passwordAttempt) {
return savedHash == pbkdf2(passwordAttempt, savedSalt, savedIterations);
}
Based on the nodejs documentation (http://nodejs.org/api/crypto.html), it doesn't look like there is a specific method that will validate a password for you. To validate it manually, you will need to compute the hash of the currently provided password and compare it to the stored one for equality. Basically, you will do the same thing with the challenge password that you did with the original, but use the salt stored in the database instead of generating a new one, and then compare the two hashes.
If you aren't too committed to using the built in crypto library, I might recommend using bcrypt instead. The two are about equal on the security front, but I think bcrypt has a more user-friendly interface. An example of how to use it (taken directly from the bcrypt docs on the page linked above) would be this:
Create a hash:
var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync("B4c0/\/", salt);
// Store hash in your password DB.
To check a password:
// Load hash from your password DB.
bcrypt.compareSync("B4c0/\/", hash); // true
bcrypt.compareSync("not_bacon", hash); // false
Edit to add:
Another advantage of bcrypt is that the output of the genSalt function contains both the hash and the salt in one string. This means that you can store just the single item in your database, instead of two. There is also a method provided that will generate a salt at the same time that the hashing occurs, so you don't have to worry about managing the salt at all.
Edit to update:
In response to the comment from Peter Lyons: you're 100% correct. I had assumed that the bcrypt module that I had recommended was a javascript implementation, and therefor using it asynchronously wouldn't really speed things up on node's single threaded model. It turns out that this is not the case; the bcrypt module uses native c++ code for it's computations and will run faster asynchronously. Peter Lyons is right, you should use the asynchronous version of the method first and only pick the synchronous one when necessary. The asynchronous method might be as slow as the synchronous one, but the synchronous one will always be slow.
Either store password and salt in separate columns in your database, or (my preferred method), store your passwords in your database in a format that's compatible with RFC 2307 section 5.3. An example would be {X-PBKDF2}base64salt:base64digest. You could also store your iteration count in there, which allows you to increase the iteration count in the future for new accounts and accounts that update your passwords, without breaking logins for everyone else.
An example hash from my own PBKDF2 module for Perl looks like
{X-PBKDF2}HMACSHA1:AAAD6A:8ODUPA==:1HSdSVVwlWSZhbPGO7GIZ4iUbrk= which includes the specific hash algorithm used, as well as the number of iterations, the salt, and the resulting key.
This is a modified version of #Matthews answer, using TypeScript
import * as crypto from "crypto";
const PASSWORD_LENGTH = 256;
const SALT_LENGTH = 64;
const ITERATIONS = 10000;
const DIGEST = "sha256";
const BYTE_TO_STRING_ENCODING = "hex"; // this could be base64, for instance
/**
* The information about the password that is stored in the database
*/
interface PersistedPassword {
salt: string;
hash: string;
iterations: number;
}
/**
* Generates a PersistedPassword given the password provided by the user.
* This should be called when creating a user or redefining the password
*/
export function generateHashPassword(
password: string
): Promise<PersistedPassword> {
return new Promise<PersistedPassword>((accept, reject) => {
const salt = crypto
.randomBytes(SALT_LENGTH)
.toString(BYTE_TO_STRING_ENCODING);
crypto.pbkdf2(
password,
salt,
ITERATIONS,
PASSWORD_LENGTH,
DIGEST,
(error, hash) => {
if (error) {
return reject(error);
}
accept({
salt,
hash: hash.toString(BYTE_TO_STRING_ENCODING),
iterations: ITERATIONS,
});
}
);
});
}
/**
* Verifies the attempted password against the password information saved in
* the database. This should be called when
* the user tries to log in.
*/
export function verifyPassword(
persistedPassword: PersistedPassword,
passwordAttempt: string
): Promise<boolean> {
return new Promise<boolean>((accept, reject) => {
crypto.pbkdf2(
passwordAttempt,
persistedPassword.salt,
persistedPassword.iterations,
PASSWORD_LENGTH,
DIGEST,
(error, hash) => {
if (error) {
return reject(error);
}
accept(
persistedPassword.hash === hash.toString(BYTE_TO_STRING_ENCODING)
);
}
);
});
}
Faced with the same question I brought everything together into one module: https://www.npmjs.org/package/password-hash-and-salt
It uses pbkdf2 and stores hash, salt, algorithm, and iterations in a single field. Hope it helps.
There are two major steps involved in this scenario
1) Creating and Storing password
Here you will have to do the following.
Take the user password
Generate a string of random chars (salt)
Combine the salt with the user entered password
Hash the combined string.
Store the hash and the salt in the database.
2) Validating user password
This step would be required to authenticate the user.
The user will enter the username/email and the password.
Fetch the hash and the salt based on the username entered
Combine the salt with the user password
Hash the combination with the same hashing algorithm.
Compare the result.
This tutorial has a detailed explaination on how to do it with nodejs crypto. Exactly what you are looking for.
Salt Hash passwords using NodeJS crypto