Key Locator Framework (KLF)

To comply with the Payment Card Industry Data Security Standard (PCI DSS), a Key Locator Framework (KLF) is introduced to allow an encryption key to be stored outside of WebSphere Commerce. For example, the merchant key can now be stored and retrieved from a configurable location such as from an external, more secure, device. This is accomplished by associating each encryption key with a key provider class.

There are two key providers that are ready for immediate use.

Key providers for Merchant key:
  • WCMerchantKeyImpl: stores the merchant key in the instance configuration file.
  • WCExternalFileMerchantKeyImpl: stores the merchant key in an external file.
Note: The KLF does not support defining a custom session key implementation. This option is only available for merchant keys.

If you want to store the encryption key by using a different mechanism, for example, by using a hardware device, you must create a custom key provider class. This class must implement the WCKey interface, and extend from the following abstract class: WCKeyBaseImpl. This abstract class implements some of the common methods on the WCKey interface. The list of encryption keys available to the system is registered in a key configuration file.

To define an alternative merchant key provider in a separate custom key configuration file, see Implementation of the KLF.

The default key configuration file is WCKeys.xml, which contains the following:

   <key name="MerchantKey" 
        providerName="WC" 
        status="current"
        className="com.ibm.commerce.security.keys.WCMerchantKeyImpl">
   </key>

   <key name="SessionKey" 
        providerName="WC" 
        status="current"
        className="com.ibm.commerce.security.keys.WCSessionKeyImpl">
   </key>

Where:

name
Name of the key.
providerName
Name of the provider. You can specify your own custom provider name to refer to your customized provider class name. This can only be modified for the Merchant Key.
status
Valid values are "current" and "new". At most times, there would be only a single key for each key name, and that key would have status "current". In this case, the key would be used for encrypting new data and decrypting existing data.

Valid values are "current", "pending" and "new". At most times, there would be only a single key for each key name, and that key would have status "current". In this case, the key would be used for encrypting new data and decrypting existing data.

While you are running MigrateEncryptedInfo, an extra key with status "new" must be added to the key configuration file.
If you want to change the merchant key while the site is live, in a clustered environment, the new key is introduced in two steps:
  1. Add the new key to the key configuration file and set its status to "pending". Then, a partial EAR update is called so that the change is picked up. In the clustered environment, as each node picks up the new "pending" key, it can decrypt with the new key, if needed, but never encrypt with it. New encryption would continue to be done with the highest version "current" key.
  2. Change the status of the new key from "pending" to "new" in the key configuration file, and then do another partial EAR update. While the change is being propagated, nodes that already picked up the "new" key would use it for any new encryption. Nodes that have not yet picked up the "new" key would still be able to decrypt any new data by using the "pending" key.
Note: If you are running in a non-clustered environment, the first step of introducing the key with the status of "pending" can be skipped. Once the "new" key is picked up by all the nodes, it is safe to run MigrateEncryptedInfo on the live site. When MigrateEncryptedInfo completes, the "current" key can be removed from the key configuration file and the "new" key can be changed to "current" status.
className
The Java class that implements your key provider.
version
Optional: Version of the key. You must specify a version if you plan to run the MigrateEncryptedInfo utility to change the encryption key while the site is live. The MigrateEncryptedInfo utility decrypts data encrypted with the "current" key, and re-encrypts it with the "new" key. When your site is live and the utility is running, WebSphere Commerce must have a way to differentiate data encrypted with the "current" key from data encrypted with the "new" key. For this reason, you must specify a unique version number to associate to each key by using this version parameter. When you encrypt data by using a versioned key, the ActiveProvider encryption provider appends a suffix to the data itself using this convention: _IBM_n. For example, _IBM_3 denotes that this data is encrypted with version 3 of the encryption key. The utility appends the data with this suffix in plain text, for example: yXiW3W4iblU=_IBM_3. Data that was encrypted before versioning was introduced does not have this suffix, and is associated with a key that does not have a version. When you encrypt data at run time, the "new" key provider is used if it is defined. If a "new" key is not defined, then the "current" key with the highest version is used.
config
Optional: Parameters that are required by your provider, for example the name of a configuration file.
algorithm
Algorithm for the merchant key. Valid values are "AES" and "3DES". If you are running the MigrateEncryptedInfo command for the first time to migrate encryption from 3DES to AES, set this value to AES. If the algorithm parameter is not specified for the merchant key, the AES_DB parameter is checked in the following file to determine if AES is used:
  • For IBM i OS operating systemAIXLinuxWindowsWC_installdir\xml\product.xml
  • WebSphere Commerce Developerworkspace_dir\WC\xml\config\wc-server.xml

Once all the encryption keys are registered in the key configuration file, the WCKeyRegistry class is used for reading this file and caches all the key providers in memory.

You can use the getKey(strKeyName) and getNewKey(strKeyName) methods of WCKeyRegistry to retrieve the current and new key provider.

For example, to retrieve the "current" key with a particular name, you can use the following code snippet:
WCKey key = WCKeyRegistry.getInstance().getKey(<name of the key>); 
String keyValue = key.getValueAsString();
To retrieve the "new" key with a particular name and provider:
WCKey newKey = WCKeyRegistry.getInstance().getNewKey(<name of the key>, <name of the provider>); 
String newKeyValue = newKey.getNewValueAsString();
The main WCKeyRegistry methods are as follows:
  • getKey(strKeyName) Returns the "new" key if it exists, or the "current" key with the highest version
  • getCurrentKeys() Returns the current keys
  • getNewKey() Returns the new key if it is defined