sign签名算法一致算法-.net、java、golang

签名在接口中使用广泛,那么进行接口交互的时候为了保证数据中途不会被篡改需要进行一致性签名,下面将为大家展示个语言一致性前面的算法,同样的内容签名后的数据必须是一致的:

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 }
View Code
  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(Map<String, String> params, 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 bytes
104      * @return
105      */
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 }
View Code
  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      * <ul>
 15      * <li>SysUtils.isEmpty(null) = true</li>
 16      * <li>SysUtils.isEmpty("") = true</li>
 17      * <li>SysUtils.isEmpty("   ") = true</li>
 18      * <li>SysUtils.isEmpty("abc") = false</li>
 19      * </ul>
 20      * 
 21      * @param value 待检查的字符串
 22      * @return true/false
 23      */
 24     public static boolean isEmpty(String value) {
 25         int strLen;
 26         if (value == null || (strLen = value.length()) == 0) {
 27             return true;
 28         }
 29         for (int i = 0; i < strLen; i++) {
 30             if ((Character.isWhitespace(value.charAt(i)) == false)) {
 31                 return false;
 32             }
 33         }
 34         return true;
 35     }
 36 
 37     /**
 38      * 检查对象是否为数字型字符串,包含负数开头的。
 39      */
 40     public static boolean isNumeric(Object obj) {
 41         if (obj == null) {
 42             return false;
 43         }
 44         char[] chars = obj.toString().toCharArray();
 45         int length = chars.length;
 46         if(length < 1)
 47             return false;
 48         
 49         int i = 0;
 50         if(length > 1 && chars[0] == '-')
 51             i = 1;
 52         
 53         for (; i < length; i++) {
 54             if (!Character.isDigit(chars[i])) {
 55                 return false;
 56             }
 57         }
 58         return true;
 59     }
 60 
 61     /**
 62      * 检查指定的字符串列表是否不为空。
 63      */
 64     public static boolean areNotEmpty(String... values) {
 65         boolean result = true;
 66         if (values == null || values.length == 0) {
 67             result = false;
 68         } else {
 69             for (String value : values) {
 70                 result &= !isEmpty(value);
 71             }
 72         }
 73         return result;
 74     }
 75 
 76     /**
 77      * 把通用字符编码的字符串转化为汉字编码。
 78      */
 79     public static String unicodeToChinese(String unicode) {
 80         StringBuilder out = new StringBuilder();
 81         if (!isEmpty(unicode)) {
 82             for (int i = 0; i < unicode.length(); i++) {
 83                 out.append(unicode.charAt(i));
 84             }
 85         }
 86         return out.toString();
 87     }
 88 
 89     /**
 90      * 过滤不可见字符
 91      */
 92     public static String stripNonValidXMLCharacters(String input) {
 93         if (input == null || ("".equals(input)))
 94             return "";
 95         StringBuilder out = new StringBuilder();
 96         char current;
 97         for (int i = 0; i < input.length(); i++) {
 98             current = input.charAt(i);
 99             if ((current == 0x9) || (current == 0xA) || (current == 0xD)
100                     || ((current >= 0x20) && (current <= 0xD7FF))
101                     || ((current >= 0xE000) && (current <= 0xFFFD))
102                     || ((current >= 0x10000) && (current <= 0x10FFFF)))
103                 out.append(current);
104         }
105         return out.toString();
106     }
107 
108 }
View Code

.net版本

 1  private static string SignTopRequest(IDictionary<string, string> parameters, string secret, string signMethod)
 2         {
 3             // 第一步:把字典按Key的字母顺序排序
 4             IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
 5             IEnumerator<KeyValuePair<string, string>> 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             else
31             {
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         }
View Code
 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-874
31         //.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 Chinese
36         public static string CHARSET_X_ISO_10646_UCS_4_3412 = "X-ISO-10646-UCS-4-3412"; // Malformed UTF-32
37         public static string CHARSET_X_ISO_10646_UCS_4_2143 = "X-ISO-10646-UCS-4-2143"; // Malformed UTF-32
38     }
39 }
View Code

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.Buffer
119     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 b
134 }
View Code

 

posted @ 2017-04-14 15:55  linuxone  阅读(4264)  评论(1编辑  收藏  举报
kaochuan