Browse DevX
Sign up for e-mail newsletters from DevX


Encrypt Sensitive Configuration Data with Java-2 : Page 2




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Encrypting a String
There are two main classes that I have created to solve this problem: StringEncrypter and EncryptionScheme. Figure 1 shows a UML representation of what is provided in the source code.
Figure 1. Stringing Along: This UML class diagram represents the contents of the StringEncrypter and EncryptionScheme classes.

The StringEncrypter class (Listing 1) provides methods that allow you to encrypt and decrypt a string using a given encryption scheme. The first constructor takes two parameters: an object of type EncryptionScheme and the encryption key that will be used to encrypt and decrypt. After you construct the StringEncrypter, you can encrypt and decrypt a given string using the eponymous methods, encrypt and decrypt.

I have provided a set of unit tests that demonstrate how the StringEncrypter works (see Listing 2).

EncryptionScheme is a Java interface that encapsulates the properties of different encryption schemes. A concrete class that implements the EncryptionScheme interface is passed into the StringEncrypter (this is known as the strategy design pattern). You can pass a custom key into the constructor, or you can use the one that is provided by default, DEFAULT_ENCRYPTION_KEY. If you use the single argument constructor, it will automatically use the default key.

The main calls in the encrypt and decrypt methods are the calls made to the Cipher class (see the next section). The Cipher.init() method takes an integer that represents the encryption mode (encrypt or decrypt) and the key as an argument. Static constants representing the encryption mode are defined on the Cipher class. The Cipher.doFinal() method performs an encryption or decryption, based on what mode was initialized.

The Java Cryptography Extension (JCE)
The EncryptionScheme object that is passed into the constructor of the StringEncrypter class is used to generate three class-level fields: a KeySpec, a SecretKeyFactory, and a Cipher. The encrypt and decrypt methods on the StringEncrypter also use the SecretKey class. These classes are part of the JCE, a framework that provides key generation and encryption, among other things. This package comes standard in J2SE v1.4 and is available as an optional package in Java 2 SDK, versions 1.2.x and 1.3.x.

Here is what the Java 1.4.1 API specification has to say about these classes:

  • KeySpec—"A (transparent) specification of the key material that constitutes a cryptographic key."
  • SecretKeyFactory—"Key factories are used to convert keys (opaque cryptographic keys of type Key) into key specifications (transparent representations of the underlying key material), and vice versa. Secret key factories operate only on secret (symmetric) keys."
  • Cipher—"This class provides the functionality of a cryptographic cipher for encryption and decryption. It forms the core of the JCE framework."
  • SecretKey—"A secret (symmetric) key."
There are two other classes that are used in the enrypt and decrypt methods. The classes are: BASE64Encoder and BASE64Decoder. These classes are not part of the JCE, but they are helpful for converting between byte arrays and strings. BASE64Encoder encodes a binary stream as a "Base64" format string. BASE64Decoder decodes a "Base64" format string into a binary stream

Using the StringEncrypter
Along with all the implementation classes shown in the source code download, I have provided a set of unit tests that demonstrate how the StringEncrypter works.

Testing Encryption

public void testEncryptsUsingDesEde() throws Exception { String stringToEncrypt = "test"; String encryptionKey = "123456789012345678901234567890"; EncryptionScheme encryptionScheme = DesEdeEncryptionScheme.INSTANCE; StringEncrypter encrypter = new StringEncrypter( encryptionScheme, encryptionKey ); String encryptedString = encrypter.encrypt( stringToEncrypt ); assertEquals( "Ni2Bih3nCUU=", encryptedString ); }

This test shows how a client application would encrypt a string using the DESede encryption scheme. First, I specified a string that I wanted to encrypt—"test"—and an encryption key. For DESede encryption, the encryption key must be more than 24 characters long. I used a 30-character encryption key just to be on the safe side.

There is no instance-specific data in the DesEdeEncryptionScheme class, thus it is designed using the Singleton design pattern so that you don't have to maintain multiple instances of the class in memory. The EncryptionScheme object is obtained through a static constant defined on the DesEdeEncryptionScheme class.

Next, a StringEncrypter is constructed using the EncryptionScheme and the key. At this point, obtaining an encrypted string is as simple as calling the encrypt method, and passing in the String you wish to encrypt. The test asserts that the value of the encrypted string is correct according to its previously determined value (a regression test).

Decrypting the string is just as simple. A StringEncrypter is constructed by passing in the encryption key and the EncryptionScheme object. The encrypted string is passed to the decrypt method, which returns the unencrypted string ("test").

Testing Decryption

public void testDecryptsUsingDesEde() throws Exception { String string = "Ni2Bih3nCUU="; String encryptionKey = "123456789012345678901234567890"; EncryptionScheme encryptionScheme = DesEdeEncryptionScheme.INSTANCE; StringEncrypter encrypter = new StringEncrypter( encryptionScheme, encryptionKey ); String decryptedString = encrypter.decrypt( string ); assertEquals( "test", decryptedString ); }

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date