智慧服务,成就美好体验 项目咨询

主页 > 服务与支持 > 开发平台 > 服务端API参考 > 附录 signature说明

入门使用

signature说明

更新时间:2019-11-20

1.待请求数据:

CanonicalRequest = HTTPRequestMethod + '\n' + CanonicalURI + '\n' + CanonicalHeaders + '\n' + HexEncode(Hash(RequestPayload))

HTTPRequestMethod:http请求方法

CanonicalURI:URL路径,计算签名时,URI必须以“/”结尾。发送请求时,可以不以“/”结尾。

CanonicalHeaders:由多个请求消息头(目前协商取content-type\date头域)共同组成,CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ...,

其中每个请求消息头(CanonicalHeadersEntry )的格式为Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n‘

说明:

Lowercase表示将所有字符转换为小写字母的函数。

Trimall表示删除值前后的多余空格的函数。

最后一个请求消息头也会携带一个换行符。叠加规范中CanonicalHeaders自身携带的换行符,因此会出现一个空行。

 

请求消息体:

消息体需要做两层转换:HexEncode(Hash(RequestPayload)),其中Hash表示生成消息摘要的函数,当前支持SHA-256算法。

HexEncode表示以小写字母形式返回摘要的Base-16编码的函数。

 

2.对于构造好的待请求数据再进行哈希处理,算法与对RequestPayload哈希处理的算法相同

HashedCanonicalRequest = Lowercase(HexEncode(Hash.SHA256(CanonicalRequest)))

 

3.创建待签字符串

StringToSign = Algorithm + \n + RequestDateTime + \n + HashedCanonicalRequest

Algorithm签名算法。算法为HMAC-SHA256。

RequestDateTime请求时间戳。与请求消息头Date的值相同,UTC时间格式为YYYYMMDDTHHMMSSZ。

HashedCanonicalRequest经过哈希处理的规范请求。

 

4.计算签名

将SK(Access Secret Key)和创建的待签字符串作为加密哈希函数的输入,计算签名,将二进制值转换为十六进制表示形式。

signature = HexEncode(HMAC(StringToSign, Access Secret Key))

此处SK是APPKey。

 

5.添加签名信息到请求头

在计算签名后,将它添加到Authorization的HTTP消息头。Authorization消息头未包含在已签名消息头中,主要用于身份验证。

需要注意的是算法与access之前有空格但没有逗号,但是access与signature之前需要使用逗号隔开。

Authorization: algorithm access=Access key, signature=signature

algorithm: HMAC-SHA256

access:对于appid进行base64编码

signature:计算签名数据

 

示例代码如下:

注意:保证代码中RequestPayload与实际调用接口的请求body完全一致;保证CanonicalRequest中date与实际调用接口Header中的date完全一致。
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进行签名
     * @param encryptText 被签名的字符串
     * @param encryptKey  密钥
     * @return
     * @throws Exception
     */
    public static byte[] HmacSHA256Encrypt(String encryptText, String encryptKey) throws Exception
    {
        byte[] data=encryptKey.getBytes(ENCODING);
        //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
        SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
        //生成一个指定 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进行SHA-256计算,并进行Base16转码
        String RequestPayload = "{\"userAccount\":\"yuthird\",\"clientType\":5,\"userName\":\"yuthird\",\"userEmail\":\"yuthird@huawei.com\",\"userPhone\":\"13511112222\"}";
        System.out.println(encodeSHA256(RequestPayload));

        //2、拼接待请求数据,并将待请求数据进行SHA-256计算,并进行Base16转码
        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、拼接待签名字符串,并将待签名字符串进行HMAC-SHA256计算,并Base16转码
        String StringToSign = "HMAC-SHA256\n20190329T074551Z\n" + HashedCanonicalRequest;
        String signature = bytesToHexString(HmacSHA256Encrypt(StringToSign,"gHKag2yRtR2bP83x"));
        System.out.println("signature:" + signature);
    }
}