签名在接口中使用广泛,那么进行接口交互的时候为了保证数据中途不会被篡改需要进行一致性签名,下面将为大家展示个语言一致性前面的算法,同样的内容签名后的数据必须是一致的:
java版本:
1 package cn.com.gome.utils; 2 3 /** 4 * 编码 5 * @author 6 * 7 */ 8 public abstract class Constants { 9 10 /**11 * TOP默认时间格式12 */13 public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";14 15 /**16 * TOP Date默认时区17 */18 public static final String DATE_TIMEZONE = "GMT+8";19 20 /**21 * UTF-8字符集22 */23 public static final String CHARSET_UTF8 = "UTF-8";24 25 /**26 * GBK字符集27 */28 public static final String CHARSET_GBK = "GBK";29 30 /**31 * TOP JSON 应格式32 */33 public static final String FORMAT_JSON = "json";34 35 /**36 * TOP XML 应格式37 */38 public static final String FORMAT_XML = "xml";39 40 /**41 * MD5签名方式42 */43 public static final String SIGN_METHOD_MD5 = "md5";44 45 /**46 * HMAC签名方式47 */48 public static final String SIGN_METHOD_HMAC = "hmac";49 50 51 }
1 package cn.com.gome.utils; 2 3 import java.io.IOException; 4 import java.security.GeneralSecurityException; 5 import java.security.MessageDigest; 6 import java.security.NoSuchAlgorithmException; 7 import java.util.Arrays; 8 import java.util.Map; 9 10 import javax.crypto.Mac; 11 import javax.crypto.SecretKey; 12 import javax.crypto.spec.SecretKeySpec; 13 14 import cn.com.gome.utils.StringUtils; 15 16 /** 17 * 签名工具 18 * @author 19 * 20 */ 21 public class SignUtil { 22 /** 23 * 签名算法 24 * 25 * @param params 26 * @param secret 27 * @param signMethod 28 * @return 29 * @throws IOException 30 */ 31 public static String signTopRequest(Mapparams, String secret, String signMethod) 32 throws IOException { 33 // 第一步:检查参数是否已经排序 34 String[] keys = params.keySet().toArray(new String[0]); 35 Arrays.sort(keys); 36 37 // 第二步:把所有参数名和参数值串在一起 38 StringBuilder query = new StringBuilder(); 39 if (Constants.CHARSET_UTF8.equals(signMethod)) { 40 query.append(secret); 41 } 42 for (String key : keys) { 43 String value = params.get(key); 44 if (StringUtils.areNotEmpty(key, value)) { 45 query.append(key).append(value); 46 } 47 } 48 49 // 第三步:使用MD5/HMAC加密 50 byte[] bytes = new byte[0]; 51 if (Constants.CHARSET_UTF8.equals(signMethod)) { 52 bytes = encryptHMAC(query.toString(), secret); 53 } else { 54 query.append(secret); 55 try { 56 bytes = encryptMD5(query.toString()); 57 } catch (NoSuchAlgorithmException e) { 58 // TODO Auto-generated catch block 59 e.printStackTrace(); 60 } 61 } 62 63 // 第四步:把二进制转化为大写的十六进制 64 return byte2hex(bytes); 65 } 66 67 /** 68 * hmac加密 69 * @param data 70 * @param secret 71 * @return 72 * @throws IOException 73 */ 74 public static byte[] encryptHMAC(String data, String secret) throws IOException { 75 byte[] bytes = null; 76 try { 77 SecretKey secretKey = new SecretKeySpec(secret.getBytes(Constants.CHARSET_UTF8), "HmacMD5"); 78 Mac mac = Mac.getInstance(secretKey.getAlgorithm()); 79 mac.init(secretKey); 80 bytes = mac.doFinal(data.getBytes(Constants.CHARSET_UTF8)); 81 } catch (GeneralSecurityException gse) { 82 throw new IOException(gse.toString()); 83 } 84 return bytes; 85 } 86 87 /** 88 * 实现md5加密 89 * @param data 90 * @return 91 * @throws IOException 92 * @throws NoSuchAlgorithmException 93 */ 94 public static byte[] encryptMD5(String data) throws IOException, NoSuchAlgorithmException { 95 96 //确定计算方法 97 MessageDigest md5 = MessageDigest.getInstance("MD5"); 98 return md5.digest(data.getBytes(Constants.CHARSET_UTF8)); 99 }100 101 /**102 * 将字节数据进行16位处理103 * @param bytes104 * @return105 */106 public static String byte2hex(byte[] bytes) {107 StringBuilder sign = new StringBuilder();108 for (int i = 0; i < bytes.length; i++) {109 String hex = Integer.toHexString(bytes[i] & 0xFF);110 if (hex.length() == 1) {111 sign.append("0");112 }113 sign.append(hex.toUpperCase());114 }115 return sign.toString();116 }117 }
1 package cn.com.gome.utils; 2 3 /** 4 * 字符串工具类 5 * @author 6 * 7 */ 8 public abstract class StringUtils { 9 10 private StringUtils() {} 11 12 /** 13 * 检查指定的字符串是否为空。 14 *
- 15 *
- SysUtils.isEmpty(null) = true 16 *
- SysUtils.isEmpty("") = true 17 *
- SysUtils.isEmpty(" ") = true 18 *
- SysUtils.isEmpty("abc") = false 19 *
.net版本
1 private static string SignTopRequest(IDictionaryparameters, string secret, string signMethod) 2 { 3 // 第一步:把字典按Key的字母顺序排序 4 IDictionary sortedParams = new SortedDictionary (parameters, StringComparer.Ordinal); 5 IEnumerator > dem = sortedParams.GetEnumerator(); 6 7 // 第二步:把所有参数名和参数值串在一起 8 StringBuilder query = new StringBuilder(); 9 if (Constants.CHARSET_UTF_8.Equals(signMethod))10 {11 query.Append(secret);12 }13 while (dem.MoveNext())14 {15 string key = dem.Current.Key;16 string value = dem.Current.Value;17 if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))18 {19 query.Append(key).Append(value);20 }21 }22 23 // 第三步:使用MD5/HMAC加密24 byte[] bytes;25 if (Constants.CHARSET_UTF_8.Equals(signMethod))26 {27 HMACMD5 hmac = new HMACMD5(Encoding.UTF8.GetBytes(secret));28 bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));29 }30 else31 {32 query.Append(secret);33 MD5 md5 = MD5.Create();34 bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));35 }36 37 // 第四步:把二进制转化为大写的十六进制38 StringBuilder result = new StringBuilder();39 for (int i = 0; i < bytes.Length; i++)40 {41 result.Append(bytes[i].ToString("X2"));42 }43 44 return result.ToString();45 }
1 namespace Sys.Common 2 { 3 public sealed class Constants 4 { 5 public static string CHARSET_ISO_2022_JP = "ISO-2022-JP"; 6 public static string CHARSET_ISO_2022_CN = "ISO-2022-CN"; 7 public static string CHARSET_ISO_2022_KR = "ISO-2022-KR"; 8 public static string CHARSET_ISO_8859_5 = "ISO-8859-5"; 9 public static string CHARSET_ISO_8859_7 = "ISO-8859-7";10 public static string CHARSET_ISO_8859_8 = "ISO-8859-8";11 public static string CHARSET_BIG5 = "BIG5";12 public static string CHARSET_GB18030 = "GB18030";13 public static string CHARSET_EUC_JP = "EUC-JP";14 public static string CHARSET_EUC_KR = "EUC-KR";15 public static string CHARSET_EUC_TW = "EUC-TW";16 public static string CHARSET_SHIFT_JIS = "SHIFT_JIS";17 public static string CHARSET_IBM855 = "IBM855";18 public static string CHARSET_IBM866 = "IBM866";19 public static string CHARSET_KOI8_R = "KOI8-R";20 public static string CHARSET_MACCYRILLIC = "x-mac-cyrillic"; //C#中"MACCYRILLIC"改名了21 public static string CHARSET_WINDOWS_1251 = "WINDOWS-1251";22 public static string CHARSET_WINDOWS_1252 = "WINDOWS-1252";23 public static string CHARSET_WINDOWS_1253 = "WINDOWS-1253";24 public static string CHARSET_WINDOWS_1255 = "WINDOWS-1255";25 public static string CHARSET_UTF_8 = "UTF-8";26 public static string CHARSET_UTF_16BE = "UTF-16BE";27 public static string CHARSET_UTF_16LE = "UTF-16LE";28 public static string CHARSET_UTF_32BE = "UTF-32BE";29 public static string CHARSET_UTF_32LE = "UTF-32LE";30 public static string CHARSET_TIS_620 = "WINDOWS-874";//C#泰语的TIS-620在.NET里叫WINDOWS-87431 //.NET直接支持GB2312编码的32 //public static string CHARSET_HZ_GB_2312 = "GB2312"; 33 34 // WARNING: Listed below are charsets which Java does not support.35 public static string CHARSET_HZ_GB_2312 = "HZ-GB-2312"; // Simplified Chinese36 public static string CHARSET_X_ISO_10646_UCS_4_3412 = "X-ISO-10646-UCS-4-3412"; // Malformed UTF-3237 public static string CHARSET_X_ISO_10646_UCS_4_2143 = "X-ISO-10646-UCS-4-2143"; // Malformed UTF-3238 }39 }
golang版本
1 package utils 2 3 import ( 4 "bytes" 5 "crypto/hmac" 6 "crypto/md5" 7 "fmt" 8 "sort" 9 "strconv" 10 "strings" 11 "sync" 12 ) 13 14 //签名的字符编码类型 15 type GOLANG_CHARSET string 16 17 //字符编码类型常量 18 const ( 19 CHARSET_ISO_2022_JP GOLANG_CHARSET = "ISO-2022-JP" 20 CHARSET_ISO_2022_CN = "ISO-2022-CN" 21 CHARSET_ISO_2022_KR = "ISO-2022-KR" 22 CHARSET_ISO_8859_5 = "ISO-8859-5" 23 CHARSET_ISO_8859_7 = "ISO-8859-7" 24 CHARSET_ISO_8859_8 = "ISO-8859-8" 25 CHARSET_BIG5 = "BIG5" 26 CHARSET_GB18030 = "GB18030" 27 CHARSET_EUC_JP = "EUC-JP" 28 CHARSET_EUC_KR = "EUC-KR" 29 CHARSET_EUC_TW = "EUC-TW" 30 CHARSET_SHIFT_JIS = "SHIFT_JIS" 31 CHARSET_IBM855 = "IBM855" 32 CHARSET_IBM866 = "IBM866" 33 CHARSET_KOI8_R = "KOI8-R" 34 CHARSET_MACCYRILLIC = "x-mac-cyrillic" 35 CHARSET_WINDOWS_1251 = "WINDOWS-1251" 36 CHARSET_WINDOWS_1252 = "WINDOWS-1252" 37 CHARSET_WINDOWS_1253 = "WINDOWS-1253" 38 CHARSET_WINDOWS_1255 = "WINDOWS-1255" 39 CHARSET_UTF_8 = "UTF-8" 40 CHARSET_UTF_16BE = "UTF-16BE" 41 CHARSET_UTF_16LE = "UTF-16LE" 42 CHARSET_UTF_32BE = "UTF-32BE" 43 CHARSET_UTF_32LE = "UTF-32LE" 44 CHARSET_TIS_620 = "WINDOWS-874" 45 CHARSET_HZ_GB_2312 = "HZ-GB-2312" 46 CHARSET_X_ISO_10646_UCS_4_3412 = "X-ISO-10646-UCS-4-3412" 47 CHARSET_X_ISO_10646_UCS_4_2143 = "X-ISO-10646-UCS-4-2143" 48 ) 49 50 //当前类的指针 51 var sign *signUtils 52 53 //同步锁 54 var signone sync.Once 55 56 //签名类 57 type signUtils struct { 58 mapExtend *MapExtend 59 } 60 61 //实例化签名 62 func Sign() *signUtils { 63 signone.Do(func() { 64 sign = new(signUtils) 65 sign.mapExtend = new(MapExtend) 66 }) 67 return sign 68 } 69 70 /** 71 签名算法 72 parameters 要签名的数据项 73 secret 生成的publicKey 74 signMethod 签名的字符编码 75 */ 76 func (s *signUtils) SignTopRequest(parameters *map[string]string, secret string, signMethod GOLANG_CHARSET) string { 77 /** 78 1、第一步:把字典按Key的字母顺序排序 79 2、第二步:把所有参数名和参数值串在一起 80 3、第三步:使用MD5/HMAC加密 81 4、第四步:把二进制转化为大写的十六进制 82 */ 83 84 //第一步:把字典按Key的字母顺序排序 85 keys, err := s.mapExtend.GetKeys(parameters) 86 if err != nil { 87 // goto result 88 return "" 89 } 90 sort.Strings(keys) 91 //第二步:把所有参数名和参数值串在一起 92 var bb bytes.Buffer 93 if CHARSET_UTF_8 == signMethod { 94 bb.WriteString(secret) 95 } 96 for i, v := range keys { 97 _ = i 98 val := (*parameters)[v] 99 if len(val) > 0 {100 bb.WriteString(v)101 bb.WriteString(val)102 }103 }104 fmt.Println(bb.String())105 //第三步:使用MD5/HMAC加密106 b := make([]byte, 0)107 if CHARSET_UTF_8 == signMethod {108 h := hmac.New(md5.New, s.GetUtf8Bytes(secret))109 h.Write(bb.Bytes())110 b = h.Sum(nil)111 } else {112 bb.WriteString(secret)113 md5instence := md5.New()114 md5instence.Write(bb.Bytes())115 b = md5instence.Sum(nil)116 }117 //第四步:把二进制转化为大写的十六进制118 var result bytes.Buffer119 for i := 0; i < len(b); i++ {120 s := strconv.FormatInt(int64(b[i]&0xff), 16)121 if len(s) == 1 {122 result.WriteString("0")123 }124 result.WriteString(s)125 }126 //返回签名完成的字符串127 return strings.ToUpper(result.String())128 }129 130 //默认utf8字符串131 func (s *signUtils) GetUtf8Bytes(str string) []byte {132 b := []byte(str)133 return b134 }