文档中心 > Taobao Global Open Platform

签名加密算法

更新时间:2021/08/04 访问次数:1218

淘宝全球开放平台会对每个 API 请求的身份进行验证,伺服器也将验证呼叫参数是否有效。因此,每个 HTTP 请求必须包含签名资讯,签名无效的请求将被拒绝。
淘宝全球开放平台通过 App Key 和分配给应用程式的金钥来验证请求的身份。 App 金钥用于在 HTTP 请求 URL 和伺服器端签名字串时生成签名字串。请严格保密您的金钥。
如果手动编写 HTTP 请求(而不使用官方 SDK),则需要了解以下签名算法。

生成签名的过程如下:

  • 根据 ASCII 表中的参数名称对所有请求参数(包括系统和应用程式参数,但“符号”和带位元组阵列类型的参数除外)进行排序。举例:

Before sort:

foo=1, bar=2, foo_bar=3, foobar=4

After sort:

bar=2, foo=1, foo_bar=3, foobar=4

  • 将排序后的参数及其值连接到一个字串中。举例:bar2foo1foo_bar3foobar4

  • 在连接的字串前面添加API名称。举例,添加API名称“/test/api”:

/test/apibar2foo1foo_bar3foobar4

  • 用UTF-8格式编码连接的字串,并通过签名演算法(使用HMAC_SHA256)进行摘要。举例:

hmac_sha256(/test/apibar2foo1foo_bar3foobar4)

  • 将摘要转换为十六进位格式。举例:

hex("helloworld".getBytes("utf-8")) = "68656C6C6F776F726C64"

JAVA 示例代码:

/**
     * Sign the API request with body.
     */
    public static String signApiRequest(Map<String, String> params, String body, String appSecret, String signMethod, String apiName) throws IOException {
       // first: sort all text parameters
       String[] keys = params.keySet().toArray(new String[0]);
       Arrays.sort(keys);
 
       // second: connect all text parameters with key and value
       StringBuilder query = new StringBuilder();
       query.append(apiName);
       for (String key : keys) {
           String value = params.get(key);
           if (areNotEmpty(key, value)) {
              query.append(key).append(value);
           }
       }
 
       // third:put the body to the end
       if (body != null) {
           query.append(body);
       }
 
       // next : sign the whole request
       byte[] bytes = null;
      
       if(signMethod.equals(Constants.SIGN_METHOD_HMAC)) {
           bytes = encryptWithHmac(query.toString(), appSecret);
        } else if(signMethod.equals(Constants.SIGN_METHOD_SHA256)) {
           bytes = encryptHMACSHA256(query.toString(), appSecret);
       }
 
       // finally : transfer sign result from binary to upper hex string
       return byte2hex(bytes);
    }
 
    private static byte[] encryptHMACSHA256(String data, String secret) throws IOException  {
    byte[] bytes = null;
    try {
            SecretKey secretKey = new SecretKeySpec(secret.getBytes(Constants.CHARSET_UTF8), Constants.SIGN_METHOD_HMAC_SHA256);
            Mac mac = Mac.getInstance(secretKey.getAlgorithm());
            mac.init(secretKey);
            bytes = mac.doFinal(data.getBytes(Constants.CHARSET_UTF8));
    } catch (GeneralSecurityException gse) {
            throw new IOException(gse.toString());
        }
        return bytes;
    }
 
    /**
     * Transfer binary array to HEX string.
     */
    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();
   }

C# 示例代码:

public static string SignRequest(IDictionary<string, string> parameters, string body, string appSecret, string signMethod, string apiName)
        {
            // first : sort all key with asci order
            IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
 
            // second : contact all params with key order
            StringBuilder query = new StringBuilder();
            query.Append(apiName);
            foreach (KeyValuePair<string, string> kv in sortedParams)
            {
                if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value))
                {
                    query.Append(kv.Key).Append(kv.Value);
                }
            }
 
            // third : add body to last
            if (!string.IsNullOrEmpty(body))
            {
                query.Append(body);
            }
 
            // next : sign the string
            byte[] bytes = null;
            if (signMethod.Equals(Constants.SIGN_METHOD_SHA256))
            {
                HMACSHA256 sha256 = new HMACSHA256(Encoding.UTF8.GetBytes(appSecret));
                bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
            }
 
            // finally : transfer binary byte to hex string
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < bytes.Length; i++)
            {
                result.Append(bytes[i].ToString("X2"));
            }
 
            return result.ToString();
        }

PYTHON 示例代码:

def sign(secret,api, parameters):
    #===========================================================================
    # @param secret
    # @param parameters
    #===========================================================================
    sort_dict = sorted(parameters)
   
    parameters_str = "%s%s" % (api,
        str().join('%s%s' % (key, parameters[key]) for key in sort_dict))
 
    h = hmac.new(secret.encode(encoding="utf-8"), parameters_str.encode(encoding="utf-8"), digestmod=hashlib.sha256)
    return h.hexdigest().upper()

其他程式设计语言的签名样例代码,请参阅官方 SDK 的原始程式码。

FAQ

关于此文档暂时还没有FAQ
返回
顶部