import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;
import org.springframework.util.StringUtils;
public class SignUtil {
public static String signTopRequest(Map<String, Object> params, String secret) throws Exception{
// 第一步:检查参数是否已经排序
String[] keys = params.keySet().toArray(new String[0]);
Arrays.sort(keys);
// 第二步:把所有参数名和参数值串在一起
StringBuilder query = new StringBuilder();
for (String key : keys) {
String value = replaceNullStr(params.get(key));
if (!StringUtils.isEmpty(key)&&!StringUtils.isEmpty(value)) {
if("sign".equals(key)){
continue;
}
query.append(key).append(CONST.CONNECT_EQUAL).append(value).append(CONST.CONNECT_AND);
}
}
String strtemp = null;
if(query.length()>0){
strtemp = query.substring(0, query.lastIndexOf(CONST.CONNECT_AND));
}
// 第三步:使用MD5加密
byte[] bytes;
strtemp = strtemp + secret;
System.out.println(strtemp);
bytes = encryptMD5(strtemp);
// 第四步:把二进制转化为大写的十六进制
// return new String(bytes,"UTF-8");
return byte2hex(bytes);
}
private static String replaceNullStr(Object str) {
if(str == null){
return "";
}
return str.toString();
}
/**
* 加密
* @param data
* @return
*/
private static byte[] encryptMD5(String data) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(data.getBytes("UTF-8"));
return md.digest();
}
/**
* 二进制转化为大写的十六进制
* @param bytes
* @return
*/
public static String byte2hex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
return sign.toString();
}
}
import org.apache.commons.codec.digest.DigestUtils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Test {
public static void main(String args[]) throws NoSuchAlgorithmException, UnsupportedEncodingException {
String str = "12345xxxxxx";
System.out.println("第一种方式:调用org.apache.commons.codec.digest.DigestUtils;");
String sign1 = DigestUtils.md5Hex(str);
System.out.println("第一次md5加密的字符串是");
System.out.println("第一次md5加密后转大写的");
System.out.println(sign1);
System.out.println(sign1.toUpperCase());
System.out.println("第一种方式:调用jdk中自带的java.security.MessageDigest,需要抛几个异常");
MessageDigest md = MessageDigest.getInstance("MD5");
System.out.println(md.toString());
md.update(str.getBytes("UTF-8"));
System.out.println(md.toString());
byte[] bytes = md.digest(); //encryptMD5(strtemp);
System.out.println(bytes);
/**
* 二进制转化为大写的十六进制
* @param bytes
* @return
*/
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
String result = sign.toString();
System.out.println(result);
StringBuilder sign3 = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String singdata = String.format("%2s", Integer.toHexString(bytes[i] & 0xFF).toUpperCase()).replace(' ', '0');
sign3.append(singdata);
}
String result3 = sign3.toString();
System.out.println(result3);
// 把 BYTE 类型 转化为十六进大写字符串 HEX,并在最左补齐0,方法如下。
//String singdata = String.format("%2s", Integer.toHexString(mdata & 0xFF).toUpperCase()).replace(' ', '0');
}
}
"C:Program FilesJavajdk1.8.0_172injava.exe" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2018.1.5libidea_rt.jar=41471:C:Program FilesJetBrainsIntelliJ IDEA 2018.1.5in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_172jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_172jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_172jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_172jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_172jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_172jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_172jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_172jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_172jrelibext
ashorn.jar;C:Program FilesJavajdk1.8.0_172jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_172jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_172jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_172jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_172jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_172jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_172jrelibjce.jar;C:Program FilesJavajdk1.8.0_172jrelibjfr.jar;C:Program FilesJavajdk1.8.0_172jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_172jrelibjsse.jar;C:Program FilesJavajdk1.8.0_172jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_172jrelibplugin.jar;C:Program FilesJavajdk1.8.0_172jrelib
esources.jar;C:Program FilesJavajdk1.8.0_172jrelib
t.jar;D: 0M_IDEA_Projectencryptoutproductionencrypt;D: 0M_IDEA_Projectencryptjarcommons-codec-1.11.jar" Test
第一种方式:调用org.apache.commons.codec.digest.DigestUtils;
第一次md5加密的字符串是
第一次md5加密后转大写的
c1005a2f48f6e4242fa973960ae74452
C1005A2F48F6E4242FA973960AE74452
第一种方式:调用jdk中自带的java.security.MessageDigest,需要抛几个异常
MD5 Message Digest from SUN, <initialized>
MD5 Message Digest from SUN, <in progress>
[B@63947c6b
C1005A2F48F6E4242FA973960AE74452
C1005A2F48F6E4242FA973960AE74452
MD5签名
1. 参与签名参数数组
在请求参数列表中,除去sign参数外,其他需要使用到的参数(参数值为空或空字符串除外)皆是要签名的参数。
例如下的签名参数:
brand_id=MB1000000000001
scene_str=card_center
timestamp=1504688298167
user_id=ksXMQfCgMAPT5GhKuGoTJTeFN7rxYDUdQNmfIfTUWtnGbg+IZPYBarluhEZKR1wYJS2h4odHkXhusDb49ysYbleBXH2ScnfmP9GfWVs9lKXgZXqFzkdPqxhLN3fmIV/cx3l4DCMsCHy5dmrZLmufPeUnNY/IIYG8k6+vVd3DiEc=
签名秘钥:
sign_key=”xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”
2. 生成代签名的字符串
将所有参与签名的参数名按照字典排序(每一个参数名按照a-z的顺序排序),若遇到相同的首字母,则看第二个字母,以此类推。排序完成后,再把数组所有参数按照“参数=参数值用”的模式用“&”字符拼接成字符串,并在得到的字符串最后拼接上签名秘钥sign_key得到待签名字符串signTempStr。
signTempStr=“brand_id=MB1000000000001&scene_str=card_center×tamp=1504688298167&user_id=ksXMQfCgMAPT5GhKuGoTJTeFN7rxYDUdQNmfIfTUWtnGbg+IZPYBarluhEZKR1wYJS2h4odHkXhusDb49ysYbleBXH2ScnfmP9GfWVs9lKXgZXqFzkdPqxhLN3fmIV/cx3l4DCMsCHy5dmrZLmufPeUnNY/IIYG8k6+vVd3DiEc= xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”
3. MD5签名
把上面得到的代签名字符串使用MD5进行签名,并转为大写字母得到最后的签名串sign值。
String sign = MD5(signTempStr) = 782200BEFC4BB3C37E6F35C53BBFE34E