Reputation: 23
I'm trying to store some strings in a .properties file. Now i want to encrypt those strings with Jasypt. But when I try to save this to the .properties file it is missing the surrounding "ENC()". When i try to insert this manually, the string is stored in clear text. Why?
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword("123456789");
Properties prop = new EncryptableProperties(encryptor);
prop.setProperty("key", "ENC(" + encryptor.encrypt("value") + ")");
prop.store(new FileOutputStream(System.getProperty("user.home") + "/.application-name/config.properties"), "Test");
Upvotes: 0
Views: 1713
Reputation: 965
Looking at the JDK source code explains what's happening here. The cause is the class hierarchy involved; org.jasypt.properties.EncryptableProperties
extends java.util.Properties
which in turn extends java.util.Hashtable
.
So when prop.store()
is called, the method from java.util.Properties
is invoked:
public void store(OutputStream out, String comments)
throws IOException
{
store0(new BufferedWriter(new OutputStreamWriter(out, "8859_1")),
comments,
true);
}
private void store0(BufferedWriter bw, String comments, boolean escUnicode)
throws IOException
{
if (comments != null) {
writeComments(bw, comments);
}
bw.write("#" + new Date().toString());
bw.newLine();
synchronized (this) {
for (Enumeration e = keys(); e.hasMoreElements();) {
String key = (String)e.nextElement();
String val = (String)get(key);
key = saveConvert(key, true, escUnicode);
/* No need to escape embedded and trailing spaces for value, hence
* pass false to flag.
*/
val = saveConvert(val, false, escUnicode);
bw.write(key + "=" + val);
bw.newLine();
}
}
bw.flush();
}
The interesting line is
String val = (String)get(key);
EncryptableProperties
defines a
public Object get(Object key)
method, overriding that of java.util.Hashtable
- see the Jasypt API docs for EncryptableProperties. Hence the method below is invoked, which as you can see by reading the decode
method, will perform the decryption, which in your case is not what you want!
public synchronized Object get(final Object key) {
final Object value = super.get(key);
final String valueStr =
(value instanceof String) ? (String)value : null;
return decode(valueStr);
}
private synchronized String decode(final String encodedValue) {
if (!PropertyValueEncryptionUtils.isEncryptedValue(encodedValue)) {
return encodedValue;
}
if (this.stringEncryptor != null) {
return PropertyValueEncryptionUtils.decrypt(encodedValue, this.stringEncryptor);
}
if (this.textEncryptor != null) {
return PropertyValueEncryptionUtils.decrypt(encodedValue, this.textEncryptor);
}
/*
* If neither a StringEncryptor nor a TextEncryptor can be retrieved
* from the registry, this means that this EncryptableProperties
* object has been serialized and then deserialized in a different
* classloader and virtual machine, which is an unsupported behaviour.
*/
throw new EncryptionOperationNotPossibleException(
"Neither a string encryptor nor a text encryptor exist " +
"for this instance of EncryptableProperties. This is usually " +
"caused by the instance having been serialized and then " +
"de-serialized in a different classloader or virtual machine, " +
"which is an unsupported behaviour (as encryptors cannot be " +
"serialized themselves)");
}
To avoid this, don't use EncryptableProperties
to store your properties, just using java.util.Properties
will do. Simply replace
Properties prop = new EncryptableProperties(encryptor);
with
Properties prop = new Properties();
and the encrypted values will be stored in the properties file.
Upvotes: 1