PBE Ciphers

A PBE Cipher is a password based cipher. It allows keying of a cipher based on a user supplied password. PKCS#5 is the standard which defines the generic PBE algorithm used by all PBE algorithms except for the PBEWithSHA1AndTripleDES algorithm, which uses PKCS#12 (see PKCS #12: Personal Information Exchange Syntax Standard). A particular PBE implementation will combine a message digest algorithm (such as MD5) with a symmetric encryption algorithm (DES, for example).

SafeNet ProtectToolkit-J includes five password-based Ciphers. They are essentially identical, with the password-generation differences below:

>PBEWithMD2AndDES - uses MD2 in password generation

>PBEWithMD5AndDES - uses MD5 in password generation

>PBEWithMD5AndCAST - uses MD5 in password generation

>PBEWithSHA1AndCAST - uses SHA1 in password generation

>PBEWithSHA1AndTripleDES - uses SHA1 in password generation

As the names suggest, these ciphers use either DES, CAST, or TripleDES as their encryption algorithm, and are therefore 64-bit block ciphers. They are all operated with the block cipher in CBC mode; however, the initialization vector is determined from the password, so there is no need to supply its value.

PBE Cipher Initialization

A PBE Cipher will always operate with the underlying Cipher in a specific mode. For SafeNet ProtectToolkit-J, the DES Cipher will operate in CBC mode with PCKS5Padding. Thus, the only valid transformations that may be passed to the Cipher.getInstance() method are PBEWithMD2AndDES, PBEWithMD5AndDES , PBEWithMD5AndCAST, PBEWithSHA1AndCAST, or PBEWithSHA1AndTripleDES.

This Cipher will only accept a SafeNet ProtectToolkit-J provider PBE key as the key parameter during initialization. To create such a Key, use the PBE SecretKeyFactory described below.

This Cipher also requires initialization with a valid PBEParameterSpec instance, (or an AlgorithmParameters instance that can be converted to the generic form via the getParameterSpec() method). This parameters instance is used to supply the salt and iteration count parameters to the PBE Cipher. This is a required parameter, there are no defaults and so the Cipher.getParameters() method, this will always return null.

PBE Key

The PBE Cipher instances require initialization with a SafeNet ProtectToolkit-J provider PBE key. Instances of this type may be created using the PBE SecretKeyFactory. The PBE SecretKeyFactory is used to construct SafeNet ProtectToolkit-J keys from their provider-independent form. The provider independent form of the PBE key is the javax.crypto.spec.PBEKeySpec class.

For example, to create the provider based key from its provider independent form:

PBEKeySpec pbeKS = new PBEKeySpec(“password”.toCharArray())
SecretKeyFactory pbeKF = SecretKeyFactory.getInstance(“PBE”,
                                                    “SAFENET”);
Key key = pbeKF.generateSecret(pbeKS);

The SafeNet ProtectToolkit-J PBE key will return the string “PBE” as its algorithm name, “RAW” as its encoding. However, this key class does not support encoding and so will return null from the getEncoded() method.

PBE Example Code

The following example code will create a PBE key with the string “password”, convert this into a SafeNet ProtectToolkit-J PBE key, then create a PBE cipher. Next it initializes the cipher for encryption using the newly-created key and the PBE parameters with a salt of “salt” and an iteration count of 5. Finally we encrypt the string "hello world".

To perform the decryption, we simply re-initialize the cipher in decrypt mode, with the same key and parameters.

PBEKeySpec pbeKS = new PBEKeySpec(“password”.toCharArray())
SecretKeyFactory pbeKF = SecretKeyFactory.getInstance(“PBE”,
                                                    “SAFENET”);
Key pbeKey = pbeKF.generateSecret(pbeKS);
PBEParameterSpec pbeParams =
                     new PBEParameterSpec(“salt”.getBytes, 5);
Cipher pbeCipher = Cipher.getInstance(“PBEWithMD5andDES”,
                                                    “SAFENET”);
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParams);
byte[] cipherText = pbeCipher.doFinal(
                             “hello world”.getBytes());
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParams);
byte[] plainText = pbeCipher.doFinal(cipherText);