I have a properties file in java, in wich i store all information of my app, like logo image filename, database name,database user and database password.
I can store the password encrypted on the properties file.
But, the key or passphrase can be read out of the jar using a decompiler.
Is there a way to store the db pass in a properties file securely?
views:
534answers:
7No there is not. Even if you encrypt it, somebody will decompile the code that decrypts it.
There are multiple ways to manage this. If you can figure out a way to have a user provide a password for a keystore when the application starts up the most appropriate way would be to encrypt all the values using a key, and store this key in the keystore. The command line interface to the keystore is by using keytool. However JSE has APIs to programmatically access the keystore as well.
If you do not have an ability to have a user manually provide a password to the keystore on startup (say for a web application), one way to do it is to write an exceptionally complex obfuscation routine which can obfuscate the key and store it in a property file as well. Important things to remember is that the obfuscation and deobfuscation logic should be multi layered (could involve scrambling, encoding, introduction of spurious characters etc. etc.) and should itself have at least one key which could be hidden away in other classes in the application using non intuitive names. This is not a fully safe mechanism since someone with a decompiler and a fair amount of time and intelligence can still work around it but is the only one I know of which does not require you to break into native (ie. non easily decompilable) code.
You could make a separate properties file (outside the jar) for passwords (either direct DB password or or key passphrase) and not include that properties file with the distribution. Or you might be able to make the server only accept that login from a specific machine so that spoofing would be required.
You store a SHA1 hash of the password in your properties file. Then when you validate a users password, you hash their login attempt and make sure that the two hashes match.
This is the code that will hash some bytes for you. You can easily ger bytes from a String using the getBytes()
method.
/**
* Returns the hash value of the given chars
*
* Uses the default hash algorithm described above
*
* @param in
* the byte[] to hash
* @return a byte[] of hashed values
*/
public static byte[] getHashedBytes(byte[] in)
{
MessageDigest msg;
try
{
msg = MessageDigest.getInstance(hashingAlgorithmUsed);
}
catch (NoSuchAlgorithmException e)
{
throw new AssertionError("Someone chose to use a hashing algorithm that doesn't exist. Epic fail, go change it in the Util file. SHA(1) or MD5");
}
msg.update(in);
return msg.digest();
}
In addition to encrypting the passwords as described above put any passwords in separate properties file and on deployment try to give this file the most locked down permissions possible.
For example, if your Application Server runs on Linux/Unix as root
then make the password properties file owned by root
with 400/-r--------
permissions.
Couldn't you have the app contact a server over https and download the password, after authenticating in some way of course?