<!-- --><style type="text/css">@import url(https://www.blogger.com/static/v1/v-css/navbar/3334278262-classic.css); div.b-mobile {display:none;} </style> </head><body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d7256432\x26blogName\x3dThe+Frustrated+Programmer\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLACK\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttp://frustratedprogrammer.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://frustratedprogrammer.blogspot.com/\x26vt\x3d5012862196962223429', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>
| Wednesday, July 07, 2004

I was recently tasked with adding authentication to our application. We had a database filled with users and passwords, but the old middleware vendor we were using was reluctant to give us the algorithm used to encrypt the passwords. Well, they did tell us it was DES, but refused to give us the key, or the ascii encoding algorithm used to store the binary data as a string in the database.

This is really the heart of the problem with using DES for passwords. Once you decrypt one password, you have them all. This is why most other password encoding schemes involve a one-way encryption. With one-way encryption, the encrypted password in the database cannot be decrypted. Instead, the password is re-encrypted and compared to the encrypted version in the database. Java's JCE package provides MessageDigest. It was very easy to use:

public boolean passwordMatches( String passwordFromUser, String passwordFromDatabase ) {
MessageDigest digester = MessageDigest.getInstance("MD5");
String digestedPassword = convert( digester.digest( passwordFromUser.getBytes() ) );
return digestedPassword.equals( passwordFromDatabase );
}

[...]

// These two methods are copied from the jakarta-tomcat project's HexUtil

/**
* Convert a byte array into a printable format containing a
* String of hexadecimal digit characters (two per byte).
*
* @param bytes Byte array representation
*/
public static String convert(byte bytes[]) {

StringBuffer buf = new StringBuffer(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
buf.append(convertDigit(bytes[i] >> 4));
buf.append(convertDigit(bytes[i] & 0x0f));
}
return (buf.toString());
}

/**
* [Private] Convert the specified value (0 .. 15) to the corresponding
* hexadecimal digit.
*
* @param value Value to be converted
*/
private static char convertDigit(int value) {
value &= 0x0f;
if (value >= 10) {
return ((char) (value - 10 + 'a'));
} else {
return ((char) (value + '0'));
}
}


The next question is, how much more secure is this than just storing plain-text passwords in the database?

Arguements for not using plain-text passwords in the database:
-If someone cracks your database, they have direct access to all your passwords.
Well, I always figured if they cracked your database, its not much more work to find your source code, or find your binaries and decompile them. This give them access to your encryption algorithm, which gets them pretty close to cracking most of your passwords.
-If someone uses your database for reporting or something similar, they will have direct access to your passwords.
This can be solved with using decent access permissions in your database. Reporting users should just have read-only access to the tables they need to do reporting.

Do I think passwords should be plain-text in the database? No, not really. But I think there's something better out there. I'm sure someone smart has come up with a system of public/private key encryption for web applications. Why don't browsers help support something like this by already generating private keys for people?