views:

2968

answers:

6

Hey Folks,

I have a program that reads server information from a configuration file and would like to encrypt the password in that configuration that can be read by my program and decrypted.

Requirments:

  • Encrypt plaintext password to be stored in the file
  • Decrypt the encrypted password read in from the file from my program

Any reccomendations on how i would go about doing this? I was thinking of writing my own algorithm but i feel it would be terribly insecure.

Thanks,
-Pete

+8  A: 

Yes, definitely don't write your own algorithm. Java has lots of cryptography APIs.

If the OS you are installing upon has a keystore, then you could use that to store your crypto keys that you will need to encrypt and decrypt the sensitive data in your configuration or other files.

JeeBee
+1 for using a KeyStore! It's nothing more than obfuscation if you're storing the key in the Jar file.
ninesided
If all that is needed is not to have the password stored in clear text, then keystores are overkill.
Thorbjørn Ravn Andersen
+6  A: 

check jasypt link text

+4  A: 

I think that the best approach is to ensure that your config file (containing your password) is only accessible to a specific user account. For example, you might have an application specific user appuser to which only trusted people have the password (and to which they su to).

That way, there's no annoying cryptography overhead and you still have a password which is secure.

EDIT: I am assuming that you are not exporting your application configuration outside of a trusted environment (which I'm not sure would make any sense, given the question)

oxbow_lakes
+1  A: 

See what is available in Jetty for storing password (or hashes) in configuration files, and consider if the OBF encoding might be useful for you. Then see in the source how it is done.

http://docs.codehaus.org/display/JETTY/Securing+Passwords

Thorbjørn Ravn Andersen
+9  A: 

A simple way of doing this is to use Password Based Encryption in Java. This allows you to encrypt and decrypt a text by using a password.

This basically means initialing a javax.crypto.Cipher with algorithm "PBEWithMD5AndDES" and getting a key from javax.crypto.SecretKeyFactory with the same algorithm.

Here is a code example:

import java.io.IOException;
import java.security.GeneralSecurityException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class ProtectedConfigFile {

    private static final char[] PASSWORD = "enfldsgbnlsngdlksdsgm".toCharArray();
    private static final byte[] SALT = {
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
    };

    public static void main(String[] args) throws Exception {
        String originalPassword = "secret";
        System.out.println("Original password: " + originalPassword);
        String encryptedPassword = encrypt(originalPassword);
        System.out.println("Encrypted password: " + encryptedPassword);
        String decryptedPassword = decrypt(encryptedPassword);
        System.out.println("Decrypted password: " + decryptedPassword);
    }

    private static String encrypt(String property) throws GeneralSecurityException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
        return base64Encode(pbeCipher.doFinal(property.getBytes()));
    }

    private static String base64Encode(byte[] bytes) {
        // NB: This class is internal, and you probably should use another impl
        return new BASE64Encoder().encode(bytes);
    }

    private static String decrypt(String property) throws GeneralSecurityException, IOException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
        return new String(pbeCipher.doFinal(base64Decode(property)));
    }

    private static byte[] base64Decode(String property) throws IOException {
        // NB: This class is internal, and you probably should use another impl
        return new BASE64Decoder().decodeBuffer(property);
    }

}

One problem remains: Where should you store the password that you use to encrypt the passwords? You can store it in the source file and obfuscate it, but it's not too hard to find it again. Alternatively, you can give it as a system property when you start the Java process (-DpropertyProtectionPassword=...).

The same issue remains if you use the KeyStore, which also is protected by a password. Basically, you will need to have one master password somewhere, and it's pretty hard to protect.

Johannes Brodwall
Thanks for the code example, it's pretty much how i ended up doing it. In regards to the password that protects the passwords i ran into that same problem, i went witht the obfuscate it method for now but havnt come up with an acceptable solution yet, thanks for your suggestions.
Petey B
+1  A: 

Hi! I have created a simple PropertyEncryptor in Java. It can encrypt your property files during the build. Then you can decrypt it using an EncryptionHelper in your programs. You can find the source codes in this location http://devpinoy.org/blogs/jakelite/archive/2009/07/14/encrypting-passwords-in-java-property-files.aspx

jake.stateresa