前段時間,因爲工做須要,首次接觸md5加密 (接觸的有點晚)git
本次需求主要是對接淘寶保險產品,咱們將產品發佈到淘寶商城上進行銷售,客戶進行購買後,咱們爲其完成核保、承保的相關工做。由於是兩個系統之間的對接,全部牽扯報文交互。算法
對接系統:淘寶商城,壽險網銷系統app
交互協議:http請求post
數據格式 :xml 報文編碼
加密機制:加密
在我未拿到相關的文檔的時候,我覺得必定是一種很是酷的加密方式,畢竟牽扯的雙方都是業界大拿,雄踞乙方的商業霸主,可是拿到具體的文檔後,着實大跌眼鏡。spa
發送方對報文進行(MD5)加簽,接收方一樣對報文進行加簽,而後對簽名進行比較code
注意MD5是不可逆 ,加密以後就是一個字符串 ,全部淘寶 須要把簽名和xml 報文一塊兒傳過來 ,而後 接收方在按照共同的公鑰 ,(公鑰+xml)進行加簽(是否是low)orm
不過在研發的過程當中發現了一個有意思的事 :xml
一個http請求,既能夠是post請求,也可使get請求,你們不妨一試
另外,有一點值得注意的是,在加密的過程當中,若是含有中文,那麼編碼格式是很是重要的,在加簽名的過程當中,中文的格式將影響到最後密文
具體代碼以下
public class SignUtil { private static String key=null;//Configuration.getValue("tmall.comId"); private static String encoding="GBK"; private static final FormatLogger log = new FormatLogger(SignUtil.class); public static void setKey(String key){ SignUtil.key = key; } public static String readXmlFromInputStream(ServletInputStream sis) throws Exception{ ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = -1; while ((len = sis.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } String requestXml = new String(outSteam.toByteArray(), encoding); log.info("SignUtil-readXmlFromInputStream-requestXml:"+requestXml); return requestXml; } public static boolean validateSign(String requestXml, String sign) throws IOException, NoSuchAlgorithmException{ MessageDigest md = MessageDigest.getInstance("MD5"); md.update(key.getBytes(encoding)); md.update(requestXml.getBytes(encoding)); byte[] bs = md.digest(); String resultStr = bytes2HexString(bs); boolean flag = sign.equals(resultStr); log.info("SignUtil-validateSign-key:" + key + " resultStr:"+resultStr + " return:" + flag); return flag; } public static String sign(String data) throws NoSuchAlgorithmException, UnsupportedEncodingException{ MessageDigest md = MessageDigest.getInstance("MD5"); md.update(key.getBytes(encoding)); md.update(data.getBytes(encoding)); return asHex(md.digest()); } public static String asHex (byte hash[]) { StringBuffer buf = new StringBuffer(hash.length * 2); int i; for (i = 0; i < hash.length; i++) { if (((int) hash[i] & 0xff) < 0x10) buf.append("0"); buf.append(Long.toString((int) hash[i] & 0xff, 16)); } return buf.toString(); } public final static String MD5(String s) { char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; try { byte[] btInput = s.getBytes(); // 得到MD5摘要算法的 MessageDigest 對象 MessageDigest mdInst = MessageDigest.getInstance("MD5"); // 使用指定的字節更新摘要 mdInst.update(btInput); // 得到密文 byte[] md = mdInst.digest(); // 把密文轉換成十六進制的字符串形式 int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { e.printStackTrace(); return null; } } public static String bytes2HexString(byte[] b) { StringBuffer result = new StringBuffer(); String hex; for (int i = 0; i < b.length; i++) { hex = Integer.toHexString(b[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } result.append(hex); } return result.toString(); }