主頁 > 服務(wù)與支持 > 開發(fā)平臺 > 服務(wù)端API參考 > 附錄 signature說明
更新時(shí)間:2019-11-20
1.待請求數(shù)據(jù):
CanonicalRequest = HTTPRequestMethod + '\n' + CanonicalURI + '\n' + CanonicalHeaders + '\n' + HexEncode(Hash(RequestPayload))
HTTPRequestMethod:http請求方法
CanonicalURI:URL路徑,計(jì)算簽名時(shí),URI必須以“/”結(jié)尾。發(fā)送請求時(shí),可以不以“/”結(jié)尾。
CanonicalHeaders:由多個(gè)請求消息頭(目前協(xié)商取content-type\date頭域)共同組成,CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ...,
其中每個(gè)請求消息頭(CanonicalHeadersEntry )的格式為Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n‘
說明:
Lowercase表示將所有字符轉(zhuǎn)換為小寫字母的函數(shù)。
Trimall表示刪除值前后的多余空格的函數(shù)。
最后一個(gè)請求消息頭也會攜帶一個(gè)換行符。疊加規(guī)范中CanonicalHeaders自身攜帶的換行符,因此會出現(xiàn)一個(gè)空行。
請求消息體:
消息體需要做兩層轉(zhuǎn)換:HexEncode(Hash(RequestPayload)),其中Hash表示生成消息摘要的函數(shù),當(dāng)前支持SHA-256算法。
HexEncode表示以小寫字母形式返回摘要的Base-16編碼的函數(shù)。
2.對于構(gòu)造好的待請求數(shù)據(jù)再進(jìn)行哈希處理,算法與對RequestPayload哈希處理的算法相同
HashedCanonicalRequest = Lowercase(HexEncode(Hash.SHA256(CanonicalRequest)))
3.創(chuàng)建待簽字符串
StringToSign = Algorithm + \n + RequestDateTime + \n + HashedCanonicalRequest
Algorithm簽名算法。算法為HMAC-SHA256。
RequestDateTime請求時(shí)間戳。與請求消息頭Date的值相同,UTC時(shí)間格式為YYYYMMDDTHHMMSSZ。
HashedCanonicalRequest經(jīng)過哈希處理的規(guī)范請求。
4.計(jì)算簽名
將SK(Access Secret Key)和創(chuàng)建的待簽字符串作為加密哈希函數(shù)的輸入,計(jì)算簽名,將二進(jìn)制值轉(zhuǎn)換為十六進(jìn)制表示形式。
signature = HexEncode(HMAC(StringToSign, Access Secret Key))
此處SK是APPKey。
5.添加簽名信息到請求頭
在計(jì)算簽名后,將它添加到Authorization的HTTP消息頭。Authorization消息頭未包含在已簽名消息頭中,主要用于身份驗(yàn)證。
需要注意的是算法與access之前有空格但沒有逗號,但是access與signature之前需要使用逗號隔開。
Authorization: algorithm access=Access key, signature=signature
algorithm: HMAC-SHA256
access:對于appid進(jìn)行base64編碼
signature:計(jì)算簽名數(shù)據(jù)
示例代碼如下:
import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class EncodeSignature { /** * 定義加密方式 * MAC算法可選以下多種算法 * <pre> * HmacMD5 * HmacSHA1 * HmacSHA256 * HmacSHA384 * HmacSHA512 * </pre>**/ private static final String MAC_NAME = "HmacSHA256"; private static final String ENCODING = "UTF-8"; public static String bytesToHexString(byte[] srcArray) { if ((srcArray == null) || (srcArray.length == 0)) { return ""; } StringBuffer sb = new StringBuffer(srcArray.length); for (int i = 0; i < srcArray.length; i++) { String temp = Integer.toHexString(0xFF & srcArray[i]); if (temp.length() < 2) { sb.append(0); } sb.append(temp); } return sb.toString(); } public static String encodeSHA256(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException { if ("".equals(str)) { return str; } MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(str.getBytes("UTF-8")); byte[] hashByte = md.digest(); return bytesToHexString(hashByte); } /** * 使用 HMAC-SHA256 簽名方法對對encryptText進(jìn)行簽名 * @param encryptText 被簽名的字符串 * @param encryptKey 密鑰 * @return * @throws Exception */ public static byte[] HmacSHA256Encrypt(String encryptText, String encryptKey) throws Exception { byte[] data=encryptKey.getBytes(ENCODING); //根據(jù)給定的字節(jié)數(shù)組構(gòu)造一個(gè)密鑰,第二參數(shù)指定一個(gè)密鑰算法的名稱 SecretKey secretKey = new SecretKeySpec(data, MAC_NAME); //生成一個(gè)指定 Mac 算法 的 Mac 對象 Mac mac = Mac.getInstance(MAC_NAME); //用給定密鑰初始化 Mac 對象 mac.init(secretKey); byte[] text = encryptText.getBytes(ENCODING); //完成 Mac 操作 return mac.doFinal(text); } public static void main(String[] args) throws Exception { //1、對RequestBody進(jìn)行SHA-256計(jì)算,并進(jìn)行Base16轉(zhuǎn)碼 String RequestPayload = "{\"userAccount\":\"yuthird\",\"clientType\":5,\"userName\":\"yuthird\",\"userEmail\":\"yuthird@huawei.com\",\"userPhone\":\"13511112222\"}"; System.out.println(encodeSHA256(RequestPayload)); //2、拼接待請求數(shù)據(jù),并將待請求數(shù)據(jù)進(jìn)行SHA-256計(jì)算,并進(jìn)行Base16轉(zhuǎn)碼 String CanonicalRequest = "POST\n/rest/usg/sso/v1/auth/appauth/\ncontent-type:application/json\ndate:20190329T074551Z\n\n" + encodeSHA256(RequestPayload); String HashedCanonicalRequest = encodeSHA256(CanonicalRequest); System.out.println(HashedCanonicalRequest); //3、拼接待簽名字符串,并將待簽名字符串進(jìn)行HMAC-SHA256計(jì)算,并Base16轉(zhuǎn)碼 String StringToSign = "HMAC-SHA256\n20190329T074551Z\n" + HashedCanonicalRequest; String signature = bytesToHexString(HmacSHA256Encrypt(StringToSign,"gHKag2yRtR2bP83x")); System.out.println("signature:" + signature); } }