Using AES with Java Technology

By Rags Srinivas
June 2003

In September 2000, the National Institute of Standards and Technology (NIST) approved the Federal Information Processing Standards (FIPS) 197(pdf 279.5 kb), culminating a multi-year effort to replace the out-of-date Data Encryption Standard (DES). As with DES, the new Advanced Encryption Standard (AES) should continue making inroads into private industry. This article looks at using AES in your Java programs.

What Is AES?

AES is a federal standard for private-key or symmetric cryptography. It supports combinations of key and block sizes of 128, 192, and 256. The algorithm chosen for this standard -- called Rijndael -- was invented by two Belgian cryptographers. As part of the evaluation process, the candidate algorithms (including Rijndael) were implemented in the Java language.

AES and Java Technology

The AES standard has been incorporated into several Java technology offerings. Beginning with the Java 2 SDK, Standard Edition (J2SE) v 1.4.0, the Java Cryptography Extension (JCE) was integrated with the SDK and the JRE. Since then, it has no longer been necessary to install the JCE optional package, since support for strong cryptography is now available as part of J2SE. JCE has a provider architecture that enables different providers to be plugged in under a common framework.

Several providers have supported AES in their own clean-room implementations of JCE, or under the existing framework. In Java 2 Platform, Standard Edition v 1.4.2, which is currently under beta, the Sun Provider, referred to as SunJCE, supports AES. Also, the Java Secure Socket Extension (JSSE) supports AES via JCE.

Finally, the Java Card specification version 2.2_01 supports AES with a 128-bit key size.

In this article, we will look primarily at AES support in J2SE, starting with JCE.

Using AES in JCE

Note: The programs listed in this article work only with Java 2 Platform, Standard Edition (J2SE) 1.4.2 installed.

You use AES like any other cipher. To see how, take a look at this JCE sample program. I've modified it to use AES, instead of Blowfish (another symmetric cipher). (I have changed occurrences of Blowfish to AES.)


  1. import java.security.*;
  2. import javax.crypto.*;
  3. import javax.crypto.spec.*;
  4. import java.io.*;
  5. /**
  6. * This program generates a AES key, retrieves its raw bytes, and
  7. * then reinstantiates a AES key from the key bytes.
  8. * The reinstantiated key is used to initialize a AES cipher for
  9. * encryption and decryption.
  10. */
  11. public class AES {
  12. /**
  13. * Turns array of bytes into string
  14. *
  15. * @param buf Array of bytes to convert to hex string
  16. * @return Generated hex string
  17. */
  18. public static String asHex (byte buf[]) {
  19. StringBuffer strbuf = new StringBuffer(buf.length * 2);
  20. int i;
  21. for (i = 0; i < buf.length; i++) {
  22. if (((int) buf[i] & 0xff) < 0x10)
  23. strbuf.append("0");
  24. strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
  25. }
  26. return strbuf.toString();
  27. }
  28. public static void main(String[] args) throws Exception {
  29. String message="This is just an example";
  30. // Get the KeyGenerator

  31. KeyGenerator kgen = KeyGenerator.getInstance("AES");
  32. kgen.init(128); // 192 and 256 bits may not be available
  33. // Generate the secret key specs.
  34. SecretKey skey = kgen.generateKey();
  35. byte[] raw = skey.getEncoded();

  36. SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
  37. // Instantiate the cipher

  38. Cipher cipher = Cipher.getInstance("AES");

  39. cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
  40. byte[] encrypted =
  41. cipher.doFinal((args.length == 0 ?
  42. "This is just an example" : args[0]).getBytes());
  43. System.out.println("encrypted string: " + asHex(encrypted));
  44. cipher.init(Cipher.DECRYPT_MODE, skeySpec);
  45. byte[] original = cipher.doFinal(encrypted);
  46. String originalString = new String(original);
  47. System.out.println("Original string: " +
  48. originalString + " " + asHex(original));
  49. }
  50. }
  51.  

As you can see, the changes I made to accommodate AES are very minimal -- the JCE framework is very general and extensible.

This sample program demonstrates how to use strong cryptography, which is available by default in most installations. This does mean that support for larger key sizes is normally unavailable. To use AES with 192- and 256-bit key sizes, you need unlimited strength cryptography.

Strong Versus Unlimited Strength Cryptography

Due to import-control restrictions imposed by some countries, the jurisdiction policy files shipped with the Java 2 SDK, v 1.4 only permit strong cryptography to be used. An unlimited strength version of these files (that is, with no restrictions on cryptographic strength) is available for download, however.

After installing the unlimited strength version, to use key sizes of 192 and 256 bits, simply provide the required length of the key. The following line of code illustrates how to set the key size to 256 bits:


  1. kgen.init(256); // 128 and 192 bits also available
  2.  

The JCE examples given here show how to use AES for different key sizes, but they don't touch upon the more intricate issues -- like key management or key exchange algorithms. In practice, you may be more likely to use a protocol like Secure Socket Layer (SSL), which negotiates session keys using public keys that are subsequently used for bulk encryption.

Using AES in JSSE

Java Secure Socket Extension (JSSE) APIs are based around SSL, and the APIs are responsible for key negotiation and subsequent encryption and decryption. For a sample set of programs that illustrate the use of JSSE, see my earlier articles (listed in the See Also section, below). Since some of these articles are somewhat dated, note that the keyStore and trustStore entries will have to replaced by later versions of the corresponding files.

Some of the cipher suites may not be enabled for optimization of startup time. When SSLSockets are first created, no handshaking is done, so that applications can first set their communication preferences: which cipher suites to use, whether the socket should be in client or server mode, and so on. However, security is always provided by the time that application data is sent over the connection.

The getSupportedCipherSuites() method in SSLSocket returns all the possible suites that can be enabled for the connection. You can then use the setEnabledCipherSuites() to enable a subset of the available cipher suites, or to prioritize them. Use getEnabledCipherSuites() to return a list of all the enabled suites that are enabled by default, or that are set by a previous setEnabledCipherSuites() method call.

You can use the getCipherSuite() method in SSLSession to obtain the actual cipher used for the connection.

The following code illustrates the changes I made to the server program. The program uses regular expressions to prioritize AES encryption algorithms, with 256 bits as key size.


  1. import java.io.*;
  2. import java.security.*;
  3. import javax.net.ssl.*;

  4. import java.util.regex.*;
  5. public class HelloServerSSL {
  6. public static void main(String[] args) {
  7. SSLServerSocket s;

  8. // Pick all AES algorithms of 256 bits key size
  9. String patternString = "AES.*256";
  10. Pattern pattern = Pattern.compile(patternString);
  11. Matcher matcher;
  12. boolean matchFound;

  13. try {
  14. SSLServerSocketFactory sslSrvFact = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
  15. s =(SSLServerSocket)sslSrvFact.createServerSocket(8181);
  16. SSLSocket in = (SSLSocket)s.accept();

  17. String str[]=in.getSupportedCipherSuites();
  18. int len = str.length;
  19. String set[] = new String[len];
  20. int j=0, k = len-1;
  21. for (int i=0; i < len; i++) {
  22. // Determine if pattern exists in input
  23. matcher = pattern.matcher(str[i]);
  24. matchFound = matcher.find();
  25. if (matchFound)
  26. set[j++] = str[i];
  27. else
  28. set[k--] = str[i];
  29. }
  30. in.setEnabledCipherSuites(set);
  31. str=in.getEnabledCipherSuites();
  32. System.out.println("Available Suites after Set:");
  33. for (int i=0; i < str.length; i++)
  34. System.out.println(str[i]);
  35. System.out.println("Using cipher suite: " +
  36. (in.getSession()).getCipherSuite());

  37. PrintWriter out = new PrintWriter (in.getOutputStream(), true);
  38. out.println("Hello on a SSL socket");
  39. in.close();
  40. } catch (Exception e) {
  41. System.out.println("Exception" + e);
  42. }
  43. }
  44. }
  45.  

Here is the corresponding client code:


  1. import java.io.*;
  2. import java.security.*;
  3. import javax.net.ssl.*;

  4. import java.util.regex.*;
  5. public class HelloClientSSL {
  6. public static void main(String[] args) {

  7. // Pick all AES algorithms of 256 bits key size
  8. String patternString = "AES.*256";
  9. Pattern pattern = Pattern.compile(patternString);
  10. Matcher matcher;
  11. boolean matchFound;

  12. try {
  13. SSLSocketFactory sslFact = (SSLSocketFactory)SSLSocketFactory.getDefault();
  14. SSLSocket s =
  15. (SSLSocket)sslFact.createSocket(args.length == 0 ?
  16. "127.0.0.1" : args[0], 8181);

  17. String str[]=s.getSupportedCipherSuites();
  18. int len = str.length;
  19. String set[] = new String[len];
  20. int j=0, k = len-1;
  21. for (int i=0; i < len; i++) {
  22. System.out.println(str[i]);
  23. // Determine if pattern exists in input
  24. matcher = pattern.matcher(str[i]);
  25. matchFound = matcher.find();
  26. if (matchFound)
  27. set[j++] = str[i];
  28. else
  29. set[k--] = str[i];
  30. }
  31. s.setEnabledCipherSuites(set);
  32. str=s.getEnabledCipherSuites();
  33. System.out.println("Available Suites after Set:");
  34. for (int i=0; i < str.length; i++)
  35. System.out.println(str[i]);

  36. OutputStream out = s.getOutputStream();
  37. BufferedReader in = new BufferedReader (
  38. new InputStreamReader(s.getInputStream()));
  39. String mesg = in.readLine();
  40. System.out.println("Socket message: " + mesg);
  41. in.close();
  42. } catch (Exception e) {
  43. System.out.println("Exception" + e);
  44. }
  45. }
  46. }
  47.  

When running the server and the client, the output on the server side should be similar to the following:


  1. Available Suites after Set:
  2. TLS_RSA_WITH_AES_256_CBC_SHA
  3. TLS_DHE_RSA_WITH_AES_256_CBC_SHA
  4. TLS_DHE_DSS_WITH_AES_256_CBC_SHA
  5. TLS_DH_anon_WITH_AES_256_CBC_SHA
  6. SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
  7. SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
  8. SSL_DH_anon_WITH_DES_CBC_SHA
  9. SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
  10. TLS_DH_anon_WITH_AES_128_CBC_SHA
  11. SSL_DH_anon_WITH_RC4_128_MD5
  12. SSL_RSA_WITH_NULL_SHA
  13. SSL_RSA_WITH_NULL_MD5
  14. SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
  15. SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
  16. SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
  17. SSL_RSA_EXPORT_WITH_RC4_40_MD5
  18. SSL_DHE_DSS_WITH_DES_CBC_SHA
  19. SSL_DHE_RSA_WITH_DES_CBC_SHA
  20. SSL_RSA_WITH_DES_CBC_SHA
  21. SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
  22. SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
  23. SSL_RSA_WITH_3DES_EDE_CBC_SHA
  24. TLS_DHE_DSS_WITH_AES_128_CBC_SHA
  25. TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  26. TLS_RSA_WITH_AES_128_CBC_SHA
  27. SSL_RSA_WITH_RC4_128_SHA
  28. SSL_RSA_WITH_RC4_128_MD5
  29. Using cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA
  30.  

This output illustrates that the AES 256-bit algorithms are set to higher precedence than the other available algorithms. The cipher suite TLS_RSA_WITH_AES_256_CBC_SHAname constitutes the key negotiation, bulk encryption algorithms, and the key size, which in this case are RSA, AES and 256, respectively. SHA is used in the HMAC construction for integrity protection. By setting some of the debug output (as illustrated in my earlier article), you can get a peek into the inner workings of the different phases of the SSL algorithm.

Note: For performance reasons, it's probably not a good idea to enable all the supported algorithms, but I've included them here for illustration purposes.

Conclusion

The JCE framework is a very powerful and flexible framework for using different cryptographic algorithms. It's based on a provider architecture that enables the same framework to be used for newer cryptographic algorithms. From a developer perspective, this means a higher level of abstraction, and a common set of APIs for newer and different cryptographic algorithms -- without the need to worry about the inner workings of the algorithm.

Some of the other Java security APIs -- such as JSSE -- are implemented on top of JCE, and supplement it to make the different cryptographic algorithms (ciphers, Message Authentication Codes (MACs), and Key Exchange algorithms) available to in a more developer-friendly manner.

See Also

Java World article on AES

Java World article on Java Security optional packages (reprinted in java.sun.com)

AES home page

About the Author

Raghavan "Rags" Srinivas is a Java technology evangelist at Sun Microsystems, Inc. He specializes in Java technology and distributed systems. Srinivas has worked on several technology areas, including internals of VMS, UNIX® software, and NT.

AESwithJCE http://www.coderanch.com/how-to/content/AES_v1.html的更多相关文章

  1. requests的content与text导致lxml的解析问题

    title: requests的content与text导致lxml的解析问题 date: 2015-04-29 22:49:31 categories: 经验 tags: [Python,lxml, ...

  2. Content Security Policy 入门教程

    阮一峰文章:Content Security Policy 入门教程

  3. android 使用Tabhost 发生could not create tab content because could not find view with id 错误

    使用Tabhost的时候经常报:could not create tab content because could not find view with id 错误. 总结一下发生错误的原因,一般的 ...

  4. 【解决方案】cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'. One of '{"http://java.sun.com/xml/ns/javaee":run-as, "http://java.sun.com/xml/ns/javaee":security-role-r

    [JAVA错误] cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'. One o ...

  5. 注意 AppResLib.dll.*.mui 的生成操作应该为 Content

    为 Windows Phone 8 App 添加本地化的时候,发现修改 AppResLib.dll.*.mui 后不仅没有其变化,还发现修改它导致它失效.通过对比代码发现,问题原因是 AppResLi ...

  6. android Content Provider介绍

    ContentProvider(内容提供者)是Android中的四大组件之一.主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过Conte ...

  7. Jsoup问题---获取http协议请求失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.

    Jsoup问题---获取http协议请求失败 1.问题:用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不 ...

  8. css content之counter-reset、content-increment

    万万没想到,写了快三年前端,有不会用的css,居然还有完全没听过.见过的css属性,而且还是CSS2的内容! 关于counter-reset.content-increment两个属性的详解可以参看张 ...

  9. DOM解析XML报错:Content is not allowed in prolog

    报错内容为: Content is not allowed in prolog. Nested exception: Content is not allowed in prolog. 网上所述总结来 ...

随机推荐

  1. 黑马程序员——JAVA基础之标准输入输出流

    ------- android培训.java培训.期待与您交流! ---------- 标准输入输出流: System中的基本字段,in,out 它们各代表了系统标准的输入和输出设备. 默认输入设备是 ...

  2. jQuery radio change事件 checkbox选中事件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. PHPSTORM支持dwt文件设置方法

  4. Java多线程——同步(一)

    好习惯要坚持,这是我第二篇博文,任务略重,但是要坚持努力!!! 1.竞争条件 首先,我们回顾一下<Java核心技术卷>里讲到的多线程的"竞争条件".由于各线程访问数据的 ...

  5. MyEclipse Spring 学习总结二 Bean的生命周期

    文件结构可以参考上一节 Bean的生命周期有方法有:init-method,destroy-method ApplicationContext.xml 文件配置如下: <?xml version ...

  6. SQL语句统计每天、每月、每年的 数据

    SQL语句统计每天.每月.每年的数据 1.每年select year(ordertime) 年,sum(Total) 销售合计from 订单表group by year(ordertime) 2.每月 ...

  7. Hadoop I/O操作原理整理

    I/O操作中的数据检查 校验和方式是检查数据完整性的重要方式.一般会通过对比新旧校验和来确定数据情况,如果两者不同则说明数据已经损坏.比如,在传输数据前生成了一个校验和,将数据传输到目的主机时再次计算 ...

  8. linux net command /uboot command

    1. uboot command 读取寄存器内容 md [内存地址][长度] 修改内存地址 mw [内存地址][长度] 2. linux络命令  -- netstat -a (all)显示所有选项,默 ...

  9. MRD

    搜索 复制

  10. 浅谈可扩展性框架:MEF

    之前在使用Prism框架时接触到了可扩展性框架MEF(Managed Extensibility Framework),体验到MEF带来的极大的便利性与可扩展性. 此篇将编写一个可组合的应用程序,帮助 ...