# 签名机制
# 1. 签名方法
签名时,您需要在项目详情页面查看目前项目的 accessKey 和 accessSecret。其中 accessKey 用于标识访问者身份;accessSecret 用于对称加密时的密钥,应严格保密,不能在空中传播;若泄露,可在项目详情里刷新。
- 签名方法
sign = sign_method(accessSecret, "accessKey{accessKey}timestamp{timestamp}random{randomStr}signMethod{signMethod}").HexToString()
- 算法逻辑
randomStr 和时间戳防重放,timestamp 取当前时间戳,单位秒,10 分钟误差,randomStr 取 uuid,10 分钟内只能使用一次;sign_method 为签名算法;
待加密字符串需按指定顺序拼接;
将字符串和 secret 进行哈希,得到签名字符串,并转为十六进制小写字符串;
# 2. 签名示例
一个用户的连接信息为:
accessKey: "GmXM0L69da381d51" accessSecret: "04d711bd2390ae4f605caff758df90e5" randomStr: "ae1786" signMethod: "hmacsha1" timestamp: "1631585734"
通过签名方法得到的新的签名:
sign = hmacsha1("04d711bd2390ae4f605caff758df90e5", "accessKeyGmXM0L69da381d51timestamp1631585734randomae1786signMethodhmacsha1")
计算得到的签名字符串为:
068baf6ed7a9f2c6df9f5d8f870b5add7460cf8b
请求头参数为:
access_key: GmXM0L69da381d51 sign: 068baf6ed7a9f2c6df9f5d8f870b5add7460cf8b sign_method: hmacsha1 timestamp: 1631585734 random_str: ae1786
# 3. 代码示例
# 3.1 java
package example; import java.security.Timestamp; import java.util.*; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; import javax.xml.bind.annotation.adapters.HexBinaryAdapter; public class SignUtils { private static String accessKey = "GmXM0L69da381d51"; private static String accessSecret = "04d711bd2390ae4f605caff758df90e5"; private static String timestamp = "1631585734"; private static String randomStr = "ae1786"; private static String signMethod = "HmacSHA1"; public static void main(String[] args) throws Exception { String sign = genHmacsha1Sign(accessKey, accessSecret); System.out.println("sign: " + sign); } private static String genHmacsha1Sign(String accessKey, String secret) throws Exception { String plainText = genSignString(accessKey, secret, timestamp, randomStr); byte[] rawBytes = hmacsha1Sign(plainText); return bytes2hex(rawBytes); } private static String genSignString(String accessKey, String secret, String timestamp, String randomStr) { StringBuilder plainText = new StringBuilder(); plainText.append("accessKey").append(accessKey); plainText.append("timestamp").append(timestamp); plainText.append("random").append(randomStr); plainText.append("signMethod").append("hmacsha1"); return plainText.toString(); } private static byte[] hmacsha1Sign(String signString) throws Exception { Mac mac = Mac.getInstance(signMethod); SecretKeySpec keySpec = new SecretKeySpec(accessSecret.getBytes("utf8"), signMethod); mac.init(keySpec); return mac.doFinal(signString.getBytes("utf8")); } private static String bytes2hex(byte[] bytes) { StringBuilder result = new StringBuilder(); for (byte aByte : bytes) { result.append(String.format("%02x", aByte)); } return result.toString(); } }
# 3.2 golang
package main import ( "crypto/hmac" "crypto/md5" "crypto/sha1" "encoding/hex" "errors" "fmt" "hash" ) const ( accessKey = "GmXM0L69da381d51" accessSecret = "04d711bd2390ae4f605caff758df90e5" ) func main() { signMethod := "hmacsha1" timestamp := "1631585734" randomStr := "ae1786" sign, _ := authSign(accessKey, timestamp, randomStr, accessSecret, signMethod) fmt.Println("signature: ", sign) } func authSign(accessKey, timestamp, randomStr, accessSecret, signMethod string) (string, error) { src := "" src = fmt.Sprintf("accessKey%stimestamp%srandom%ssignMethod%s", accessKey, timestamp, randomStr, signMethod) var h hash.Hash switch signMethod { case "hmacsha1": h = hmac.New(sha1.New, []byte(accessSecret)) case "hmacmd5": h = hmac.New(md5.New, []byte(accessSecret)) default: return "", errors.New("invalid sign method") } _, err := h.Write([]byte(src)) if err != nil { return "", err } return hex.EncodeToString(h.Sum(nil)), nil }
# 3.3 python
import hmac,hashlib access_key = "GmXM0L69da381d51" access_secret = "04d711bd2390ae4f605caff758df90e5" timestamp = "1631585734" sign_method = "hmacsha1" random_str = "ae1786" def gen_sign_str(access_key, timestamp, sign_method, random_str): plaintext = 'accessKey{}timestamp{}random{}signMethod{}'.format(access_key, timestamp, random_str, sign_method) return plaintext def sign(access_key, access_secret, timestamp, sign_method, random_str): plaintext = gen_sign_str(access_key, timestamp, sign_method, random_str) return hmac.new(bytes(access_secret, encoding="utf-8"), bytes(plaintext, encoding="utf-8"),hashlib.sha1).hexdigest() if __name__ == '__main__': signature = sign(access_key, access_secret, timestamp, sign_method, random_str) print("sign: ", signature)