Encrypting Passwords in Java Property Files
Configuration is an essential part of every software development project. Among other things, we store sensitive information such as database, ftp and other credentials in these configuration files. This may not be an issue for a small company. But if you're working for a large bank, this becomes a major audit issue. Hence, i give to you this post about encrypting passwords in Java Property files.
PropertyFile Templates
We need a way to externalize sensitive information from the property files and put a place holder for them. These place holders will be replaced when the build process gets triggered. For this we will be using StringTemplate.
I will not go into details on how one uses StringTemplate. But below is an an example configuration file with the said place holders.
//PropertyFile.st
ftp.username=$ftpUsername$
ftp.username=$ftpPassword$
Password File
As you can see, the property file template expects the variables $ftpUsername$ and $ftpPassword$ to be replaced by the actual value. This variables are stored in another property file. Lets just call it Passwords.prop and its content is shown below.
//Passwords.prop
ftpUsername=jake.stateresa
ftpPassword=omgwtfbbq!!!!
The Goal
The goal of this exercise is to be able to generate a property file based on the template Property.st and have the stubs replaced with the values in Passwords.prop. All variables ending with Password should be encrypted in the generated property file.
//Target.prop
ftp.username=jake.stateresa
ftp.username=uznecctWVkMqB9eMxnIJ7Q==
The source code below demonstrates the process of loading the Password file to a Properties object, encrypting all values in the Password file whose key ends with "Password", loading the template and passing the Properties object to the setAttributes method and writing the output of the template operation to a file.
1: Properties passwordFileProperties = new Properties();
2: passwordFileProperties.load(new FileInputStream(passwordFilePath));
3: Set<String> stringPropertyNames = passwordFileProperties.stringPropertyNames();
4: for (String propertyName : stringPropertyNames) {
5: if(propertyName.endsWith("Password")){
6: String propertyValue = passwordFileProperties.getProperty(propertyName);
7: passwordFileProperties.setProperty(
8: propertyName,
9: encryptionHelper.encrypt(propertyValue));
10: }
11: }
12:
13: StringTemplate template =
14: templateGroup.getInstanceOf(templateName);
15: template.setAttributes(passwordFileProperties);
16:
17: FileWriter outputStream = new FileWriter(outputFilename);
18: BufferedWriter outputWriter = new BufferedWriter(outputStream);
19: outputWriter.write(template.toString());
20: outputWriter.close();
In your java program, you can read/decrypt the properties from the output file using the code below. In reality you would have used the values on an FtpClient class like the one commented out below.
1:
2: Properties encryptedProperties = new Properties();
3: encryptedProperties.load(new FileInputStream("Output.prop"));
4: String username = encryptedProperties.getProperty("ftp.username");
5: String encryptedPassword = encryptedProperties.getProperty("ftp.password");
6: String decryptedPassword = new EncryptionHelper().decrypt(encryptedPassword);
7:
8: //FtpClient ftp = new FtpClient("localhost", 22, username, decryptedPassword);
9: System.out.print(String.format("Username: %s; Password: %s", username, decryptedPassword));
10:
Final Notes
You can find the source code for this project here. Please make sure to download the latest StringTemplate libs from this location when you attempt to execute the project.
Feel free to comment on the given approach. This is my first post in Java so be gentle.
Cheers!