前段时间,由于工作需要,首次接触md5加密 (接触的有点晚)
本次需求主要是对接淘宝保险产品,我们将产品发布到淘宝商城上进行销售,客户进行购买后,我们为其完成核保、承保的相关工作。因为是两个系统之间的对接,所有牵扯报文交互。
对接系统:淘宝商城,寿险网销系统
交互协议:http请求
数据格式 :xml 报文
加密机制:
在我未拿到相关的文档的时候,我以为一定是一种非常酷的加密方式,毕竟牵扯的双方都是业界大拿,雄踞乙方的商业霸主,但是拿到具体的文档后,着实大跌眼镜。
发送方对报文进行(MD5)加签,接收方同样对报文进行加签,然后对签名进行比较
注意MD5是不可逆 ,加密之后就是一个字符串 ,所有淘宝 需要把签名和xml 报文一起传过来 ,然后 接收方在按照共同的公钥 ,(公钥+xml)进行加签(是不是low)
不过在研发的过程中发现了一个有意思的事 :
一个http请求,既可以是post请求,也可以使get请求,大家不妨一试
扫描二维码关注公众号,回复:
1007958 查看本文章
另外,有一点值得注意的是,在加密的过程中,如果含有中文,那么编码格式是非常重要的,在加签名的过程中,中文的格式将影响到最后密文
具体代码如下
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();
}