How to use WLP passwordUtilities feature for encryption/decryption

Recently one of my colleagues asked if there was an easy way to utilise existing IBM WebSphere Application Server  (WAS) provided library to encrypt and decrypt password (or any sensitive information for that matter) from within the Java application deployed on WebSphere Liberty Profile (WLP). After doing some digging around, I found very useful WAS Liberty feature called "passwordUtilities-1.0". Class "com.ibm.websphere.crypto.PasswordUtil" is part of this feature, which provides set of static methods to deal with text encryption/decryption using default 'xor' or 'aes' algorithms. In this post, I'll walk you through, how to use it in you application.
Note: looks like feature "passwordUtilities-1.0" is available only from WLP version 8.5.5.9. Here is how you can check the version of your installed WLP product:

$> cd /opt/ibm/wlp/bin
$> ./productInfo version
Product name: WebSphere Application Server
Product version: 17.0.0.2
Product edition: BASE_ILAN

If you are using WLP version prior to 8.5.5.9, however, still need to use com.ibm.websphere.crypto.PasswordUtil, there is some work-around, which I'll explain later in this post.
Note: If you need to verify whether or not "passwordUtilities-1.0" feature is available for your version of WLP, you can run "installUtility find passwordUtilities*". The feature is supported, if it appears in search result.


$> cd /opt/ibm/wlp/bin
$> ./installUtility find passwordUtilities*
Establishing a connection to the configured repositories ...
...

Searching assets. This process might take several minutes to complete.

feature : passwordUtilities-1.0 : Password Utilities

1) Steps for WLP 8.5.5.9 and Later that Support passwordUtilities-1.0 features

1.1) Make sure "passwordUtilities-1.0" is installed.


$> cd /opt/ibm/wlp/bin
$> ./installUtility install passwordutilities-1.0
Establishing a connection to the configured repositories ...
This process might take several minutes to complete.
...
...
Step 5 of 8: Downloading passwordUtilities-1.0 ...
Step 6 of 8: Installing passwordUtilities-1.0 ...
...


All assets were successfully installed.

Start product validation...
Product validation completed successfully.           

1.2) Make sure feature "passwordUtilities-1.0" is listed under <featureManager> in the server.xml


<featureManager>
   ...
   <feature>passwordUtilities-1.0</feature>
</featureManager>

Note: If you forgot to install the "passwordUtilities-1.0" (step #1), but declared this feature in server.xml (step #2), you'll see an error message in the messages.log like this [10/7/17 20:56:42:807 BST] 0000001f com.ibm.ws.kernel.feature.internal.FeatureManager  E CWWKF0042E: A feature definition cannot  be found for the  passwordutilities-1.0 feature.  Try running the command, bin/installUtility install passwordutilities-1.0,  to install the feature. ...

1.3) [optional] Define encryption key. 

This step is required only if you are using 'aes' encryption/decryption and want to override the default encryption key. The default encryption key can be overridden by setting the wlp.password.encryption.key property. Property can be defined either in server.xml or bootstrap.properties file. However, as a best security practice, define this property in an external XML or properties file and include it in server.xml or bootstrap.properties accordingly. This ensures that the file containing the key is not included in the server dump or package command output. Here we define it in app_enc_key.xml file and put it outside of WLP configuration directory.

/opt/secrets/app_enc_key.xml
<server> 
   <variable name="wlp.password.encryption.key" value="replaceM3"/>   
</server>

Now, include /opt/secrets/app_enc_key.xml in server.xml

<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">
    <featureManager>
        <feature>webProfile-7.0</feature>
        <feature>passwordUtilities-1.0</feature>
    </featureManager>
    <include location="/opt/secrets/my_enc_key.xml"/>

    <httpEndpoint id="defaultHttpEndpoint"
                  httpPort="9080"
                  httpsPort="9443" host="*"/>
    <applicationManager autoExpand="true"/>
    <application context-root="pwdencdemo" id="pwdencdemo" location="/opt/ibm/apps/pwdencdemo.war" name="pwdencdemo" type="war"/>

</server>


1.4) Use PasswordUtil methods in the application.

Put together your application that has encoding/decoding (xor algorithm based) or more robust (aes algorithm based) encryption/decryption. You can use public static method of com.ibm.websphere.crypto.PasswordUtil class. See example below:

String myplainTxtPwd="t3mp_pwD";

// xor encoding
String xorEncodedVal=com.ibm.websphere.crypto.PasswordUtil.passwordEncode(myplainTxtPwd, "xor"));
// return xorEncodedVal value: {xor}K2wyLwAvKBs=

// aes encryption
String aesEncodedVal=com.ibm.websphere.crypto.PasswordUtil.passwordEncode(myplainTxtPwd, "aes"));
// return aesEncodedVal value: {aes}AM99D1D9JLThDLt32ZCn3VBj27kuwNp5MorW6Ig/7h5h

// xor decoding
String xorDecodedVal=com.ibm.websphere.crypto.PasswordUtil.passwordDecode("{xor}K2wyLwAvKBs="));
// return xorDecodedVal value: t3mp_pwD

// aes decryption
String aesDecodedVal=com.ibm.websphere.crypto.PasswordUtil.passwordDecode("{aes}AM99D1D9JLThDLt32ZCn3VBj27kuwNp5MorW6Ig/7h5h"));
// return aesDecodedVal value: t3mp_pwD

For full details of all available methods see Java documentation of  com.ibm.websphere.crypto.PasswordUtil

I have created a GitLab project, which contains server.xml and a simple web application pwdencdemo.war, which you can deploy into your WLP server and test the working of encryption/decryption.

2) Steps for WLP 8.5.5.8 and Prior version.

2.1) Define Java library and configure classloader for the application. 

Since "passwordUtilities-1.0" feature is not available in WLP 8.5.5.8 or earlier versions, in order to use public methods of com.ibm.websphere.crypto.PasswordUtil, we need to make sure this class and any other dependent classes are accessible for the application in run time. The easiest way to do it is to define a Java library (that includes com.ibm.ws.crypto.passwordutil_<version>.jar, com.ibm.ws.kernel.service_<version>.jar, and  com.ibm.ws.logging_<version>.jar), include in the application itself, and configure classloader for the application.  These jar files come with WLP product and located under ${wlp.install.dir}/lib directory. See below for example:

<application context-root="pwdencdemo" id="pwdencdemo" location="/opt/ibm/apps/pwdencdemo.war" name="pwdencdemo" type="war"> 
   <classloader> 
      <privatelibrary> 
         <fileset dir="${wlp.install.dir}/lib" includes="com.ibm.ws.crypto.passwordutil_*.jar,com.ibm.ws.kernel.service_*.jar,com.ibm.ws.logging_*.jar"> 
         </fileset> 
      </privatelibrary> 
   </classloader> 
</application>

See IBM Knowledge Center documentation for more detail on configuring Java library.
Note: Make sure your library configuration is correct and all listed jar files are available in the given location, otherwise, you may get java.lang.NoClassDefFoundError: com/ibm/websphere/crypto/PasswordUtil exception.


2.2) Follow steps #1.3 and #1.4 from from the previous section.

Hope, this post will be helpful for your current or next WLP based project. If you are deploying your application in Docker container, visit my blog <<Using Docker Secrets with IBM WebSphere Liberty Profile Application Server>>

Note: If you just need to encode/encrypt password to put into your server.xml or bootstrap.properties, you can use securityUtility tool that comes with WLP product. Below is a simple example:
$> cd /opt/ibm/wlp/bin
$> ./securityUtility encode --encoding=aes --key=replaceM3 t3mp_pwD

For more detail on securityUtility , refer to https://www.ibm.com/support/knowledgecenter/en/SSEQTP_8.5.5/com.ibm.websphere.wlp.doc/ae/rwlp_command_securityutil.html


Looks like you're really interested in WebSphere Liberty Profile, see my other related blog posts below:


1 comment: