Hi everyone -
Upon reviewing the entity engine encryption code it looks like the keys
for entity encryption are stored unencrypted in the database. Because
of this, I can't really see the purpose of doing any encryption at all,
other than providing a minor layer of abstraction for a potential
hacker. Obviously, if a hacker has gotten access to your database your
data is compromised, so securing your database is the most important.
However, it seems to me that the point of encrypting data in the
database (since it is decrypted the instant it hits the entity engine)
is to protect that data from unauthorized sources, even if they have
access to your database (like your DBA, who really shouldn't be able to
read encrypted data). I'm having a hard time seeing how the encryption
as it's implemented provides any security at all (say, of credit card
numbers) since if someone has gotten access to the encrypted data, they
can probably get access to the keys in the entity_key_store table (since
the data is only encrypted in the database, not in the application
layer). In other words, if they have a need for the key that means they
have encrypted data, and if the data they have is encrypted, it seems
likely that they have somehow gotten access to the the database.
Of course the framework can only do so much - the people implementing
ofbiz really have a responsibility to secure their installation, and
anyone can take a very secure application and make it not so by their
configuration or implementation of it. However, I think the system as
it is gives the *illusion* of security through encryption, which seems
even more dangerous than not providing encryption in the first place.
As I see it there are three options (I'm sure there are more) for
changing this in the code - 1) either move the key store to the
application layer, 2) re-encrypt the actual data so it would be
decrypted/encrypted once using the existing method and once using a new
key stored in the application layer (just double-encrypt everything), or
3) encrypt the keys in entity_key_store using a new key stored somewhere
in the application layer.
#1 has the "benefit" (perhaps from a cleanliness standpoint) of being
conceptually simple - you have data that is encrypted in the database
and you have a plaintext keys somewhere (now outside of the data layer)
to decrypt it. No double encrypting. #2 and #3 involve some sort of
double encryption; #2 just encrypts each piece of data twice using
different keys and #3 encrypts the encryption key itself. I have
implemented #3 for our own code because it meant we only had to
re-encrypt the handful of encryption keys in the database, rather than
re-encrypt all the encrypted data in the database. I didn't like #1
because I didn't want to think about where the best place to store the
keys are (and felt, apparently, that it was easier to figure out where
to stick a single encryption key).
So I changed the entity engine (when it needs to pull a key from the key
store) to decrypt that key first using a new plaintext key stored in the
entityengine.xml configuration file. It uses AES (Rijndael) 256-bit
encryption using a simple AesCrypt utility class I created that's
basically a clone of the DesCrypt utility class, and the plaintext key
is run through a hash so a you can't just use the value in
entityengine.xml. It's a really simple addition to the entity engine,
which was my goal, and an attacker can't compromise the encrypted data
by just gaining access to the database. I'd be happy to dot the I's and
cross the T's in what little code I've written and submit it as a patch.
Also, perhaps someone who has actual experience with cryptanalysis
(particularly with the 3DES and Rijndael algorithms) can answer this
question: is there any practically useful extra information for
brute-forcing a 3DES encryption when you have a Rijndael-encrypted
version of the key? That is, is it appreciably easier to crack some
3DES-encrypted data when you have a the key in encrypted form vs. when
you don't have any form of the key? I doubt it, but really don't know.
If it is easier, than the #3 method above is cryptographically inferior
to #2 and #1, although it might still be overall more secure than #1.
However, I'm open to the possibility that I haven't thought this through
completely enough and a) there is a better solution (likely) or b) I'm
just spinning my wheels here and the system as it is is actually secure
(although I know that it is not secure enough for our purposes, but I
admit that this might have to do with how we use our database).
Regards,
David Vediner
- Entity Key Store David Vediner
-