/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.xml.ws.rt; import gw.util.StreamUtil; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.HashMap; import java.util.Map; public class DigestAuthentication { private static final int CNONCE_NUM_BYTES = 16; private static String _staticCnonceForTesting; private static String convertToHex(byte[] data) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < data.length; i++) { int halfbyte = (data[i] >>> 4) & 0x0F; int two_halfs = 0; do { if ((0 <= halfbyte) && (halfbyte <= 9)) buf.append((char) ('0' + halfbyte)); else buf.append((char) ('a' + (halfbyte - 10))); halfbyte = data[i] & 0x0F; } while (two_halfs++ < 1); } return buf.toString(); } private static String randHexBytes(int nbBytes) { byte[] bytes = new byte[nbBytes]; new SecureRandom().nextBytes(bytes); return convertToHex(bytes); } private static String digest(String src) { String target = null; try { MessageDigest digest = MessageDigest.getInstance("MD5"); digest.update(StreamUtil.toBytes(src)); target = convertToHex(digest.digest()); } catch (NoSuchAlgorithmException e) { System.out.println(e.getMessage()); } return target; } private static String getUri(String url) { String[] strs = url.split("://")[1].split("/"); if (strs.length == 1) { return "/"; } StringBuilder sb = new StringBuilder(); for (int i = 1; i < strs.length; i++) { sb.append("/").append(strs[i]); } return sb.toString(); } public static String generateDigestAuthorizationHeader(String wwwAuthenticateHeader, String username, String password, String url) { wwwAuthenticateHeader = wwwAuthenticateHeader.replaceFirst("Digest ", ""); String uri = getUri(url); String[] attrs = wwwAuthenticateHeader.split(","); Map<String, String> attrMap = new HashMap<String, String>(); for (String attr : attrs) { String[] keyValue = attr.split("="); String key = keyValue[0].trim(); String value = keyValue[1].trim().replaceAll("\"", ""); attrMap.put(key, value); } String src = username + ":" + attrMap.get("realm") + ":" + password; String ha1 = digest(src); src = "POST:" + uri; String ha2 = digest(src); String cnonce = _staticCnonceForTesting == null ? randHexBytes(CNONCE_NUM_BYTES) : _staticCnonceForTesting; src = ha1 + ":" + attrMap.get("nonce") + ":00000001:" + cnonce + ":" + attrMap.get("qop") + ":" + ha2; String response = digest(src); StringBuilder sb = new StringBuilder(); sb.append("Digest "); sb.append("username=\""); sb.append(username); sb.append("\","); sb.append("realm=\""); sb.append(attrMap.get("realm")); sb.append("\","); sb.append("nonce=\""); sb.append(attrMap.get("nonce")); sb.append("\","); sb.append("uri=\""); sb.append(uri); sb.append("\","); sb.append("cnonce=\""); sb.append(cnonce); sb.append("\","); sb.append("nc=00000001,"); sb.append("response=\""); sb.append(response); sb.append("\","); sb.append("qop=\""); sb.append(attrMap.get("qop")); sb.append("\""); return sb.toString(); } public static void setStaticClientNonceForTesting( String cnonce ) { _staticCnonceForTesting = cnonce; } }