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.
To store the encryption key by using a different mechanism, for example, by using a hardware device, we 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.WCExternalFileMerchantKeyImpl"> <config name="keyFile" value="merchantKey.xml" /> <config name="keyEncryptionKeyFile" value="KeyEncryptionKey.xml" /> </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. We can specify our own custom provider name to refer to our 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 we are running MigrateEncryptedInfo, an extra key with status "new" must be added to the key configuration file.
To change the merchant key while the site is live, 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 using the "pending" key.
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. We 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 the 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, we 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 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 we 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:
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.
We 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, we 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
Related concepts
Implementation of the KLF
Related tasks
Encrypting data in custom code using EncryptionFactory