DEV Community

Cover image for How to Securely Store a Password in Java

How to Securely Store a Password in Java

Andrew (he/him) on December 06, 2018

A previous version of this article confused the process of "hashing" with the process of "encryption". It's worth noting that, while similar, hashi...
Collapse
 
madhadron profile image
Fred Ross

A couple comments:

  1. Aside from making sure you're not retaining references to it forever, worrying about trying to overwrite the the String containing the user's password is basically futile. There are likely lots of copies made of that string along the way. If someone has access to your program's memory, it's not protected anyway.

  2. At this point in time, please use argon2 or scrypt as your password hashing algorithm. They force much larger use of memory which makes brute force attack schemes less feasible on GPUs and more expensive on ASICs and FPGUs.

  3. Using a more expensive password hashing scheme should never be a vector for a DoS attack. The correct solution is to implement exponential backoff on repeated failed login attempts: the first failure lets you try again in 100ms, the second failure in 200ms, the third in 400ms, etc. The exception is in environments that specify otherwise, such as health care in the USA, where HIPAA specifies three tries then lockout.

Collapse
 
awwsmm profile image
Andrew (he/him)

Fair points. Thanks for taking the time to read and comment. These are definitely things I'll have to change if I implement this commercially. (This example was for a term project for a class I took.)

Collapse
 
terracraft profile image
Terracraft

I heard that there's ASIC rigs for mining scrypt

Collapse
 
edsaavedra84 profile image
Eduardo Saavedra

Cool material, very useful!
BTW, thanks for the *Rush * references :)

Collapse
 
pojntfx profile image
Felicitas Pojtinger
// Java
import java.security.SecureRandom;

private static final SecureRandom RAND = new SecureRandom();

System.out.println(RAND)
Enter fullscreen mode Exit fullscreen mode

Just in case someone ever asks me why I refuse to use Java ;)

// JavaScript/TypeScript
import { hash } from 'bcrypt'

const random: string = hash('seed', 10)

console.log(random)
Enter fullscreen mode Exit fullscreen mode

Very nice article though!

Collapse
 
billoneil profile image
Bill O'Neil

You can use BCrypt in Java as well Hashing passwords in Java with BCrypt.

public String hash(String password) {
    return BCrypt.hashpw(password, BCrypt.gensalt(logRounds));
}

public boolean verifyHash(String password, String hash) {
    return BCrypt.checkpw(password, hash);
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
caseywebb profile image
Casey Webb

While this is a well written guide, it should be pointed out that hashing != encryption. Hashing is 1-way, encryption is 2-way. In other words, you can't decrypt a hash, you can only check that rehashing the same value gives the same results.

Collapse
 
awwsmm profile image
Andrew (he/him)

Thanks for the heads-up! I'm working on an amended version of the article that discusses this issue. I'll post it tonight or tomorrow.

Collapse
 
awwsmm profile image
Andrew (he/him)

Updated. Let me know what you think!

Collapse
 
caseywebb profile image
Casey Webb

Looking good!

Collapse
 
theodesp profile image
Theofanis Despoudis

I've seen the same implementation in PHP done in 3 lines

Collapse
 
shalvah profile image
Shalvah

Yes, most of us agree that dynamically typed languages are easier/faster to code in and generally involve less lines of code But your comment isn't very encouraging, and doesn't add value to this post. Maybe I'm misreading, but it sounds fairly hostile. Do reconsider next time.

Collapse
 
awwsmm profile image
Andrew (he/him)

If anyone's interested, here are different implementations of this general procedure in languages like PHP, Ruby, JavaScript, and so on. The PHP implementation is indeed just 3 lines:

password_hash($password, PASSWORD_BCRYPT);
$salt = '$2y$10$' . mcrypt_create_iv(22);
$salted_password = crypt($password, $salt);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
theodesp profile image
Theofanis Despoudis • Edited

Yes, I remember because I had to port a similar algorithm in Java and it was like 200 lines of code vs this one!

Collapse
 
awwsmm profile image
Andrew (he/him)

Could you post it?

Collapse
 
vdelitz profile image
vdelitz

Loved reading through some of your articles and have to admit, you have a great style when explaining things. As you have demonstrated to have great coding skills: have you ever worked on WebAuthn / passkeys? How was the developer experience in your opinion?

Collapse
 
rafasmxp profile image
rafuru

It's a great idea to toss the password string to the garbage collector ASAP, I've saw a lot of implementation which doesn't consider this fact.

Collapse
 
awwsmm profile image
Andrew (he/him)

Yeah, unfortunately, there's no way to force garbage collection in Java. You can only suggest it by calling System.gc().

Collapse
 
ondrejs profile image
Ondrej

Correct. Good article btw, I would probably use the Kotlin/Java implementation of NaCl library but in this case the ones you used are strong enough.

Collapse
 
aavulamanudeep profile image
AavulaManudeep • Edited

I am try to check the Hashpasword with .equals() method but it is showing stored password and user entered password as false even though both are same please suggest me a code fix. HashedPassword is saving is working fine while registering.

//Java
public boolean userAuthentication(Userdetails userdetails)
{
Optional salt = passwordUtils.generateSalt(CableTVConstants.SALT_LENGTH);
Optional userinfo = userDetailService.findById(userdetails.getUsername());
if(userinfo.isPresent())
{
return passwordUtils.verifypassword(userdetails.getPassword(),userinfo.get().getPassword(),salt.get());
}
logger.log(Level.ALL,"Invalid user credentials");
return false;
}
public boolean verifypassword(String password, String key, String salt)
{
Optional password_check = generateHashPassword(password,salt);
if(!password_check.isPresent())
{
return false;
}
return password_check.get().equals(key);
}

Collapse
 
kirankamath96 profile image
Kiran Kamath

I have a requirement of taking a password from the user and then when he needs to see, then I must decrypt it and show on screen, is this method can be used for decryption.