Symmetric Encryption
67
getInstance()
As we've mentioned before, most of the classes in the JCE use factory methods instead of normal
constructors. Rather than create an instance with the new keyword, we make a call to the class's
getInstance() method, with the name of the algorithm and some additional parameters like so:
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
The first parameter is the name of the algorithm, in this case, "DESede". The second is the mode the cipher
should use, "ECB", which stands for Electronic Code Book. The third parameter is the padding, specified
with "PKCS5Padding". We'll go into more detail about the mode and padding later. For now, just be aware
that even though it is possible to skip the declaration of the mode and padding they should be declared
anyway. If the mode and padding are skipped, the provider picks a mode and padding to use, which is
rarely what you want, and prevents the code from being ported to other providers.
init()
Once an instance of Cipher is obtained, it must be initialized with the init() method. This declares the
operating mode, which should be either ENCRYPT_MODE or DECRYPT_MODE, and also passes the cipher a
key (java.security.Key, described later). Assuming we had a key declared, initialized, and stored in the
variable myKey, we could initialize a cipher for encryption with the following line of code:
cipher.init(Cipher.ENCRYPT_MODE, myKey);
The JCE 1.2.1 specification adds two more possible operating modes, WRAP_MODE and UNWRAP_MODE.
These modes set up a cipher to encrypt or decrypt keys. We'll use these modes later, when we use
asymmetric encryption.
update()
In order to actually encrypt or decrypt anything, we need to pass it to the cipher in the form of a byte
array. If the data is in the form of anything other than a byte array, it needs to be converted. If we have a
string called myString and we want to encrypt it with the cipher we've initialized above, we can do so with
the following two lines of code:
byte[] plaintext = myString.getBytes("UTF8");
byte[] ciphertext = cipher.update(plaintext);
Ciphers typically buffer their output. If the input is large enough that it produces some ciphertext, it will be
returned as a byte array. If the buffer has not been filled, then null will be returned.
Note that in order to get bytes from a string, we should specify the encoding method. In most cases, it will
be UTF8.
If you don't specify the encoding type, you will get the underlying platform's default encoding. This
is almost never what you want, and can cause bizarre errors when encryption takes place on one
platform, and decryption on another. Always specify the encoding.
doFinal()
Now we can actually get the encrypted data from the cipher. doFinal() will produce a byte array, which
is the encrypted data.
byte[] ciphertext = cipher.doFinal();