Encrypt Passwords Properly to Prevent Database Drains and Protect User Login Security

In daily development, passwords are generally just simply MD5'd, and some systems even store users' plaintext passwords directly. If a hacker drains the database and downloads the entire thing, they can log into any account and do dangerous, even irreparable, things. So encrypt passwords properly to protect user account security.

In daily development, passwords are generally just simply MD5’d, and some systems even store users’ plaintext passwords directly. If a hacker drains the database and downloads the entire thing, they can log into any account and do dangerous, even irreparable, things. So encrypt passwords properly to protect user account security.

The Idea of No Encryption or Simple Encryption

Suppose we store users’ passwords unencrypted or simply MD5’d in the database. A hacker finds an exploit to export the database, exports and downloads the entire user table — a database-drain incident. Although MD5 is irreversible, a rainbow table can quickly look up the plaintext password. Then this hacker can log into any user’s account, even an admin’s, and do further dangerous actions like transfers and tampering, and our losses grow further.

How to Stop Hackers from Getting Plaintext Passwords

First, any algorithm can be cracked — only the time required differs. We just need to make the cracking time as long as possible so the hacker gives up. Some students may know you can add salt when encrypting passwords: salting means adding a bit of “seasoning” — the salt — on top of the original plaintext password, actually adding a random string, making an ordinary, regular plaintext password completely random and irregular, reducing the chance of being found by a rainbow table. But as computer performance improves and cloud computing can apply and release compute at any time, after salting we also need iteration, e.g. MD5(MD5(“password”)), encrypting the result multiple times.

Quick Implementation

To make password salting and encryption iteration easier, I’ve included the password-encryption code in my own development kit. If you use a Java, Maven-built project, you can edit the pom.xml and add the following dependency:

<dependency>
    <groupId>net.renfei</groupId>
    <artifactId>sdk</artifactId>
    <version>0.0.2</version>
</dependency>

Usage example:

package net.renfei.sdk.test.utils;

import net.renfei.sdk.utils.PasswordUtils;
import org.junit.Assert;
import org.junit.Test;

public class PasswordUtilsTest {
    @Test
    public void testPassword() throws PasswordUtils.CannotPerformOperationException {
        String password = "MyPassword", correctHash;
        correctHash = PasswordUtils.createHash(password);
        Assert.assertTrue(PasswordUtils.verifyPassword(password, correctHash));
    }
}

After executing the PasswordUtils.createHash() method you get an encrypted ciphertext, roughly in this format: “sha1:64000:18:7CBjTHkH09rc2Ug2BgOhSP20n1E1bTxR:OyNxGcEUaR3WjEoCzBehSyKw”, separated by colons, meaning “encryption method : iteration count : hash length : salt : hash result”. This ciphertext is the encrypted one; store it in the database. When the user logs in, use PasswordUtils.verifyPassword() to verify the password. This way, even if the database leaks, the hacker can hardly reverse the plaintext password. It’s essentially an implementation of javax.crypto.spec.PBEKeySpec in the JDK.

Project source: https://github.com/NeilRen/renfei-java-sdk