Example of implementation with JAVA
Definition of the utility class SHA that will include the elements required for processing the HMAC-SHA-256 algorithm:
import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; import java.util.TreeMap; public class VadsSignatureExample { /** * Build signature (HMAC SHA-256 version) from provided parameters and secret key. * Parameters are provided as a TreeMap (with sorted keys). */ public static String buildSignature(TreeMap<String, String> formParameters, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { // Build message from parameters String message = String.join("+", formParameters.values()); message += "+" + secretKey; // Sign return hmacSha256Base64(message, secretKey); } /** * Actual signing operation. */ public static String hmacSha256Base64(String message, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { // Prepare hmac sha256 cipher algorithm with provided secretKey Mac hmacSha256; try { hmacSha256 = Mac.getInstance("HmacSHA256"); } catch (NoSuchAlgorithmException nsae) { hmacSha256 = Mac.getInstance("HMAC-SHA-256"); } SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256"); hmacSha256.init(secretKeySpec); // Build and return signature return Base64.getEncoder().encodeToString(hmacSha256.doFinal(message.getBytes("UTF-8"))); } }
Definition of the utility class SHA that will include the elements required for processing the SHA-1 algorithm:
import java.security.MessageDigest; import java.security.SecureRandom; public class Sha { static public final String SEPARATOR = "+" ; public static String encode(String src) { try { MessageDigest md; md = MessageDigest.getInstance( "SHA-1" ); byte bytes[] = src.getBytes( "UTF-8" ); md.update(bytes, 0, bytes. length ); byte[] sha1hash = md.digest(); return convertToHex(sha1hash); } catch(Exception e){ throw new RuntimeException(e); } } private static String convertToHex(byte[] sha1hash) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < sha1hash. length ; i++) { byte c = sha1hash[i]; addHex(builder, (c >> 4) & 0xf); addHex(builder, c & 0xf); } return builder.toString(); } private static void addHex(StringBuilder builder, int c) { if (c < 10) builder.append((char) (c + '0' )); else builder.append((char) (c + 'a' - 10)); } }
Function that computes the signature:
public ActionForward performCheck(ActionMapping actionMapping, Basivoirorm form, HttpServletRequest request, HttpServletResponse response){ SortedSet<String> vadsFields = new TreeSet<String>(); Enumeration<String> paramNames = request.getParameterNames(); // retrieve and sort the fields starting with vads_* alphabetically while (paramNames.hasMoreElements()) { String paramName = paramNames.nextElement(); if (paramName.startsWith( "vads_" )) { vadsFields.add(paramName); } } // Compute the signature String sep = Sha.SEPARATOR; StringBuilder sb = new StringBuilder(); for (String vadsParamName : vadsFields) { String vadsParamValue = request.getParameter(vadsParamName); if (vadsParamValue != null) { sb.append(vadsParamValue); } sb.append(sep); } sb.append( shaKey ); String c_sign = Sha.encode(sb.toString()); return c_sign;}