Implement hash service using JCE
10 November 2010 14:13 0 messages
License : Copyright Emeric Nasi, some rights reserved
This work is licensed under a Creative Commons Attribution 4.0 International 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
A commented code is the best example :
package com.test.security; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.util.Properties; /** * The HashService class * NOTE : Remember to always precise the keyword final if class is not supposed to be inheritable */ public final class HashService { // Set default algo and provider : // Set algo and provider for SHA-1 // For singleton pattern private static HashService instance = new HashService(); /** * Public access so it is easy to know the default algorithm */ return this.defaultAlgorithm; } /** * Constructor (initialise properties) */ private HashService() { try { prop.load(HashService.class.getResourceAsStream(PROP_FILE)); this.defaultProvider = prop.getProperty("defaultProvider"); this.defaultAlgorithm = prop.getProperty("defaultAlgorithm"); this.sha1Provider = prop.getProperty("sha1Provider"); this.sha1Algorithm = prop.getProperty("sha1Algorithm"); e.printStackTrace(); } } /** * Return the HashService Instance * @return */ public static synchronized HashService getInstance() { return instance; } /** * We do not want our singleton to have clones */ } /** * Return the Hash String corresponding to the digest byte[] * NOTE : This method could be exported to another service * @param hexBytes * @return */ for (int i = 0; i < hexBytes.length; i++) { } return hexString.toString(); } /** * The method used to hash a message * @param message * @return */ byte[] hashMessageBytes; try { // Get messageDigest instance final MessageDigest messageDigest = MessageDigest.getInstance(this.defaultAlgorithm, this.defaultProvider); // Hash the message hashMessageBytes = messageDigest.digest(message.getBytes()); // Convert the hash bytes to String hashMessage = hex2String(hashMessageBytes); // You can add log feature here e.printStackTrace(); // You can add log feature here e.printStackTrace(); } return hashMessage; } /** * Use this method if you really need SHA1 hash * WARNING : SHA11 is considered to be have security flaws, if possible you should use the digest() method which * uses the DEFAULT_ALGORIHM algorithm * @param message * @return */ byte[] hashMessageBytes; try { // Get messageDigest instance final MessageDigest messageDigest = MessageDigest.getInstance(this.sha1Algorithm, this.sha1Provider); // Hash the message hashMessageBytes = messageDigest.digest(message.getBytes()); // Convert the hash bytes to String hashMessage = hex2String(hashMessageBytes); // You can add log feature here e.printStackTrace(); // You can add log feature here e.printStackTrace(); } return hashMessage; } }
II.2 The hashservice.properties file content
II.3 Call our service
try { e.printStackTrace(); } }
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