From: Mark O'D. <mar...@fi...> - 2004-09-24 06:10:07
|
Hi Alex Alex Peshkov wrote: > Hi! > > During last two weeks I implemented crypt plugins facility for firebird > engine. Well done! And I like most of what you describe. Having now read the complete thread, there is a lot!, and since I'd previously given this issue quite some thought. Here is my outline of Alex's idea, plus a few extra bits. Hopefully it might help with the formalisation and acceptance of the design for fb2. The idea is to supplement the current password hash with something more modern, while retaining backward compatibility. The current system, roughly, and using my bad memory, has two cycles of DES to store/use a password. #define PASSWORD_SALT "9z" client: clienthash = DES(PASSWORD_SALT + password) ... sendToServer(username, clienthash) server: boolean isUserOK(user, password) { serverhash = DES(PASSWORD_SALT + clienthash) databaseValue = getHashForUserFromSecurityDB(username) if (serverHash == databaseValue) { return true; } return false; } The server side of this could be fairly easily updated to be: boolean isUserOK(username, password) { siteSalt = getSiteSalt() databaseValue = getHashForUserFromSecurityDB(username) // try md5 (or SHA-1 if you must :-) serverhash = MD5(sitesalt + username + clienthash) if (serverHash == databaseValue) { return true; } // try old DES serverhash = DES(PASSWORD_SALT + clienthash) if (serverHash == databaseValue) { return true; } return false; } // Get an array of random data that will be specific per site. // perhaps generated at install time. // The random prefix could either be stored in another table in // security.fdb. or in the firebird.conf file. // Either will do, there are plusses and minuses for both // It should also be longer than 1 byte, anyting over 4 should be // adequate, say 10 bytes? byte[] getSiteSalt() { data = getRandomFromSecurityDb() if (data == null) { buildAndStoreRandomInSecurityDB() data = getRandomFromSecurityDb() } return data; } Of course storing a password would also need to change to use md5. intermediatehash = DES(PASSWORD_SALT + password) newpassword = md5(getSiteSalt() + username + intermediatehash) For simplicity the new server hash method should be hardcoded and fixed as either MD5 or SHA-1. Choices confuse people and this is an intermediate solution. Eventually someone will implement security using PAM modules then any authentication, via SASL, unix-logon, NTLM, smartcard, kerberos, LDAP, even using MySQL or Postgresql, etc can all be plugged in. A slightly different approach to hashing user passwords that could also be used, but just as secure as the above is SSHA (most commonly used in LDAP). http://developer.netscape.com/docs/technote/ldap/pass_sha.html Thats it. It needs a bit of roadtesting, and a few more eyes, and Im sure a bit more polishing, but Alex's design means that: 1) old client can connect to new servers, 2) new clients still talk to old servers. 3) and even if really needed old security.fdb files could work with new servers. And I agree that most of Ivan's ideas are worth applying as well. http://www.volny.cz/iprenosil/interbase/ip_ib_isc4.htm I started thinking about this about two years ago, after all the PAM stuff looked like it would take a while to get done, but I have never had time to follow it up - but the idea looks good, and I think after a bit of tinkering it is worth including in fb2. Anyway, I've attached a standalone md5 implementation, if it helps, and Im guessing Jim has a SHA1. Cheers Mark PS: Later fb3? it might be useful to consider linking with openssl, since in additon to MD5/SHA-1 it also has RSA, SSL and easy use for random number generators, which are likely to be useful later. If needed I can provide openssl sample usages for both MD5/SHA1 code - it's a little different. But for inclusion in fb2.0, I'd say do it with a standalone MD5/SHA1 implentation. |