Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

encrypt and decrypt property file value in java

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.

like image 631
user234194 Avatar asked Sep 22 '10 13:09

user234194


1 Answers

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.

like image 189
AngerClown Avatar answered Oct 07 '22 00:10

AngerClown