• 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
  • 相关阅读:
    PyCharm中的Console自动换行
    Jenkins 配置用户权限错误导致无法登录解决方案
    Jenkins进阶-用户权限管理(10)
    python3+Flask 链接MySQL 时,提示“No module named MYSQLdb”
    Mongo导出mongoexport和导入mongoimport介绍
    maven常用命令
    Git 的origin和master分析
    How to handle your webdriver exceptions
    Java中equals和==的区别
    Maven中-DskipTests和-Dmaven.test.skip=true的区别
  • 原文地址:https://www.cnblogs.com/linuxone/p/6709276.html
Copyright © 2020-2023  润新知