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();