文档中心 > 淘寶台灣開放平台

簽名加密演算法

更新时间:2020/06/23 访问次数:720

淘寶台灣開放平台會對每個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
返回
顶部