You are here : Home » Learning security » Applications » Java » Implement hash service using JCE

Implement hash service using JCE

D 10 November 2010     H 14:13     A Emeric Nasi     C 0 messages


agrandir


License : Copyright Emeric Nasi, some rights reserved
This work is licensed under a Creative Commons Attribution 4.0 International License.
Creative Commons License

In this article I will present how-to simply use hash methods in your Java projects. I will also follow the Java coding security recommendation from the Java-sec project developed by French consortium (SILICOM-AMOSSYS-INRIA) for ANSSI. You can find the entire document here (in French).
At the end of this article you should be able to build your HashService class. By hash service I mean a object between JCE and the developers, easy to use and that you can integrate into your local security API.

I. Using the JCE

I.1 The Java Cryptography Extension

It is not the goal of this article to describe what is the JCE. If you would like to learn more about the JCE you should read this simple definition or the official reference guide .

II.2 Using JCE objects

All classes in the JCE are used the same way. You call a class instance using the getInstance() method. The classes does not directly describe the algorithm used; instead, when you call an instance of a JCE object, you must specify the algorithm and the provider of the service you want to use.
In our case, the object we need to implement hash services is "MessageDigest" from the package java.security.
Example :
MessageDigest messageDigest = MessageDigest.getInstance("SHA-512", "SUN");
In this example, we are going the use the SHA 512 hash algorithm provided by SUN.

I.3 Why should we build our own hash service?

The reason is that we do not want every developer to implement JCE access each time he needs to hash a message. yes, but why?
First because having a separate service (inside a security API for example) allows you to normalize your code and to be sure your use the same algorithms everywhere. Moreover using separate services can allow you to modify in one time the hash algorithm used by the entire app, without having to modify any Java code (by setting a .properties file for example).
There is another reason linked to the security of the application itself :
JCE is shipped with a list of providers of algorithms. That list may differ whether you are using Windows or Linux system. A developer has the possibility to call an object instance without describing the provider, in this case, the default provider will be use. That may be a problem because
as Javasec study pointed app, all JCE providers are not equally secure. For example the SUN pseudo random generator (SHA1-PRNG) is considered to have statistic flaws, and SUN is the default provider on most JCE installs!

II. Creating our hash service

II.1 The HashService.java code

Note : For this service I am using the singleton pattern. If you don’t like that you can modify the code the make static method calls for example.

A commented code is the best example :

  1. package com.test.security;
  2.  
  3. import java.security.MessageDigest;
  4. import java.security.NoSuchAlgorithmException;
  5. import java.security.NoSuchProviderException;
  6. import java.util.Properties;
  7.  
  8. /**
  9.  * The HashService class
  10.  * NOTE : Remember to always precise the keyword final if class is not supposed to be inheritable
  11.  */
  12. public final class HashService {
  13.  
  14. private static final String PROP_FILE = "/hashservice.properties";
  15.  
  16. // Set default algo and provider :
  17. private String defaultProvider;
  18. private String defaultAlgorithm;
  19. // Set algo and provider for SHA-1
  20. private String sha1Provider;
  21. private String sha1Algorithm;
  22.  
  23. // For singleton pattern
  24. private static HashService instance = new HashService();
  25.  
  26. /**
  27.   * Public access so it is easy to know the default algorithm
  28.   */
  29. public String getDefaultAlgorithm() {
  30. return this.defaultAlgorithm;
  31. }
  32.  
  33. /**
  34.   * Constructor (initialise properties)
  35.   */
  36. private HashService() {
  37. try {
  38. final Properties prop = new Properties();
  39. prop.load(HashService.class.getResourceAsStream(PROP_FILE));
  40. this.defaultProvider = prop.getProperty("defaultProvider");
  41. this.defaultAlgorithm = prop.getProperty("defaultAlgorithm");
  42. this.sha1Provider = prop.getProperty("sha1Provider");
  43. this.sha1Algorithm = prop.getProperty("sha1Algorithm");
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. }
  47. }
  48.  
  49. /**
  50.   * Return the HashService Instance
  51.   * @return
  52.   */
  53. public static synchronized HashService getInstance() {
  54. return instance;
  55. }
  56.  
  57. /**
  58.   * We do not want our singleton to have clones
  59.   */
  60. protected Object clone() throws CloneNotSupportedException {
  61. throw new CloneNotSupportedException("Clone is not allowed.");
  62. }
  63.  
  64. /**
  65.   * Return the Hash String corresponding to the digest byte[]
  66.   * NOTE : This method could be exported to another service
  67.   * @param hexBytes
  68.   * @return
  69.   */
  70. private String hex2String(final byte[] hexBytes) {
  71. final StringBuffer hexString = new StringBuffer();
  72. for (int i = 0; i < hexBytes.length; i++) {
  73. hexString.append(Integer.toHexString(0xFF & hexBytes[i]));
  74. }
  75. return hexString.toString();
  76. }
  77.  
  78. /**
  79.   * The method used to hash a message
  80.   * @param message
  81.   * @return
  82.   */
  83. public String digest(final String message) {
  84. byte[] hashMessageBytes;
  85. String hashMessage = null;
  86. try {
  87. // Get messageDigest instance
  88. final MessageDigest messageDigest = MessageDigest.getInstance(this.defaultAlgorithm, this.defaultProvider);
  89. // Hash the message
  90. hashMessageBytes = messageDigest.digest(message.getBytes());
  91. // Convert the hash bytes to String
  92. hashMessage = hex2String(hashMessageBytes);
  93. // You can add log feature here
  94. e.printStackTrace();
  95. // You can add log feature here
  96. e.printStackTrace();
  97. }
  98. return hashMessage;
  99. }
  100.  
  101. /**
  102.   * Use this method if you really need SHA1 hash
  103.   * WARNING : SHA11 is considered to be have security flaws, if possible you should use the digest() method which
  104.   * uses the DEFAULT_ALGORIHM algorithm
  105.   * @param message
  106.   * @return
  107.   */
  108. public String sha1Digest(final String message) {
  109. byte[] hashMessageBytes;
  110. String hashMessage = null;
  111. try {
  112. // Get messageDigest instance
  113. final MessageDigest messageDigest = MessageDigest.getInstance(this.sha1Algorithm, this.sha1Provider);
  114. // Hash the message
  115. hashMessageBytes = messageDigest.digest(message.getBytes());
  116. // Convert the hash bytes to String
  117. hashMessage = hex2String(hashMessageBytes);
  118. // You can add log feature here
  119. e.printStackTrace();
  120. // You can add log feature here
  121. e.printStackTrace();
  122. }
  123. return hashMessage;
  124. }
  125. }

II.2 The hashservice.properties file content

II.3 Call our service

  1. public static void main(String[] args) {
  2. String message = "Hello world";
  3. try {
  4.  
  5. System.out.println("SHA-512 for Hello World: "+HashService.getInstance().digest(message));
  6. System.out.println("SHA-1 for Hello World: "+HashService.getInstance().sha1Digest(message));
  7.  
  8. } catch (Exception e) {
  9. e.printStackTrace();
  10. }
  11. }

The output should be something like :
SHA-512 for Hello World: b7f783baed8297f0db917462184ff4f08e69c2....
SHA-1 for Hello World: 7b502c3a1f48c8609ae212cdfb639dee39673f5e

Conclusion

Now you are able to implement hash methods in you Java applications.
This simple example can be improved and reused for other JCE features, like random numbers and encryption.

Also in this section

13 January 2011 – Modify any Java class field using reflection.

8 January 2011 – Enable securitymanager for Spring and Hibernate

Any message or comments?
pre-moderation

This forum is moderated before publication: your contribution will only appear after being validated by an administrator.

Who are you?
Your post