Key Wrapping

The CRYPTOKI KeyStore also provides a key wrapping mechanism. Key wrapping is a technique where one key value is encrypted using another key. With SafeNet ProtectToolkit-J, since the key values are stored securely on the hardware, we can use this technique to encrypt the key on the hardware and then extract the encrypted key.

For example, using this mechanism, a session key may be generated on the hardware and then exported from the hardware in an encrypted (wrapped) form. The key will generally be encrypted using a Public/Private key encryption cipher and can then be safely exported from the HSM. It is also possible to use secret keys for key wrapping. In this case, however, the same secret key must exist on both the source (performing the wrapping function) and the destination adapters.

The WrappingKeyStore API is an extension to the standard JCE that is used to provide access to key wrapping services. This class is identical to the standard KeyStore API, except that it provides wrapKey() and unwrapKey()methods. The wrapping key store can be instantiated using the following code:

import au.com. safenet.crypto.WrappingKeyStore;

...

WrappingKeyStore wks = WrappingKeyStore.getInstance("CRYPTOKI",
                                                    "SAFENET");
...  

The wrapKey() method has the following signature:

public byte[] wrapKey(Key wrapKey, String transformation, Key key)
throws GeneralSecurityException  

The wrapKey parameter specifies the Key used to encrypt the key parameter. The transformation parameter specifies the encryption transformation that is to be used to encrypt the key. With the CRYPTOKI KeyStore, you can transform the following:

>RSA/ECB/PKCS1Padding

>RSA/ECB/NoPadding

>DES/ECB/NoPadding

>DES/ECB/PKCS5Padding

>DESede/ECB/NoPadding

>DESede/ECB/PKCS5Padding

>IDEA/ECB/NoPadding

>IDEA/ECB/PKCS5Padding

>CAST128/ECB/NoPadding

>CAST128/ECB/PKCS5Padding

>RC2/ECB/NoPadding

>RC2/ECB/PKCS5Padding

>RC4

A GeneralSecurityException will be thrown if the transformation parameter is invalid.

The value returned is a byte array containing the encrypted key. This value may be passed to the unwrapKey()method to extract the original key. The unwrapKey() method has the following signature:

public Key unwrapKey(Key unwrapKey, String transformation,
                     byte[] wrappedKey, String keyAlgorithm)
throws GeneralSecurityException  

This method will "unwrap" or decrypt the encrypted key using the provided decryption key and transformation. The Key returned will be of the type specified by the keyAlgorithm parameter. This parameter must match the actual key type that was originally wrapped.

The unwrapKey parameter should be either the same secret key as was used to wrap the key, or the private key corresponding to the public key used to wrap the key. The transformation parameter specifies the decryption transformation used to decrypt the key. This value should be the same as that used to wrap the key. The wrappedKey parameter should contain the encrypted key. The keyAlgorithm should specify the algorithm that the decrypted key is for.

A GeneralSecurityException will be thrown if the transformation parameter is invalid.

The following example will create a new random RC4 key, wrap that key with an RSA public key, and unwrap it with the associated RSA private key.

KeyGenerator keyGen = KeyGenerator.getInstance(“RC4”, “SAFENET”);
Key rc4Key = keyGen.generateKey();
WrappingKeyStore wks = WrappingKeyStore.getInstance(“CRYPTOKI”);
wks.load(null, null);  // initialise the KeyStore
Key publicKey = wks.getKey(“RSA_pub”, null);
byte[] encKey = Wks.wrapKey(publicKey,“RSA/ECB/PKCS1Padding”,rc4Key);
// give the encrypted key to the recipient, and unwrap it
Key privateKey = wks.getKey(“RSA_priv”, null);
Key recoveredKey = wks.unwrapKey(privateKey, “RSA/ECB/PKCS1Padding’,
                                                             encKey);