3

How would one go about converting a char[] password obtained using this method:

char[] password = passwordInputField.getPassword();

To an MD5 Hash? Normally I would use the method below, but getBytes is only compatible with Strings:

MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes());
String hashedPass = new BigInteger(1, md.digest()).toString(16);
SilverlightFox
  • 32,436
  • 11
  • 76
  • 145
  • Not sure what you're application is but MD5 is generally not used for security purposes any longer. – Neil Smithline May 31 '15 at 19:24
  • So what would you recommend using? – Hrach Ghapantsyan May 31 '15 at 19:33
  • 1
    Assuming that you're looking to do password storage and verification on login, [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) is today's [standard](http://www.javacodegeeks.com/2012/08/bcrypt-salt-its-bare-minimum.html). See [this question](https://security.stackexchange.com/questions/21184/safe-to-use-jbcrypt-and-recommend-it-to-my-organization) for Java implementations. – Neil Smithline May 31 '15 at 20:40

1 Answers1

1

NOTE: The MD5 Hashing Algorithm should never be used for password storage, as it's hashes are easily cracked. However, I will use it for simplicity.

The quick/easy/UNSECURE fix would be to convert the char array to a string. However, this is unsecure because strings are immutable and can't be cleared from memory.

String password = new String(passwordInputField.getPassword());

MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes());
String hashedPass = new BigInteger(1, md.digest()).toString(16);

A more secure solution: convert the char[] to a byte[] and clear the arrays from memory afterward.

private byte[] toBytes(char[] chars) {
    CharBuffer charBuffer = CharBuffer.wrap(chars);
    ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
    byte[] bytes = Arrays.copyOfRange(byteBuffer.array(),
            byteBuffer.position(), byteBuffer.limit());
    Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data
    Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
    return bytes;
}

char[] passChars = passwordInputField.getPassword();
byte[] passBytes = toBytes(passChars);

MessageDigest md = MessageDigest.getInstance("MD5");
md.update(passBytes);
String hashedPass = new BigInteger(1, md.digest()).toString(16);

Arrays.fill(passChars, '\u0000'); // clear sensitive data
Arrays.fill(passBytes, (byte) 0); // clear sensitive data

EDIT:

Updated answer with a more secure solution (credit to user2656928 for the idea).

char[] to byte[] method credit to andreyne

Community
  • 1
  • 1
Connor
  • 670
  • 3
  • 9
  • 29
  • 1
    Quick and easy, yes. But `getPassword()` returns `char[]` for [security considerations](http://stackoverflow.com/q/8881291/4125191). One should keep this in mind when handling passwords. – RealSkeptic May 31 '15 at 18:28
  • This would go against the security reason why swing returns the password as `char[]` instead of `String` - namely, that strings are immutable, so having created one there's no way to erase it from memory. With `char[]` you're able to overwrite the data once you're done with it (except that GC is permitted to move objects, and can't be counted on to erase the original if it does). If you care about security you really need to find or write a `char[]` to `byte[]` converter and scrub both arrays afterward. – Andy Lowry May 31 '15 at 18:30
  • 2
    @RealSkeptic you're not wrong, but if that MD5 hash is directly transmitted or stored for any kind of security purpose, then the overall system has a bigger problem than an allocated string lingering in memory for a while. – Barend May 31 '15 at 18:58
  • @Barend Yes, of course. And completely unsalted, at that. – RealSkeptic May 31 '15 at 19:06
  • Thanks @Connor, although it seems that you did make one mistake. Bytes is meant to be Byte: byte[] passBytes = toBytes(passChars); – Hrach Ghapantsyan May 31 '15 at 19:10
  • No problem! And thanks, I believe I fixed the mistake. – Connor May 31 '15 at 19:13
  • This is insecure for password storage. – Neil Smithline May 31 '15 at 20:41