ERXCrypto thread safety, performance, and security
Allen Cronce <[email protected]>
| Newsgroups | gmane.comp.web.webobjects.wonder-disc,gmane.comp.web.webobjects.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi all, I've been investigating using ERXCrypto for database encryption and have some observations/issues. Apologies in advance to the general WO list members for the somewhat OT nature of this post. If you don't care about partial encryption of your database, then please ignore it. Thread Safety: The ERXCrypto implementation uses static Blowfish Cipher objects. But Cipher objects are not guaranteed to be thread safe. First off, none of the JCE providers use "synchronized" anywhere. Second, Cipher objects by definition contain internal states that can change on a per encryption operation basis. The ERXCrypto implementation does not serialize access to these cached Cipher objects. So if ERXCrypto's blowfishEncode and blowfishDecode methods work in a multithreaded environment, it's because the current security provider implementations of Blowfish for ECB mode don't have any internal state when called with a single doFinal call. Unless I'm missing something, this is potentially dangerous because it relies on implementation assumptions that are outside of ProjectWonder's control. I'd be interested in hearing from any developers who have used ERXCrypto regarding what, if anything, they did to insure thread safety. Obviously one solution would be to serialize access to the method calls. But serialization can be expensive. I haven't done any performance tests to see which is faster, creating a new Cipher object for each encryption operation, or serializing access to a shared Cipher object. Performance: I was curious as to how Blowfish stacks up performance wise nowadays. So I extended ERXCrypto to allow me to specify the cipher and key. I then wrote an application that looped performing encrypt/decrypt operations. I ran the app using jMechanic under Eclipse to obtain relative performance numbers. What I found was that using AES was about 41% faster than Blowfish for the encrypt/decrypt operations on my development machine running Java 1.4.2 and Sun's security provider (not Bouncy Castle). This was not a big surprise. Previous experience with compiled C security implementations have shown time and again that AES beats the snot out of older, less secure algorithms. Note that I only tested AES in ECB mode, in part because I suspect that ERXCrypto only works in ECB mode due to the threading issues raised above. If you're interested in switching from Blowfish to AES with ERXCrypto, there's pretty much no way to do it except to modify the code. Basically you have to specify a cipher instance of "AES/ECB/NoPadding" when creating the Cipher objects, a key algorithm of "AES" when instancing the SecretKey, and a block size of 16. It would be nice if in the future ERXCrypto allowed for the algorithms to be more flexibly specified, perhaps by properties. Note that using AES with ERXCrypto means that the data will be a little bigger than with Blowfish. This is because ERXCrypto pads the data with zeros to an even multiple of the block size, and AES has a block size of 16 instead of 8. ERXCrypto also doubles the string length by converting it to a hex string. So you have to carve out enough space in your database to hold the maximum string size rounded up to the nearest block size (16 for AES), then multiply that number by 2 for the hex string encoding. Security: ERXCrypto uses Blowfish in ECB mode. Even if we assume for the moment that Blowfish is secure (which is a matter of debate best left for cryptographers), the use of ECB mode can be problematic. The issue is that ECB mode repeats the same encryption on a per block size basis. So in the case of the ERXCrypto's Blowfish-based implementation, each block of 8 bytes will be encrypted with the same key. That in turn means that any patterns in the clear text on a per block basis would also be visible in the encrypted data. A better mode to use would be CBC, where each block encrypted affects the subsequent blocks. That way, any patterns are completely obscured, and a single bit change in the data affects the encryption of all the data downstream of the change. The problem with CBC mode is that it pretty much can't work with the current ERXCrypto implementation because it has to use internal state to chain from block to block. That would mean that ERXCrypto would have to be changed to reset the Cipher on a per encryption basis and synchronize access to the cached Cipher objects. Which is probably why they picked ECB in the first place, although I couldn't find any such rationalization in the comments or docs. Of course, if you're only encrypting small runs of data, like credit card numbers, and if you assume that your raw database is unlikely to fall into the hands of hackers who are experienced with cryptography, then ECB is probably OK. But if you're storing larger sized, highly sensitive encrypted data, or if you're as paranoid as I am, then you might want to consider alternatives. Best, -- Allen Cronce Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642