views:

198

answers:

4

I am looking for a way to encrypt a password in a configuration file that is being read by a Java program. Currently, I read-in the password from the text file, but that leaves the password sitting right out in the open if someone were to look at the config file.

I was thinking of building a simple class where user could type in their desired password, get an encrypted version of the password, then paste the encrypted version into the configuration text file. Then the application would read encrypted password, decrypt the password back into a string, and move on.

I am having trouble with the string-->encrytped bytes-->string conversions.

I am using the built-in java security classes to implement this code. Here is some sample test code:

    // Reads password from config file
String password = ScriptConfig.getString( "password" );

// Generate Key
KeyGenerator kg = KeyGenerator.getInstance("DES");
Key key = kg.generateKey();

// Create Encryption cipher
Cipher cipher = Cipher.getInstance( "DES" );
cipher.init( Cipher.ENCRYPT_MODE, key );

// Encrypt password
byte[] encrypted = cipher.doFinal( password.getBytes() );

// Create decryption cipher
cipher.init( Cipher.DECRYPT_MODE, key );
byte[] decrypted = cipher.doFinal( encrypted );

// Convert byte[] to String
String decryptedString = new String(decrypted);

System.out.println("password: " + password);
System.out.println("encrypted: " + encrypted);
System.out.println("decrypted: " + decryptedString);

// Read encrypted string from config file
String encryptedPassword = ScriptConfig.getString( "encryptedPassword"
);

// Convert encryptedPassword string into byte[]
byte[] encryptedPasswordBytes = new byte[1024];
encryptedPasswordBytes = encryptedPassword.getBytes();

// Decrypt encrypted password from config file
byte[] decryptedPassword = cipher.doFinal( encryptedPasswordBytes );//error here

System.out.println("encryptedPassword: " + encryptedPassword);
System.out.println("decryptedPassword: " + decryptedPassword);


The config file has the following variables:
password=password
encryptedPassword=[B@2a4983


When I run the code, I get the following output:
password: passwd
encrypted: [B@2a4983
decrypted: passwd
javax.crypto.IllegalBlockSizeException: Input length must be multiple
of 8 when decrypting with padded cipher
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.DESCipher.engineDoFinal(Da shoA12275)
at javax.crypto.Cipher.doFinal(DashoA12275)
at com.sapient.fbi.uid.TestEncryption.main(TestEncryp tion.java:4

Any help on the error, structure, or process I am using to do this would be great. Thanks.

+2  A: 

I am having trouble with the string-->encrytped bytes-->string conversions.

I'd stuff the byte array through a base64 en/decoder, this way you'll have to persist strings that contain nothing but chars within (a subset of) ASCII, which should limit your trouble. Have a look e.g. at commons codecs and replace your new String(decrypted) with a call to one of the static methods in the org.apache.commons.codec.binary.Base64 class.

Besides that I think what you ultimately want to do is not strictly to "encrypt" the password but rather to store only a hash of the password, which was already discussed on SO.

Waldheinz
+1  A: 

A really simple solution would be to use Base64 encoding, see example below:

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

private String encode(String str) {
    BASE64Encoder encoder = new BASE64Encoder();
    str = new String(encoder.encodeBuffer(str.getBytes()));
    return str;
}

private String decode(String str) {
    BASE64Decoder decoder = new BASE64Decoder();
    try {
        str = new String(decoder.decodeBuffer(str));
    } catch (IOException e) {
        e.printStackTrace();
    }       
    return str;
}
Cheesle
the use of classes from sun.misc makes this non-portable, though
Waldheinz
+1  A: 

Take a look at Jasypt. It has already done the heavy lifting for you. Specifically, the org.jasypt.encryption.pbe.StandardPBEStringEncryptor and org.jasypt.properties.PropertyValueEncryptionUtils classes.

Create an encryptor:

SimplePBEConfig config = new SimplePBEConfig(); 
config.setAlgorithm("PBEWithMD5AndTripleDES");
config.setKeyObtentionIterations(1000);
config.setPassword("propertiesFilePassword");

StandardPBEStringEncryptor encryptor = new org.jasypt.encryption.pbe.StandardPBEStringEncryptor();
encryptor.setConfig(config);
encryptor.initialize();

Then use PropertyValueEncryptionUtils to encrypt / decrypt values:

PropertyValueEncryptionUtils.encrypt(value, encryptor);
PropertyValueEncryptionUtils.decrypt(encodedValue, encryptor)

Note the encoded value will start with ENC( and end with ), so it's easy to tell if a property from a file is encrypted.

Also, note that the password used for config.setPassword() is not the password you are encoding to store in the properties file. Instead, it is the password to encrypt / decrypt the value you are storing. What this password is and how to set it is up to you. I default to the fully qualified classname of whatever is reading the Properties file.

Finally, if you are using Spring, Jasypt has an EncryptablePropertyPlaceholderConfigurer class that you can use to load the properties file and use ${foo} syntax in your Spring XML files to do variable substitution for things like DB passwords.

AngerClown
A: 

hi this is vijay am new to encrypting property file in java my requirement is i have one property file that consist of username and password like this username = abcdefg password = forterr

i need to encrypt this =abcdefg and =forterr and decrypt it , can anybody send me code to do this

alternate email id [email protected]

vijay