Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Deleted NSA from Bibliography. SHA mention in text is broad enough not to need source, and URL just goes to home page, no specific article.

...

Always append a salt to the password being hashed. A salt is a unique (often sequential), or randomly generated, piece of data that is stored along with the hash value. The use of a salt helps prevent brute-force attacks against the hash value , provided the salt is long enough to generate sufficient entropy (shorter salt values cannot significantly slow down a brute-force attack). Each password should have its own salt associated with it. If a single salt were used for more than one password, two users would be able to see whether their passwords are the same.

The choice of hash function and salt length presents a trade-off between security and performance. Increases in the time required to compute hash values raise the effort required for effective brute-force attacks , but make the program slower when validating a password. Increasing the length of the salt makes brute-force attacks more difficult , but requires additional storage space.

Java's MessageDigest class provides implementations of various cryptographic hash functions. Avoid defective functions such as the Message-Digest Algorithm (MD5). Hash functions such as Secure Hash Algorithm (SHA)-1 and SHA-2 are maintained by the NSA National Security Agency and are currently considered safe.

...

This noncompliant code example encrypts and decrypts the password stored in credentials.pw.:

Code Block
bgColor#FFcccc
public final class Password {
  private void setPassword(byte[] pass) throws Exception {
    bytes[] encrypted = encrypt(pass); // arbitraryArbitrary encryption scheme
    clearArray(pass);    
    saveBytes(encrypted,"password.bin"); // encryptedEncrypted password to password.bin
  }

  private boolean checkPassword(byte[] pass) throws Exception {
    boolean arrays_equal;
    byte[] encrypted = loadBytes("password.bin"); // loadLoad the encrypted password
    byte[] decrypted = decrypt(encrypted);
    arrays_equal = Arrays.equal(decrypted, pass);
    clearArray(decrypted);
    clearArray(pass);
    return arrays_equal;
  }

  private clearArray(byte[] a) {
    for (int i = 0; i < a.length; i++) {
      a[i] = 0;
    }
  }
}

...

This noncompliant code example implements the SHA-1 hash function through the MessageDigest class to compare hash values instead of cleartext strings, but it uses a String to store the password.:

Code Block
bgColor#FFcccc
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public final class Password {
  private void setPassword(String pass) throws Exception {
    byte[] salt = generateSalt(12);
    MessageDigest sha_1 = MessageDigest.getInstance("SHA-1");
    byte[] hashVal = sha_1.digest((pass+salt).getBytes()); // encodeEncode the string and salt
    saveBytes(salt, "salt.bin");
    saveBytes(hashVal,"password.bin"); // saveSave the hash value to password.bin
  }

  private boolean checkPassword(String pass) throws Exception {
    byte[] salt = loadBytes("salt.bin");
    MessageDigest sha_1 = MessageDigest.getInstance("SHA-1");
    byte[] hashVal1 = sha_1.digest((pass+salt).getBytes()); // encodeEncode the string and salt
    byte[] hashVal2 = loadBytes("password.bin"); // loadLoad the hash value stored in password.bin
    return Arrays.equals(hashVal1, hashVal2);
  }

  private byte[] generateSalt(int n) {
    // Generate a random byte array of length n
  }
}

Even when an attacker knows that the program stores passwords using SHA-1 and a 12-byte salt, he or she will be unable to retrieve the unencrypted password from password.bin and salt.bin.

Although this approach fixes the decryption problem from the previous noncompliant code example, at runtime this code may inadvertently store the passwords as cleartext. Java string objects are immutable and can be copied and internally stored by the Java Virtual Machine (JVM). Consequently, Java lacks a mechanism to securely erase a password once it has been stored in a String. See MSC63-JG. Limit the lifetime of sensitive data for more information.

...

This compliant solution addresses the problems from the previous noncompliant code example by using a byte array to store the password.:

Code Block
bgColor#ccccff
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public final class Password {

  private void setPassword(byte[] pass) throws Exception {
    byte[] salt = generateSalt(12);
    byte[] input = appendArrays(pass, salt);
    MessageDigest sha_1 = MessageDigest.getInstance("SHA-1");
    byte[] hashVal = sha_1.digest(input); // encodeEncode the string and salt   
    clearArray(pass);   
    clearArray(input);
    saveBytes(salt, "salt.bin");   
    saveBytes(hashVal,"password.bin"); // saveSave the hash value to password.bin
  }

  private boolean checkPassword(byte[] pass) throws Exception {
    byte[] salt = loadBytes("salt.bin");
    byte[] input = appendArrays(pass, salt);
    MessageDigest sha_1 = MessageDigest.getInstance("SHA-1");
    byte[] hashVal1 = sha_1.digest(input); // encodeEncode the string and salt
    clearArray(pass);
    clearArray(input);
    byte[] hashVal2 = loadBytes("password.bin"); // loadLoad the hash value stored in password.bin
    return Arrays.equals(hashVal1, hashVal2);
  }

  private byte[] generateSalt(int n) {
    // Generate a random byte array of length n
  }

  private byte[] appendArrays(byte[] a, byte[] b) {
    // Return a new array of a appended to b
  }

  private clearArray(byte[] a) {
    for (int i = 0; i < a.length; i++) {
      a[i] = 0;
    }
  }
}

In both the setPassword() and checkPassword() methods, the cleartext representation of the password is erased immediately after it is converted into a hash value. Consequently, attackers must work much harder to retrieve the cleartext password after the erasure. Providing truly guaranteed erasure is extremely challenging, is likely to be platform-specific, and may even be impossible because of the involvement of copying garbage collectors, dynamic paging, and other platform features that operate below the level of the Java Languagelanguage. Note, however, that most other languages share these complications (with the exception of garbage collection).

...

Applications such as password managers may need to retrieve the original password in order to enter it into a third-party application. This is permitted , even though it violates the guidlineguideline. The password manager is accessed by a single user and always has the user's permission to store his or her passwords and to display those passwords on command. Consequently, the limit to safety and security is the user's competence rather than the program's operation.

Related Guidelines

ISO/IEC TR 24772:20102013

"Insufficiently Protected Credentials [XYM]"

MITRE CWE

CWE ID 256, " Plaintext Storage storage of a Password"password

Bibliography

 

[API 2011]Class MessageDigest[API 2011]
Class String

http://www.javapractices.com/topic/TopicAction.do?Id=216

Passwords never in clear text

OWASP discussion of hashing java with salt

Salt (cryptography)

Christof Paar, Jan Pelzl, "Hash Functions", Chapter 11 of "Understanding Cryptography, A Textbook for Students and Practitioners". (companion web site contains online cryptography course that covers hash functions), Springer, 2009.

Cryptographic hash function

http://nsa.gov/

 

[Hirondelle 2013]Passwords Never Clear in Text
[OWASP 2012]"Why Add Salt?"
[Paar 2009]Chapter 11, "Hash Functions"

 

...

Image Added  Image Added  Image AddedImage Removed Image Removed None