产品概述
产品功能
应用场景
以下文档说明了签名方法 v3 的签名过程,但仅在您编写自己的代码来调用腾讯云 API 时才有用。我们推荐您使用 腾讯云 API Explorer 和 腾讯云命令行工具(TCCLI) 等开发者工具,从而无需学习如何对 API 请求进行签名。
腾讯云 API 会对每个请求进行身份验证,用户需要使用安全凭证,经过特定的步骤对请求进行签名(Signature),每个请求都需要在公共参数中指定该签名结果并以指定的方式和格式发送请求。
签名通过以下方式帮助保护请求:
验证请求者的身份
签名确保请求是由持有有效访问密钥的人发送的。请参阅控制台 云 API 密钥 页面获取密钥相关信息。
保护传输中的数据
为了防止请求在传输过程中被篡改,腾讯云 API 会使用请求参数来计算请求的哈希值,并将生成的哈希值加密后作为请求的一部分,发送到腾讯云 API 服务器。服务器会使用收到的请求参数以同样的过程计算哈希值,并验证请求中的哈希值。如果请求被篡改,将导致哈希值不一致,腾讯云 API 将拒绝本次请求。
签名方法 v3 (TC3-HMAC-SHA256)功能上覆盖了以前的签名方法 v1,而且更安全,支持更大的请求,支持 JSON 格式,POST 请求支持传空数组和空字符串,性能有一定提升,推荐使用该签名方法计算签名。
首次接触,建议使用 API Explorer 中的“签名串生成”功能,选择签名版本为“API 3.0 签名 v3”,可以对生成签名过程进行验证,也可直接生成 SDK 代码。推荐使用腾讯云 API 配套的 7 种常见的编程语言 SDK,已经封装了签名和请求过程,均已开源,支持 Python、Java、PHP、Go、NodeJS、.NET、C++。
本文使用的安全凭证为密钥,密钥包括 SecretId 和 SecretKey。每个用户最多可以拥有两对密钥。
申请安全凭证的具体步骤如下:
云 API 支持 GET 和 POST 请求。对于GET方法,只支持 Content-Type: application/x-www-form-urlencoded 协议格式。对于POST方法,目前支持 Content-Type: application/json 以及 Content-Type: multipart/form-data 两种协议格式,json 格式绝大多数接口均支持,multipart 格式只有特定接口支持,此时该接口不能使用 json 格式调用,参考具体业务接口文档说明。推荐使用 POST 请求,因为两者的结果并无差异,但 GET 请求只支持 32 KB 以内的请求包。
下面以云服务器查询广州区实例列表作为例子,分步骤介绍签名的计算过程。我们选择该接口是因为:
在示例中,不论公共参数或者接口的参数,我们尽量选择容易犯错的情况。在实际调用接口时,请根据实际情况来,每个接口的参数并不相同,不要照抄这个例子的参数和值。此外,这里只展示了部分公共参数和接口输入参数,用户可以根据实际需要添加其他参数,例如 Language 和 Token 公共参数(在 HTTP 头部设置,添加 X-TC- 前缀)。
假设用户的 SecretId 和 SecretKey 分别是:AKID******************************** 和 ********************************。用户想查看广州区云服务器名为“未命名”的主机状态,只返回一条数据。则请求可能为:
curl -X POST https://cvm.tencentcloudapi.com \
-H "Authorization: TC3-HMAC-SHA256 Credential=AKID********************************/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host;x-tc-action, Signature=10b1a37a7301a02ca19a647ad722d5e43b4b3cff309d421d85b46093f6ab6c4f" \
-H "Content-Type: application/json; charset=utf-8" \
-H "Host: cvm.tencentcloudapi.com" \
-H "X-TC-Action: DescribeInstances" \
-H "X-TC-Timestamp: 1551113065" \
-H "X-TC-Version: 2017-03-12" \
-H "X-TC-Region: ap-guangzhou" \
-d '{"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}'
下面详细解释签名计算过程。
按如下伪代码格式拼接规范请求串(CanonicalRequest):
CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HashedRequestPayload
| 字段名称 | 解释 |
|---|---|
| HTTPRequestMethod | HTTP 请求方法(GET、POST )。此示例取值为 POST。 |
| CanonicalURI | URI 参数,API 3.0 固定为正斜杠(/)。 |
| CanonicalQueryString | 发起 HTTP 请求 URL 中的查询字符串,对于 POST 请求,固定为空字符串"",对于 GET 请求,则为 URL 中问号(?)后面的字符串内容,例如:Limit=10&Offset=0。 注意:CanonicalQueryString 需要参考 RFC3986 进行 URLEncode 编码(特殊字符编码后需大写字母),字符集 UTF-8。推荐使用编程语言标准库进行编码。 |
| CanonicalHeaders | 参与签名的头部信息,至少包含 host 和 content-type 两个头部,也可加入其他头部参与签名以提高自身请求的唯一性和安全性,此示例额外增加了接口名头部。 拼接规则:
content-type:application/json; charset=utf-8\nhost:cvm.tencentcloudapi.com\nx-tc-action:describeinstances\n。注意:content-type 必须和实际发送的相符合,有些编程语言网络库即使未指定也会自动添加 charset 值,如果签名时和发送时不一致,服务器会返回签名校验失败。 |
| SignedHeaders | 参与签名的头部信息,说明此次请求有哪些头部参与了签名,和 CanonicalHeaders 包含的头部内容是一一对应的。content-type 和 host 为必选头部。 拼接规则:
|
| HashedRequestPayload | 请求正文(payload,即 body,此示例为 {"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]})的哈希值,计算伪代码为 Lowercase(HexEncode(Hash.SHA256(RequestPayload))),即对 HTTP 请求正文做 SHA256 哈希,然后十六进制编码,最后编码串转换成小写字母。对于 GET 请求,RequestPayload 固定为空字符串。此示例计算结果是 35e9c5b0e3ae67532d3c9f17ead6c90222632e5b1ff7f6e89887f1398934f064。 |
根据以上规则,示例中得到的规范请求串如下:
POST
/
content-type:application/json; charset=utf-8
host:cvm.tencentcloudapi.com
x-tc-action:describeinstances
content-type;host;x-tc-action
35e9c5b0e3ae67532d3c9f17ead6c90222632e5b1ff7f6e89887f1398934f064
按如下格式拼接待签名字符串:
StringToSign =
Algorithm + "\n" +
RequestTimestamp + "\n" +
CredentialScope + "\n" +
HashedCanonicalRequest
| 字段名称 | 解释 |
|---|---|
| Algorithm | 签名算法,目前固定为 TC3-HMAC-SHA256。 |
| RequestTimestamp | 请求时间戳,即请求头部的公共参数 X-TC-Timestamp 取值,取当前时间 UNIX 时间戳,精确到秒。此示例取值为 1551113065。 |
| CredentialScope | 凭证范围,格式为 Date/service/tc3_request,包含日期、所请求的服务和终止字符串(tc3_request)。Date 为 UTC 标准时间的日期,取值需要和公共参数 X-TC-Timestamp 换算的 UTC 标准时间日期一致;service 为产品名,必须与调用的产品域名一致。此示例计算结果是 2019-02-25/cvm/tc3_request。 |
| HashedCanonicalRequest | 前述步骤拼接所得规范请求串的哈希值,计算伪代码为 Lowercase(HexEncode(Hash.SHA256(CanonicalRequest)))。此示例计算结果是 7019a55be8395899b900fb5564e4200d984910f34794a27cb3fb7d10ff6a1e84。 |
注意:
- Date 必须从时间戳 X-TC-Timestamp 计算得到,且时区为 UTC+0。如果加入系统本地时区信息,例如东八区,将导致白天和晚上调用成功,但是凌晨时调用必定失败。假设时间戳为 1551113065,在东八区的时间是 2019-02-26 00:44:25,但是计算得到的 Date 取 UTC+0 的日期应为 2019-02-25,而不是 2019-02-26。
- Timestamp 必须是当前系统时间,且需确保系统时间和标准时间是同步的,如果相差超过五分钟则必定失败。如果长时间不和标准时间同步,可能运行一段时间后,请求失败,返回签名过期错误。
根据以上规则,示例中得到的待签名字符串如下:
TC3-HMAC-SHA256
1551113065
2019-02-25/cvm/tc3_request
7019a55be8395899b900fb5564e4200d984910f34794a27cb3fb7d10ff6a1e84
1)计算派生签名密钥,伪代码如下:
SecretKey = "********************************"
SecretDate = HMAC_SHA256("TC3" + SecretKey, Date)
SecretService = HMAC_SHA256(SecretDate, Service)
SecretSigning = HMAC_SHA256(SecretService, "tc3_request")
派生出的密钥 SecretDate、SecretService 和 SecretSigning 是二进制的数据,可能包含不可打印字符,将其转为十六进制字符串打印的输出分别为:da98fb70dcf6b112dc21038d1eeeb3a95c74b4dcb12c1131f864f6066bd02be0,8d70cbefb03939f929db64d32dc2ba89b1095620119fe3e050e2b18c5bd2752f,b596b923aad85185e2d1f6659d2a062e0a86731226e021e61bfe06f7ed05f5af。
请注意,不同的编程语言,HMAC 库函数中参数顺序可能不一样,请以实际情况为准。此处的伪代码密钥参数 key 在前,消息参数 data 在后。通常标准库函数会提供二进制格式的返回值,也可能会提供打印友好的十六进制格式的返回值,此处使用的是二进制格式。
| 字段名称 | 解释 |
|---|---|
| SecretKey | 原始的 SecretKey,即 ********************************。 |
| Date | 即 Credential 中的 Date 字段信息。此示例取值为 2019-02-25。 |
| Service | 即 Credential 中的 Service 字段信息。此示例取值为 cvm。 |
2)计算签名,伪代码如下:
Signature = HexEncode(HMAC_SHA256(SecretSigning, StringToSign))
此示例计算结果是 10b1a37a7301a02ca19a647ad722d5e43b4b3cff309d421d85b46093f6ab6c4f。
按如下格式拼接 Authorization:
Authorization =
Algorithm + ' ' +
'Credential=' + SecretId + '/' + CredentialScope + ', ' +
'SignedHeaders=' + SignedHeaders + ', ' +
'Signature=' + Signature
| 字段名称 | 解释 |
|---|---|
| Algorithm | 签名方法,固定为 TC3-HMAC-SHA256。 |
| SecretId | 密钥对中的 SecretId,即 AKID********************************。 |
| CredentialScope | 见上文,凭证范围。此示例计算结果是 2019-02-25/cvm/tc3_request。 |
| SignedHeaders | 见上文,参与签名的头部信息。此示例取值为 content-type;host;x-tc-action。 |
| Signature | 签名值。此示例计算结果是 10b1a37a7301a02ca19a647ad722d5e43b4b3cff309d421d85b46093f6ab6c4f。 |
根据以上规则,示例中得到的值为:
TC3-HMAC-SHA256 Credential=AKID********************************/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host;x-tc-action, Signature=10b1a37a7301a02ca19a647ad722d5e43b4b3cff309d421d85b46093f6ab6c4f
最终完整的调用信息如下:
POST https://cvm.tencentcloudapi.com/
Authorization: TC3-HMAC-SHA256 Credential=AKID********************************/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host;x-tc-action, Signature=10b1a37a7301a02ca19a647ad722d5e43b4b3cff309d421d85b46093f6ab6c4f
Content-Type: application/json; charset=utf-8
Host: cvm.tencentcloudapi.com
X-TC-Action: DescribeInstances
X-TC-Version: 2017-03-12
X-TC-Timestamp: 1551113065
X-TC-Region: ap-guangzhou
{"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}
<blockquote class="d-mod-notice">
<div class="d-mod-title d-notice-title">
<i class="d-icon-notice"></i>注意:
</div>
<p><br>请求发送时的 HTTP 头部(Header)和请求体(Payload)必须和签名计算过程中的内容完全一致,否则会返回签名不一致错误。可以通过打印实际请求内容,网络抓包等方式对比排查。</p>
</blockquote>
<h2 id=".E7.AD.BE.E5.90.8D.E6.BC.94.E7.A4.BA">签名演示</h2><p>在实际调用 API 3.0 时,推荐使用配套的腾讯云 SDK 3.0 ,SDK 封装了签名的过程,开发时只关注产品提供的具体接口即可。当前支持的编程语言有:</p>
下面提供了不同产品的生成签名 demo,您可以找到对应的产品参考签名的生成:
为了更清楚地解释签名过程,下面以实际编程语言为例,将上述的签名过程完整实现。请求的域名、调用的接口和参数的取值都以上述签名过程为准,代码只为解释签名过程,并不具备通用性,实际开发请尽量使用 SDK。
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class TencentCloudAPITC3Demo {
private final static Charset UTF8 = StandardCharsets.UTF_8;
// 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID****
private final static String SECRET_ID = System.getenv("TENCENTCLOUD_SECRET_ID");
// 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ****
private final static String SECRET_KEY = System.getenv("TENCENTCLOUD_SECRET_KEY");
private final static String CT_JSON = "application/json; charset=utf-8";
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">byte</span>[] hmac256(<span class="hljs-keyword">byte</span>[] key, String msg) <span class="hljs-keyword">throws</span> Exception {
Mac mac = Mac.getInstance(<span class="hljs-string">"HmacSHA256"</span>);
SecretKeySpec secretKeySpec = <span class="hljs-keyword">new</span> SecretKeySpec(key, mac.getAlgorithm());
mac.init(secretKeySpec);
<span class="hljs-keyword">return</span> mac.doFinal(msg.getBytes(UTF8));
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">sha256Hex</span><span class="hljs-params">(String s)</span> <span class="hljs-keyword">throws</span> Exception </span>{
MessageDigest md = MessageDigest.getInstance(<span class="hljs-string">"SHA-256"</span>);
<span class="hljs-keyword">byte</span>[] d = md.digest(s.getBytes(UTF8));
<span class="hljs-keyword">return</span> DatatypeConverter.printHexBinary(d).toLowerCase();
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>{
String service = <span class="hljs-string">"cvm"</span>;
String host = <span class="hljs-string">"cvm.tencentcloudapi.com"</span>;
String region = <span class="hljs-string">"ap-guangzhou"</span>;
String action = <span class="hljs-string">"DescribeInstances"</span>;
String version = <span class="hljs-string">"2017-03-12"</span>;
String algorithm = <span class="hljs-string">"TC3-HMAC-SHA256"</span>;
String timestamp = <span class="hljs-string">"1551113065"</span>;
<span class="hljs-comment">//String timestamp = String.valueOf(System.currentTimeMillis() / 1000);</span>
SimpleDateFormat sdf = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">"yyyy-MM-dd"</span>);
<span class="hljs-comment">// 注意时区,否则容易出错</span>
sdf.setTimeZone(TimeZone.getTimeZone(<span class="hljs-string">"UTC"</span>));
String date = sdf.format(<span class="hljs-keyword">new</span> Date(Long.valueOf(timestamp + <span class="hljs-string">"000"</span>)));
<span class="hljs-comment">// ************* 步骤 1:拼接规范请求串 *************</span>
String httpRequestMethod = <span class="hljs-string">"POST"</span>;
String canonicalUri = <span class="hljs-string">"/"</span>;
String canonicalQueryString = <span class="hljs-string">""</span>;
String canonicalHeaders = <span class="hljs-string">"content-type:application/json; charset=utf-8\n"</span>
+ <span class="hljs-string">"host:"</span> + host + <span class="hljs-string">"\n"</span> + <span class="hljs-string">"x-tc-action:"</span> + action.toLowerCase() + <span class="hljs-string">"\n"</span>;
String signedHeaders = <span class="hljs-string">"content-type;host;x-tc-action"</span>;
String payload = <span class="hljs-string">"{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}"</span>;
String hashedRequestPayload = sha256Hex(payload);
String canonicalRequest = httpRequestMethod + <span class="hljs-string">"\n"</span> + canonicalUri + <span class="hljs-string">"\n"</span> + canonicalQueryString + <span class="hljs-string">"\n"</span>
+ canonicalHeaders + <span class="hljs-string">"\n"</span> + signedHeaders + <span class="hljs-string">"\n"</span> + hashedRequestPayload;
System.out.println(canonicalRequest);
<span class="hljs-comment">// ************* 步骤 2:拼接待签名字符串 *************</span>
String credentialScope = date + <span class="hljs-string">"/"</span> + service + <span class="hljs-string">"/"</span> + <span class="hljs-string">"tc3_request"</span>;
String hashedCanonicalRequest = sha256Hex(canonicalRequest);
String stringToSign = algorithm + <span class="hljs-string">"\n"</span> + timestamp + <span class="hljs-string">"\n"</span> + credentialScope + <span class="hljs-string">"\n"</span> + hashedCanonicalRequest;
System.out.println(stringToSign);
<span class="hljs-comment">// ************* 步骤 3:计算签名 *************</span>
<span class="hljs-keyword">byte</span>[] secretDate = hmac256((<span class="hljs-string">"TC3"</span> + SECRET_KEY).getBytes(UTF8), date);
<span class="hljs-keyword">byte</span>[] secretService = hmac256(secretDate, service);
<span class="hljs-keyword">byte</span>[] secretSigning = hmac256(secretService, <span class="hljs-string">"tc3_request"</span>);
String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
System.out.println(signature);
<span class="hljs-comment">// ************* 步骤 4:拼接 Authorization *************</span>
String authorization = algorithm + <span class="hljs-string">" "</span> + <span class="hljs-string">"Credential="</span> + SECRET_ID + <span class="hljs-string">"/"</span> + credentialScope + <span class="hljs-string">", "</span>
+ <span class="hljs-string">"SignedHeaders="</span> + signedHeaders + <span class="hljs-string">", "</span> + <span class="hljs-string">"Signature="</span> + signature;
System.out.println(authorization);
TreeMap<String, String> headers = <span class="hljs-keyword">new</span> TreeMap<String, String>();
headers.put(<span class="hljs-string">"Authorization"</span>, authorization);
headers.put(<span class="hljs-string">"Content-Type"</span>, CT_JSON);
headers.put(<span class="hljs-string">"Host"</span>, host);
headers.put(<span class="hljs-string">"X-TC-Action"</span>, action);
headers.put(<span class="hljs-string">"X-TC-Timestamp"</span>, timestamp);
headers.put(<span class="hljs-string">"X-TC-Version"</span>, version);
headers.put(<span class="hljs-string">"X-TC-Region"</span>, region);
StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder();
sb.append(<span class="hljs-string">"curl -X POST https://"</span>).append(host)
.append(<span class="hljs-string">" -H \"Authorization: "</span>).append(authorization).append(<span class="hljs-string">"\""</span>)
.append(<span class="hljs-string">" -H \"Content-Type: application/json; charset=utf-8\""</span>)
.append(<span class="hljs-string">" -H \"Host: "</span>).append(host).append(<span class="hljs-string">"\""</span>)
.append(<span class="hljs-string">" -H \"X-TC-Action: "</span>).append(action).append(<span class="hljs-string">"\""</span>)
.append(<span class="hljs-string">" -H \"X-TC-Timestamp: "</span>).append(timestamp).append(<span class="hljs-string">"\""</span>)
.append(<span class="hljs-string">" -H \"X-TC-Version: "</span>).append(version).append(<span class="hljs-string">"\""</span>)
.append(<span class="hljs-string">" -H \"X-TC-Region: "</span>).append(region).append(<span class="hljs-string">"\""</span>)
.append(<span class="hljs-string">" -d '"</span>).append(payload).append(<span class="hljs-string">"'"</span>);
System.out.println(sb.toString());
}
}
# -*- coding: utf-8 -*-
import hashlib, hmac, json, os, sys, time
from datetime import datetime
# 密钥参数
# 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID****
secret_id = os.environ.get("TENCENTCLOUD_SECRET_ID")
# 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ****
secret_key = os.environ.get("TENCENTCLOUD_SECRET_KEY")
service = "cvm"
host = "cvm.tencentcloudapi.com"
endpoint = "https://" + host
region = "ap-guangzhou"
action = "DescribeInstances"
version = "2017-03-12"
algorithm = "TC3-HMAC-SHA256"
#timestamp = int(time.time())
timestamp = 1551113065
date = datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d")
params = {"Limit": 1, "Filters": [{"Values": [u"未命名"], "Name": "instance-name"}]}
# * 步骤 1:拼接规范请求串 *
http_request_method = "POST"
canonical_uri = "/"
canonical_querystring = ""
ct = "application/json; charset=utf-8"
payload = json.dumps(params)
canonical_headers = "content-type:%s\nhost:%s\nx-tc-action:%s\n" % (ct, host, action.lower())
signed_headers = "content-type;host;x-tc-action"
hashed_request_payload = hashlib.sha256(payload.encode("utf-8")).hexdigest()
canonical_request = (http_request_method + "\n" +
canonical_uri + "\n" +
canonical_querystring + "\n" +
canonical_headers + "\n" +
signed_headers + "\n" +
hashed_request_payload)
print(canonical_request)
# * 步骤 2:拼接待签名字符串 *
credential_scope = date + "/" + service + "/" + "tc3_request"
hashed_canonical_request = hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
string_to_sign = (algorithm + "\n" +
str(timestamp) + "\n" +
credential_scope + "\n" +
hashed_canonical_request)
print(string_to_sign)
# * 步骤 3:计算签名 *
# 计算签名摘要函数
def sign(key, msg):
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
secret_date = sign(("TC3" + secret_key).encode("utf-8"), date)
secret_service = sign(secret_date, service)
secret_signing = sign(secret_service, "tc3_request")
signature = hmac.new(secret_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
print(signature)
# * 步骤 4:拼接 Authorization *
authorization = (algorithm + " " +
"Credential=" + secret_id + "/" + credential_scope + ", " +
"SignedHeaders=" + signed_headers + ", " +
"Signature=" + signature)
print(authorization)
print('curl -X POST ' + endpoint
+ <span class="hljs-string">' -H "Authorization: '</span> + authorization + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "Content-Type: application/json; charset=utf-8"'</span>
+ <span class="hljs-string">' -H "Host: '</span> + host + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "X-TC-Action: '</span> + action + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "X-TC-Timestamp: '</span> + <span class="hljs-built_in">str</span>(timestamp) + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "X-TC-Version: '</span> + version + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "X-TC-Region: '</span> + region + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">" -d '"</span> + payload + <span class="hljs-string">"'"</span>)
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"os"
"strings"
"time"
)
func sha256hex(s string) string {
b := sha256.Sum256([]byte(s))
return hex.EncodeToString(b[:])
}
func hmacsha256(s, key string) string {
hashed := hmac.New(sha256.New, []byte(key))
hashed.Write([]byte(s))
return string(hashed.Sum(nil))
}
func main() {
// 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID****
secretId := os.Getenv("TENCENTCLOUD_SECRET_ID")
// 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ****
secretKey := os.Getenv("TENCENTCLOUD_SECRET_KEY")
host := "cvm.tencentcloudapi.com"
algorithm := "TC3-HMAC-SHA256"
service := "cvm"
version := "2017-03-12"
action := "DescribeInstances"
region := "ap-guangzhou"
//var timestamp int64 = time.Now().Unix()
var timestamp int64 = 1551113065
<span class="hljs-comment">// step 1: build canonical request string</span>
httpRequestMethod := <span class="hljs-string">"POST"</span>
canonicalURI := <span class="hljs-string">"/"</span>
canonicalQueryString := <span class="hljs-string">""</span>
canonicalHeaders := fmt.Sprintf(<span class="hljs-string">"content-type:%s\nhost:%s\nx-tc-action:%s\n"</span>,
<span class="hljs-string">"application/json; charset=utf-8"</span>, host, strings.ToLower(action))
signedHeaders := <span class="hljs-string">"content-type;host;x-tc-action"</span>
payload := <span class="hljs-string">`{"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}`</span>
hashedRequestPayload := sha256hex(payload)
canonicalRequest := fmt.Sprintf(<span class="hljs-string">"%s\n%s\n%s\n%s\n%s\n%s"</span>,
httpRequestMethod,
canonicalURI,
canonicalQueryString,
canonicalHeaders,
signedHeaders,
hashedRequestPayload)
fmt.Println(canonicalRequest)
<span class="hljs-comment">// step 2: build string to sign</span>
date := time.Unix(timestamp, <span class="hljs-number">0</span>).UTC().Format(<span class="hljs-string">"2006-01-02"</span>)
credentialScope := fmt.Sprintf(<span class="hljs-string">"%s/%s/tc3_request"</span>, date, service)
hashedCanonicalRequest := sha256hex(canonicalRequest)
string2sign := fmt.Sprintf(<span class="hljs-string">"%s\n%d\n%s\n%s"</span>,
algorithm,
timestamp,
credentialScope,
hashedCanonicalRequest)
fmt.Println(string2sign)
<span class="hljs-comment">// step 3: sign string</span>
secretDate := hmacsha256(date, <span class="hljs-string">"TC3"</span>+secretKey)
secretService := hmacsha256(service, secretDate)
secretSigning := hmacsha256(<span class="hljs-string">"tc3_request"</span>, secretService)
signature := hex.EncodeToString([]<span class="hljs-keyword">byte</span>(hmacsha256(string2sign, secretSigning)))
fmt.Println(signature)
<span class="hljs-comment">// step 4: build authorization</span>
authorization := fmt.Sprintf(<span class="hljs-string">"%s Credential=%s/%s, SignedHeaders=%s, Signature=%s"</span>,
algorithm,
secretId,
credentialScope,
signedHeaders,
signature)
fmt.Println(authorization)
curl := fmt.Sprintf(<span class="hljs-string">`curl -X POST https://%s\
-H "Authorization: %s"
-H "Content-Type: application/json; charset=utf-8"
-H "Host: %s" -H "X-TC-Action: %s"
-H "X-TC-Timestamp: %d"
-H "X-TC-Version: %s"
-H "X-TC-Region: %s"
-d '%s'`, host, authorization, host, action, timestamp, version, region, payload)
fmt.Println(curl)
}
<?php
// 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID********************************
$secretId = getenv("TENCENTCLOUD_SECRET_ID");
// 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ********************************
$secretKey = getenv("TENCENTCLOUD_SECRET_KEY");
$host = "cvm.tencentcloudapi.com";
$service = "cvm";
$version = "2017-03-12";
$action = "DescribeInstances";
$region = "ap-guangzhou";
// $timestamp = time();
$timestamp = 1551113065;
$algorithm = "TC3-HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = "POST";
$canonicalUri = "/";
$canonicalQueryString = "";
$canonicalHeaders = implode("\n", [
"content-type:application/json; charset=utf-8",
"host:".$host,
"x-tc-action:".strtolower($action),
""
]);
$signedHeaders = implode(";", [
"content-type",
"host",
"x-tc-action",
]);
$payload = '{"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}';
$hashedRequestPayload = hash("SHA256", $payload);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
echo $canonicalRequest.PHP_EOL;
// step 2: build string to sign
$date = gmdate("Y-m-d", $timestamp);
$credentialScope = $date."/".$service."/tc3_request";
$hashedCanonicalRequest = hash("SHA256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$timestamp."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
echo $stringToSign.PHP_EOL;
// step 3: sign string
$secretDate = hash_hmac("SHA256", $date, "TC3".$secretKey, true);
$secretService = hash_hmac("SHA256", $service, $secretDate, true);
$secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true);
$signature = hash_hmac("SHA256", $stringToSign, $secretSigning);
echo $signature.PHP_EOL;
// step 4: build authorization
$authorization = $algorithm
." Credential=".$secretId."/".$credentialScope
.", SignedHeaders=".$signedHeaders.", Signature=".$signature;
echo $authorization.PHP_EOL;
$curl = "curl -X POST https://".$host
.' -H "Authorization: '.$authorization.'"'
.' -H "Content-Type: application/json; charset=utf-8"'
.' -H "Host: '.$host.'"'
.' -H "X-TC-Action: '.$action.'"'
.' -H "X-TC-Timestamp: '.$timestamp.'"'
.' -H "X-TC-Version: '.$version.'"'
.' -H "X-TC-Region: '.$region.'"'
." -d '".$payload."'";
echo $curl.PHP_EOL;
# -*- coding: UTF-8 -*-
# require ruby>=2.3.0
require 'digest'
require 'json'
require 'time'
require 'openssl'
# 密钥参数
# 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID****
secret_id = ENV["TENCENTCLOUD_SECRET_ID"]
# 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ****
secret_key = ENV["TENCENTCLOUD_SECRET_KEY"]
service = 'cvm'
host = 'cvm.tencentcloudapi.com'
endpoint = 'https://' + host
region = 'ap-guangzhou'
action = 'DescribeInstances'
version = '2017-03-12'
algorithm = 'TC3-HMAC-SHA256'
# timestamp = Time.now.to_i
timestamp = 1551113065
date = Time.at(timestamp).utc.strftime('%Y-%m-%d')
# * 步骤 1:拼接规范请求串 *
http_request_method = 'POST'
canonical_uri = '/'
canonical_querystring = ''
canonical_headers = "content-type:application/json; charset=utf-8\nhost:#{host}\nx-tc-action:#{action.downcase}\n"
signed_headers = 'content-type;host;x-tc-action'
# params = { 'Limit' => 1, 'Filters' => [{ 'Name' => 'instance-name', 'Values' => ['未命名'] }] }
# payload = JSON.generate(params, { 'ascii_only' => true, 'space' => ' ' })
# json will generate in random order, to get specified result in example, we hard-code it here.
payload = '{"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}'
hashed_request_payload = Digest::SHA256.hexdigest(payload)
canonical_request = [
http_request_method,
canonical_uri,
canonical_querystring,
canonical_headers,
signed_headers,
hashed_request_payload,
].join("\n")
puts canonical_request
# * 步骤 2:拼接待签名字符串 *
credential_scope = date + '/' + service + '/' + 'tc3_request'
hashed_request_payload = Digest::SHA256.hexdigest(canonical_request)
string_to_sign = [
algorithm,
timestamp.to_s,
credential_scope,
hashed_request_payload,
].join("\n")
puts string_to_sign
# * 步骤 3:计算签名 *
digest = OpenSSL::Digest.new('sha256')
secret_date = OpenSSL::HMAC.digest(digest, 'TC3' + secret_key, date)
secret_service = OpenSSL::HMAC.digest(digest, secret_date, service)
secret_signing = OpenSSL::HMAC.digest(digest, secret_service, 'tc3_request')
signature = OpenSSL::HMAC.hexdigest(digest, secret_signing, string_to_sign)
puts signature
# * 步骤 4:拼接 Authorization *
authorization = "#{algorithm} Credential=#{secret_id}/#{credential_scope}, SignedHeaders=#{signed_headers}, Signature=#{signature}"
puts authorization
puts 'curl -X POST ' + endpoint \
+ <span class="hljs-string">' -H "Authorization: '</span> + authorization + <span class="hljs-string">'"'</span> \
+ <span class="hljs-string">' -H "Content-Type: application/json; charset=utf-8"'</span> \
+ <span class="hljs-string">' -H "Host: '</span> + host + <span class="hljs-string">'"'</span> \
+ <span class="hljs-string">' -H "X-TC-Action: '</span> + action + <span class="hljs-string">'"'</span> \
+ <span class="hljs-string">' -H "X-TC-Timestamp: '</span> + timestamp.to_s + <span class="hljs-string">'"'</span> \
+ <span class="hljs-string">' -H "X-TC-Version: '</span> + version + <span class="hljs-string">'"'</span> \
+ <span class="hljs-string">' -H "X-TC-Region: '</span> + region + <span class="hljs-string">'"'</span> \
+ <span class="hljs-string">" -d '"</span> + payload + <span class="hljs-string">"'"</span>
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
public class Application
{
public static string SHA256Hex(string s)
{
using (SHA256 algo = SHA256.Create())
{
byte[] hashbytes = algo.ComputeHash(Encoding.UTF8.GetBytes(s));
StringBuilder builder = new StringBuilder();
for (int i = 0; i < hashbytes.Length; ++i)
{
builder.Append(hashbytes[i].ToString("x2"));
}
return builder.ToString();
}
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-built_in">byte</span>[] <span class="hljs-title">HmacSHA256</span>(<span class="hljs-params"><span class="hljs-built_in">byte</span>[] key, <span class="hljs-built_in">byte</span>[] msg</span>)</span>
{
<span class="hljs-keyword">using</span> (HMACSHA256 mac = <span class="hljs-keyword">new</span> HMACSHA256(key))
{
<span class="hljs-keyword">return</span> mac.ComputeHash(msg);
}
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Dictionary<String, String> <span class="hljs-title">BuildHeaders</span>(<span class="hljs-params"><span class="hljs-built_in">string</span> secretid,
<span class="hljs-built_in">string</span> secretkey, <span class="hljs-built_in">string</span> service, <span class="hljs-built_in">string</span> endpoint, <span class="hljs-built_in">string</span> region,
<span class="hljs-built_in">string</span> action, <span class="hljs-built_in">string</span> version, DateTime date, <span class="hljs-built_in">string</span> requestPayload</span>)</span>
{
<span class="hljs-built_in">string</span> datestr = date.ToString(<span class="hljs-string">"yyyy-MM-dd"</span>);
DateTime startTime = <span class="hljs-keyword">new</span> DateTime(<span class="hljs-number">1970</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, DateTimeKind.Utc);
<span class="hljs-built_in">long</span> requestTimestamp = (<span class="hljs-built_in">long</span>)Math.Round((date - startTime).TotalMilliseconds, MidpointRounding.AwayFromZero) / <span class="hljs-number">1000</span>;
<span class="hljs-comment">// ************* 步骤 1:拼接规范请求串 *************</span>
<span class="hljs-built_in">string</span> algorithm = <span class="hljs-string">"TC3-HMAC-SHA256"</span>;
<span class="hljs-built_in">string</span> httpRequestMethod = <span class="hljs-string">"POST"</span>;
<span class="hljs-built_in">string</span> canonicalUri = <span class="hljs-string">"/"</span>;
<span class="hljs-built_in">string</span> canonicalQueryString = <span class="hljs-string">""</span>;
<span class="hljs-built_in">string</span> contentType = <span class="hljs-string">"application/json"</span>;
<span class="hljs-built_in">string</span> canonicalHeaders = <span class="hljs-string">"content-type:"</span> + contentType + <span class="hljs-string">"; charset=utf-8\n"</span>
+ <span class="hljs-string">"host:"</span> + endpoint + <span class="hljs-string">"\n"</span>
+ <span class="hljs-string">"x-tc-action:"</span> + action.ToLower() + <span class="hljs-string">"\n"</span>;
<span class="hljs-built_in">string</span> signedHeaders = <span class="hljs-string">"content-type;host;x-tc-action"</span>;
<span class="hljs-built_in">string</span> hashedRequestPayload = SHA256Hex(requestPayload);
<span class="hljs-built_in">string</span> canonicalRequest = httpRequestMethod + <span class="hljs-string">"\n"</span>
+ canonicalUri + <span class="hljs-string">"\n"</span>
+ canonicalQueryString + <span class="hljs-string">"\n"</span>
+ canonicalHeaders + <span class="hljs-string">"\n"</span>
+ signedHeaders + <span class="hljs-string">"\n"</span>
+ hashedRequestPayload;
Console.WriteLine(canonicalRequest);
<span class="hljs-comment">// ************* 步骤 2:拼接待签名字符串 *************</span>
<span class="hljs-built_in">string</span> credentialScope = datestr + <span class="hljs-string">"/"</span> + service + <span class="hljs-string">"/"</span> + <span class="hljs-string">"tc3_request"</span>;
<span class="hljs-built_in">string</span> hashedCanonicalRequest = SHA256Hex(canonicalRequest);
<span class="hljs-built_in">string</span> stringToSign = algorithm + <span class="hljs-string">"\n"</span>
+ requestTimestamp.ToString() + <span class="hljs-string">"\n"</span>
+ credentialScope + <span class="hljs-string">"\n"</span>
+ hashedCanonicalRequest;
Console.WriteLine(stringToSign);
<span class="hljs-comment">// ************* 步骤 3:计算签名 *************</span>
<span class="hljs-built_in">byte</span>[] tc3SecretKey = Encoding.UTF8.GetBytes(<span class="hljs-string">"TC3"</span> + secretkey);
<span class="hljs-built_in">byte</span>[] secretDate = HmacSHA256(tc3SecretKey, Encoding.UTF8.GetBytes(datestr));
<span class="hljs-built_in">byte</span>[] secretService = HmacSHA256(secretDate, Encoding.UTF8.GetBytes(service));
<span class="hljs-built_in">byte</span>[] secretSigning = HmacSHA256(secretService, Encoding.UTF8.GetBytes(<span class="hljs-string">"tc3_request"</span>));
<span class="hljs-built_in">byte</span>[] signatureBytes = HmacSHA256(secretSigning, Encoding.UTF8.GetBytes(stringToSign));
<span class="hljs-built_in">string</span> signature = BitConverter.ToString(signatureBytes).Replace(<span class="hljs-string">"-"</span>, <span class="hljs-string">""</span>).ToLower();
Console.WriteLine(signature);
<span class="hljs-comment">// ************* 步骤 4:拼接 Authorization *************</span>
<span class="hljs-built_in">string</span> authorization = algorithm + <span class="hljs-string">" "</span>
+ <span class="hljs-string">"Credential="</span> + secretid + <span class="hljs-string">"/"</span> + credentialScope + <span class="hljs-string">", "</span>
+ <span class="hljs-string">"SignedHeaders="</span> + signedHeaders + <span class="hljs-string">", "</span>
+ <span class="hljs-string">"Signature="</span> + signature;
Console.WriteLine(authorization);
Dictionary<<span class="hljs-built_in">string</span>, <span class="hljs-built_in">string</span>> headers = <span class="hljs-keyword">new</span> Dictionary<<span class="hljs-built_in">string</span>, <span class="hljs-built_in">string</span>>();
headers.Add(<span class="hljs-string">"Authorization"</span>, authorization);
headers.Add(<span class="hljs-string">"Host"</span>, endpoint);
headers.Add(<span class="hljs-string">"Content-Type"</span>, contentType + <span class="hljs-string">"; charset=utf-8"</span>);
headers.Add(<span class="hljs-string">"X-TC-Timestamp"</span>, requestTimestamp.ToString());
headers.Add(<span class="hljs-string">"X-TC-Version"</span>, version);
headers.Add(<span class="hljs-string">"X-TC-Action"</span>, action);
headers.Add(<span class="hljs-string">"X-TC-Region"</span>, region);
<span class="hljs-keyword">return</span> headers;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-built_in">string</span>[] args</span>)</span>
{
<span class="hljs-comment">// 密钥参数</span>
<span class="hljs-comment">// 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID********************************</span>
<span class="hljs-built_in">string</span> SECRET_ID = Environment.GetEnvironmentVariable(<span class="hljs-string">"TENCENTCLOUD_SECRET_ID"</span>);
<span class="hljs-comment">// 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ********************************</span>
<span class="hljs-built_in">string</span> SECRET_KEY = Environment.GetEnvironmentVariable(<span class="hljs-string">"TENCENTCLOUD_SECRET_KEY"</span>);
<span class="hljs-built_in">string</span> service = <span class="hljs-string">"cvm"</span>;
<span class="hljs-built_in">string</span> endpoint = <span class="hljs-string">"cvm.tencentcloudapi.com"</span>;
<span class="hljs-built_in">string</span> region = <span class="hljs-string">"ap-guangzhou"</span>;
<span class="hljs-built_in">string</span> action = <span class="hljs-string">"DescribeInstances"</span>;
<span class="hljs-built_in">string</span> version = <span class="hljs-string">"2017-03-12"</span>;
<span class="hljs-comment">// 此处由于示例规范的原因,采用时间戳2019-02-26 00:44:25,此参数作为示例,如果在项目中,您应当使用:</span>
<span class="hljs-comment">// DateTime date = DateTime.UtcNow;</span>
<span class="hljs-comment">// 注意时区,建议此时间统一采用UTC时间戳,否则容易出错</span>
DateTime date = <span class="hljs-keyword">new</span> DateTime(<span class="hljs-number">1970</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, DateTimeKind.Utc).AddSeconds(<span class="hljs-number">1551113065</span>);
<span class="hljs-built_in">string</span> requestPayload = <span class="hljs-string">"{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}"</span>;
Dictionary<<span class="hljs-built_in">string</span>, <span class="hljs-built_in">string</span>> headers = BuildHeaders(SECRET_ID, SECRET_KEY, service
, endpoint, region, action, version, date, requestPayload);
Console.WriteLine(<span class="hljs-string">"POST https://cvm.tencentcloudapi.com"</span>);
<span class="hljs-keyword">foreach</span> (KeyValuePair<<span class="hljs-built_in">string</span>, <span class="hljs-built_in">string</span>> kv <span class="hljs-keyword">in</span> headers)
{
Console.WriteLine(kv.Key + <span class="hljs-string">": "</span> + kv.Value);
}
Console.WriteLine();
Console.WriteLine(requestPayload);
}
}
const crypto = require('crypto');
function sha256(message, secret = '', encoding) {
const hmac = crypto.createHmac('sha256', secret)
return hmac.update(message).digest(encoding)
}
function getHash(message, encoding = 'hex') {
const hash = crypto.createHash('sha256')
return hash.update(message).digest(encoding)
}
function getDate(timestamp) {
const date = new Date(timestamp * 1000)
const year = date.getUTCFullYear()
const month = ('0' + (date.getUTCMonth() + 1)).slice(-2)
const day = ('0' + date.getUTCDate()).slice(-2)
return <span class="hljs-subst">${year}</span>-<span class="hljs-subst">${month}</span>-<span class="hljs-subst">${day}</span>
}
function main(){
// 密钥参数
// 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID****
const SECRET_ID = process.env.TENCENTCLOUD_SECRET_ID
// 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ****
const SECRET_KEY = process.env.TENCENTCLOUD_SECRET_KEY
<span class="hljs-keyword">const</span> endpoint = <span class="hljs-string">"cvm.tencentcloudapi.com"</span>
<span class="hljs-keyword">const</span> service = <span class="hljs-string">"cvm"</span>
<span class="hljs-keyword">const</span> region = <span class="hljs-string">"ap-guangzhou"</span>
<span class="hljs-keyword">const</span> action = <span class="hljs-string">"DescribeInstances"</span>
<span class="hljs-keyword">const</span> version = <span class="hljs-string">"2017-03-12"</span>
<span class="hljs-comment">//const timestamp = getTime()</span>
<span class="hljs-keyword">const</span> timestamp = <span class="hljs-number">1551113065</span>
<span class="hljs-comment">//时间处理, 获取世界时间日期</span>
<span class="hljs-keyword">const</span> date = getDate(timestamp)
<span class="hljs-comment">// ************* 步骤 1:拼接规范请求串 *************</span>
<span class="hljs-keyword">const</span> payload = <span class="hljs-string">"{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}"</span>
<span class="hljs-keyword">const</span> hashedRequestPayload = getHash(payload);
<span class="hljs-keyword">const</span> httpRequestMethod = <span class="hljs-string">"POST"</span>
<span class="hljs-keyword">const</span> canonicalUri = <span class="hljs-string">"/"</span>
<span class="hljs-keyword">const</span> canonicalQueryString = <span class="hljs-string">""</span>
<span class="hljs-keyword">const</span> canonicalHeaders = <span class="hljs-string">"content-type:application/json; charset=utf-8\n"</span>
+ <span class="hljs-string">"host:"</span> + endpoint + <span class="hljs-string">"\n"</span>
+ <span class="hljs-string">"x-tc-action:"</span> + action.toLowerCase() + <span class="hljs-string">"\n"</span>
<span class="hljs-keyword">const</span> signedHeaders = <span class="hljs-string">"content-type;host;x-tc-action"</span>
<span class="hljs-keyword">const</span> canonicalRequest = httpRequestMethod + <span class="hljs-string">"\n"</span>
+ canonicalUri + <span class="hljs-string">"\n"</span>
+ canonicalQueryString + <span class="hljs-string">"\n"</span>
+ canonicalHeaders + <span class="hljs-string">"\n"</span>
+ signedHeaders + <span class="hljs-string">"\n"</span>
+ hashedRequestPayload
<span class="hljs-built_in">console</span>.log(canonicalRequest)
<span class="hljs-comment">// ************* 步骤 2:拼接待签名字符串 *************</span>
<span class="hljs-keyword">const</span> algorithm = <span class="hljs-string">"TC3-HMAC-SHA256"</span>
<span class="hljs-keyword">const</span> hashedCanonicalRequest = getHash(canonicalRequest);
<span class="hljs-keyword">const</span> credentialScope = date + <span class="hljs-string">"/"</span> + service + <span class="hljs-string">"/"</span> + <span class="hljs-string">"tc3_request"</span>
<span class="hljs-keyword">const</span> stringToSign = algorithm + <span class="hljs-string">"\n"</span> +
timestamp + <span class="hljs-string">"\n"</span> +
credentialScope + <span class="hljs-string">"\n"</span> +
hashedCanonicalRequest
<span class="hljs-built_in">console</span>.log(stringToSign)
<span class="hljs-comment">// ************* 步骤 3:计算签名 *************</span>
<span class="hljs-keyword">const</span> kDate = sha256(date, <span class="hljs-string">'TC3'</span> + SECRET_KEY)
<span class="hljs-keyword">const</span> kService = sha256(service, kDate)
<span class="hljs-keyword">const</span> kSigning = sha256(<span class="hljs-string">'tc3_request'</span>, kService)
<span class="hljs-keyword">const</span> signature = sha256(stringToSign, kSigning, <span class="hljs-string">'hex'</span>)
<span class="hljs-built_in">console</span>.log(signature)
<span class="hljs-comment">// ************* 步骤 4:拼接 Authorization *************</span>
<span class="hljs-keyword">const</span> authorization = algorithm + <span class="hljs-string">" "</span> +
<span class="hljs-string">"Credential="</span> + SECRET_ID + <span class="hljs-string">"/"</span> + credentialScope + <span class="hljs-string">", "</span> +
<span class="hljs-string">"SignedHeaders="</span> + signedHeaders + <span class="hljs-string">", "</span> +
<span class="hljs-string">"Signature="</span> + signature
<span class="hljs-built_in">console</span>.log(authorization)
<span class="hljs-keyword">const</span> curlcmd = <span class="hljs-string">'curl -X POST '</span> + <span class="hljs-string">"https://"</span> + endpoint
+ <span class="hljs-string">' -H "Authorization: '</span> + authorization + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "Content-Type: application/json; charset=utf-8"'</span>
+ <span class="hljs-string">' -H "Host: '</span> + endpoint + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "X-TC-Action: '</span> + action + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "X-TC-Timestamp: '</span> + timestamp.toString() + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "X-TC-Version: '</span> + version + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">' -H "X-TC-Region: '</span> + region + <span class="hljs-string">'"'</span>
+ <span class="hljs-string">" -d '"</span> + payload + <span class="hljs-string">"'"</span>
<span class="hljs-built_in">console</span>.log(curlcmd)
}
main()
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <stdio.h>
#include <time.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
using namespace std;
string get_data(int64_t ×tamp)
{
string utcDate;
char buff[20] = {0};
// time_t timenow;
struct tm sttime;
sttime = *gmtime(×tamp);
strftime(buff, sizeof(buff), "%Y-%m-%d", &sttime);
utcDate = string(buff);
return utcDate;
}
string int2str(int64_t n)
{
std::stringstream ss;
ss << n;
return ss.str();
}
string sha256Hex(const string &str)
{
char buf[3];
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, str.c_str(), str.size());
SHA256_Final(hash, &sha256);
std::string NewString = "";
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
snprintf(buf, sizeof(buf), "%02x", hash[i]);
NewString = NewString + buf;
}
return NewString;
}
string HmacSha256(const string &key, const string &input)
{
unsigned char hash[32];
HMAC_CTX *h;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
HMAC_CTX hmac;
HMAC_CTX_init(&hmac);
h = &hmac;
#else
h = HMAC_CTX_new();
#endif
<span class="hljs-built_in">HMAC_Init_ex</span>(h, &key[<span class="hljs-number">0</span>], key.<span class="hljs-built_in">length</span>(), <span class="hljs-built_in">EVP_sha256</span>(), <span class="hljs-literal">NULL</span>);
<span class="hljs-built_in">HMAC_Update</span>(h, ( <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span>* )&input[<span class="hljs-number">0</span>], input.<span class="hljs-built_in">length</span>());
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span> len = <span class="hljs-number">32</span>;
<span class="hljs-built_in">HMAC_Final</span>(h, hash, &len);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
HMAC_CTX_cleanup(h);
#else
HMAC_CTX_free(h);
#endif
std::stringstream ss;
ss << std::<span class="hljs-built_in">setfill</span>(<span class="hljs-string">'0'</span>);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < len; i++)
{
ss << hash[i];
}
<span class="hljs-keyword">return</span> (ss.<span class="hljs-built_in">str</span>());
}
string HexEncode(const string &input)
{
static const char* const lut = "0123456789abcdef";
size_t len = input.length();
string output;
output.<span class="hljs-built_in">reserve</span>(<span class="hljs-number">2</span> * len);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">size_t</span> i = <span class="hljs-number">0</span>; i < len; ++i)
{
<span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> c = input[i];
output.<span class="hljs-built_in">push_back</span>(lut[c >> <span class="hljs-number">4</span>]);
output.<span class="hljs-built_in">push_back</span>(lut[c & <span class="hljs-number">15</span>]);
}
<span class="hljs-keyword">return</span> output;
}
int main()
{
// 密钥参数
// 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID****
string SECRET_ID = getenv("TENCENTCLOUD_SECRET_ID");
// 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ****
string SECRET_KEY = getenv("TENCENTCLOUD_SECRET_KEY");
string service = <span class="hljs-string">"cvm"</span>;
string host = <span class="hljs-string">"cvm.tencentcloudapi.com"</span>;
string region = <span class="hljs-string">"ap-guangzhou"</span>;
string action = <span class="hljs-string">"DescribeInstances"</span>;
string version = <span class="hljs-string">"2017-03-12"</span>;
<span class="hljs-keyword">int64_t</span> timestamp = <span class="hljs-number">1551113065</span>;
string date = <span class="hljs-built_in">get_data</span>(timestamp);
<span class="hljs-comment">// ************* 步骤 1:拼接规范请求串 *************</span>
string httpRequestMethod = <span class="hljs-string">"POST"</span>;
string canonicalUri = <span class="hljs-string">"/"</span>;
string canonicalQueryString = <span class="hljs-string">""</span>;
string lower = action;
std::<span class="hljs-built_in">transform</span>(action.<span class="hljs-built_in">begin</span>(), action.<span class="hljs-built_in">end</span>(), lower.<span class="hljs-built_in">begin</span>(), ::tolower);
string canonicalHeaders = <span class="hljs-built_in">string</span>(<span class="hljs-string">"content-type:application/json; charset=utf-8\n"</span>)
+ <span class="hljs-string">"host:"</span> + host + <span class="hljs-string">"\n"</span>
+ <span class="hljs-string">"x-tc-action:"</span> + lower + <span class="hljs-string">"\n"</span>;
string signedHeaders = <span class="hljs-string">"content-type;host;x-tc-action"</span>;
string payload = <span class="hljs-string">"{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}"</span>;
string hashedRequestPayload = <span class="hljs-built_in">sha256Hex</span>(payload);
string canonicalRequest = httpRequestMethod + <span class="hljs-string">"\n"</span>
+ canonicalUri + <span class="hljs-string">"\n"</span>
+ canonicalQueryString + <span class="hljs-string">"\n"</span>
+ canonicalHeaders + <span class="hljs-string">"\n"</span>
+ signedHeaders + <span class="hljs-string">"\n"</span>
+ hashedRequestPayload;
cout << canonicalRequest << endl;
<span class="hljs-comment">// ************* 步骤 2:拼接待签名字符串 *************</span>
string algorithm = <span class="hljs-string">"TC3-HMAC-SHA256"</span>;
string RequestTimestamp = <span class="hljs-built_in">int2str</span>(timestamp);
string credentialScope = date + <span class="hljs-string">"/"</span> + service + <span class="hljs-string">"/"</span> + <span class="hljs-string">"tc3_request"</span>;
string hashedCanonicalRequest = <span class="hljs-built_in">sha256Hex</span>(canonicalRequest);
string stringToSign = algorithm + <span class="hljs-string">"\n"</span> + RequestTimestamp + <span class="hljs-string">"\n"</span> + credentialScope + <span class="hljs-string">"\n"</span> + hashedCanonicalRequest;
cout << stringToSign << endl;
<span class="hljs-comment">// ************* 步骤 3:计算签名 ***************</span>
string kKey = <span class="hljs-string">"TC3"</span> + SECRET_KEY;
string kDate = <span class="hljs-built_in">HmacSha256</span>(kKey, date);
string kService = <span class="hljs-built_in">HmacSha256</span>(kDate, service);
string kSigning = <span class="hljs-built_in">HmacSha256</span>(kService, <span class="hljs-string">"tc3_request"</span>);
string signature = <span class="hljs-built_in">HexEncode</span>(<span class="hljs-built_in">HmacSha256</span>(kSigning, stringToSign));
cout << signature << endl;
<span class="hljs-comment">// ************* 步骤 4:拼接 Authorization *************</span>
string authorization = algorithm + <span class="hljs-string">" "</span> + <span class="hljs-string">"Credential="</span> + SECRET_ID + <span class="hljs-string">"/"</span> + credentialScope + <span class="hljs-string">", "</span>
+ <span class="hljs-string">"SignedHeaders="</span> + signedHeaders + <span class="hljs-string">", "</span> + <span class="hljs-string">"Signature="</span> + signature;
cout << authorization << endl;
string curlcmd = <span class="hljs-string">"curl -X POST https://"</span> + host + <span class="hljs-string">"\n"</span>
+ <span class="hljs-string">" -H \"Authorization: "</span> + authorization + <span class="hljs-string">"\"\n"</span>
+ <span class="hljs-string">" -H \"Content-Type: application/json; charset=utf-8\""</span> + <span class="hljs-string">"\n"</span>
+ <span class="hljs-string">" -H \"Host: "</span> + host + <span class="hljs-string">"\"\n"</span>
+ <span class="hljs-string">" -H \"X-TC-Action: "</span> + action + <span class="hljs-string">"\"\n"</span>
+ <span class="hljs-string">" -H \"X-TC-Timestamp: "</span> + RequestTimestamp + <span class="hljs-string">"\"\n"</span>
+ <span class="hljs-string">" -H \"X-TC-Version: "</span> + version + <span class="hljs-string">"\"\n"</span>
+ <span class="hljs-string">" -H \"X-TC-Region: "</span> + region + <span class="hljs-string">"\"\n"</span>
+ <span class="hljs-string">" -d '"</span> + payload + <span class="hljs-string">"\'"</span>;
cout << curlcmd << endl;
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
};
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
void get_utc_date(int64_t timestamp, char* utc, int len)
{
// time_t timenow;
struct tm sttime;
sttime = *gmtime(×tamp);
strftime(utc, len, "%Y-%m-%d", &sttime);
}
void sha256_hex(const char* str, char* result)
{
char buf[3];
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, str, strlen(str));
SHA256_Final(hash, &sha256);
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
snprintf(buf, sizeof(buf), "%02x", hash[i]);
strcat(result, buf);
}
}
void hmac_sha256(const char* key, int key_len,
const char* input, int input_len,
unsigned char* output, unsigned int* output_len)
{
HMAC_CTX *h;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
HMAC_CTX hmac;
HMAC_CTX_init(&hmac);
h = &hmac;
#else
h = HMAC_CTX_new();
#endif
HMAC_Init_ex(h, key, key_len, EVP_sha256(), <span class="hljs-literal">NULL</span>);
HMAC_Update(h, ( <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span>* )input, input_len);
HMAC_Final(h, output, output_len);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
HMAC_CTX_cleanup(h);
#else
HMAC_CTX_free(h);
#endif
}
void hex_encode(const char* input, int input_len, char* output)
{
static const char* const lut = "0123456789abcdef";
<span class="hljs-keyword">char</span> add_out[<span class="hljs-number">128</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-keyword">char</span> temp[<span class="hljs-number">2</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">size_t</span> i = <span class="hljs-number">0</span>; i < input_len; ++i)
{
<span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> c = input[i];
temp[<span class="hljs-number">0</span>] = lut[c >> <span class="hljs-number">4</span>];
<span class="hljs-built_in">strcat</span>(add_out, temp);
temp[<span class="hljs-number">0</span>] = lut[c & <span class="hljs-number">15</span>];
<span class="hljs-built_in">strcat</span>(add_out, temp);
}
<span class="hljs-built_in">strncpy</span>(output, add_out, <span class="hljs-number">128</span>);
}
void lowercase(const char * src, char * dst)
{
for (int i = 0; src[i]; i++)
{
dst[i] = tolower(src[i]);
}
}
int main()
{
// 密钥参数
// 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKID****
const char* SECRET_ID = getenv("TENCENTCLOUD_SECRET_ID");
// 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 ****
const char* SECRET_KEY = getenv("TENCENTCLOUD_SECRET_KEY");
const char* service = "cvm";
const char* host = "cvm.tencentcloudapi.com";
const char* region = "ap-guangzhou";
const char* action = "DescribeInstances";
const char* version = "2017-03-12";
int64_t timestamp = 1551113065;
char date[20] = {0};
get_utc_date(timestamp, date, sizeof(date));
<span class="hljs-comment">// ************* 步骤 1:拼接规范请求串 *************</span>
<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span>* http_request_method = <span class="hljs-string">"POST"</span>;
<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span>* canonical_uri = <span class="hljs-string">"/"</span>;
<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span>* canonical_query_string = <span class="hljs-string">""</span>;
<span class="hljs-keyword">char</span> canonical_headers[<span class="hljs-number">100</span>] = {<span class="hljs-string">"content-type:application/json; charset=utf-8\nhost:"</span>};
<span class="hljs-built_in">strcat</span>(canonical_headers, host);
<span class="hljs-built_in">strcat</span>(canonical_headers, <span class="hljs-string">"\nx-tc-action:"</span>);
<span class="hljs-keyword">char</span> value[<span class="hljs-number">100</span>] = {<span class="hljs-number">0</span>};
lowercase(action, value);
<span class="hljs-built_in">strcat</span>(canonical_headers, value);
<span class="hljs-built_in">strcat</span>(canonical_headers, <span class="hljs-string">"\n"</span>);
<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span>* signed_headers = <span class="hljs-string">"content-type;host;x-tc-action"</span>;
<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span>* payload = <span class="hljs-string">"{\"Limit\": 1, \"Filters\": [{\"Values\": [\"\\u672a\\u547d\\u540d\"], \"Name\": \"instance-name\"}]}"</span>;
<span class="hljs-keyword">char</span> hashed_request_payload[<span class="hljs-number">100</span>] = {<span class="hljs-number">0</span>};
sha256_hex(payload, hashed_request_payload);
<span class="hljs-keyword">char</span> canonical_request[<span class="hljs-number">256</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-built_in">sprintf</span>(canonical_request, <span class="hljs-string">"%s\n%s\n%s\n%s\n%s\n%s"</span>, http_request_method,
canonical_uri, canonical_query_string, canonical_headers,
signed_headers, hashed_request_payload);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, canonical_request);
<span class="hljs-comment">// ************* 步骤 2:拼接待签名字符串 *************</span>
<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span>* algorithm = <span class="hljs-string">"TC3-HMAC-SHA256"</span>;
<span class="hljs-keyword">char</span> request_timestamp[<span class="hljs-number">16</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-built_in">sprintf</span>(request_timestamp, <span class="hljs-string">"%d"</span>, timestamp);
<span class="hljs-keyword">char</span> credential_scope[<span class="hljs-number">64</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-built_in">strcat</span>(credential_scope, date);
<span class="hljs-built_in">sprintf</span>(credential_scope, <span class="hljs-string">"%s/%s/tc3_request"</span>, date, service);
<span class="hljs-keyword">char</span> hashed_canonical_request[<span class="hljs-number">100</span>] = {<span class="hljs-number">0</span>};
sha256_hex(canonical_request, hashed_canonical_request);
<span class="hljs-keyword">char</span> string_to_sign[<span class="hljs-number">256</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-built_in">sprintf</span>(string_to_sign, <span class="hljs-string">"%s\n%s\n%s\n%s"</span>, algorithm, request_timestamp,
credential_scope, hashed_canonical_request);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, string_to_sign);
<span class="hljs-comment">// ************* 步骤 3:计算签名 ***************</span>
<span class="hljs-keyword">char</span> k_key[<span class="hljs-number">64</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-built_in">sprintf</span>(k_key, <span class="hljs-string">"%s%s"</span>, <span class="hljs-string">"TC3"</span>, SECRET_KEY);
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> k_date[<span class="hljs-number">64</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span> output_len = <span class="hljs-number">0</span>;
hmac_sha256(k_key, <span class="hljs-built_in">strlen</span>(k_key), date, <span class="hljs-built_in">strlen</span>(date), k_date, &output_len);
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> k_service[<span class="hljs-number">64</span>] = {<span class="hljs-number">0</span>};
hmac_sha256(k_date, output_len, service, <span class="hljs-built_in">strlen</span>(service), k_service, &output_len);
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> k_signing[<span class="hljs-number">64</span>] = {<span class="hljs-number">0</span>};
hmac_sha256(k_service, output_len, <span class="hljs-string">"tc3_request"</span>, <span class="hljs-built_in">strlen</span>(<span class="hljs-string">"tc3_request"</span>), k_signing, &output_len);
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> k_hmac_sha_sign[<span class="hljs-number">64</span>] = {<span class="hljs-number">0</span>};
hmac_sha256(k_signing, output_len, string_to_sign, <span class="hljs-built_in">strlen</span>(string_to_sign), k_hmac_sha_sign, &output_len);
<span class="hljs-keyword">char</span> signature[<span class="hljs-number">128</span>] = {<span class="hljs-number">0</span>};
hex_encode(k_hmac_sha_sign, output_len, signature);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, signature);
<span class="hljs-comment">// ************* 步骤 4:拼接 Authorization *************</span>
<span class="hljs-keyword">char</span> authorization[<span class="hljs-number">512</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-built_in">sprintf</span>(authorization, <span class="hljs-string">"%s Credential=%s/%s, SignedHeaders=%s, Signature=%s"</span>,
algorithm, SECRET_ID, credential_scope, signed_headers, signature);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, authorization);
<span class="hljs-keyword">char</span> curlcmd[<span class="hljs-number">10240</span>] = {<span class="hljs-number">0</span>};
<span class="hljs-built_in">sprintf</span>(curlcmd, <span class="hljs-string">"curl -X POST https://%s\n \
-H \"Authorization: %s\"\n \
-H \"Content-Type: application/json; charset=utf-8\"\n \
-H \"Host: %s\"\n \
-H \"X-TC-Action: %s\"\n \
-H \"X-TC-Timestamp: %s\"\n \
-H \"X-TC-Version: %s\"\n \
-H \"X-TC-Region: %s\"\n \
-d \'%s\'"</span>,
host, authorization, host, action, request_timestamp, version, region, payload);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, curlcmd);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
存在以下签名失败的错误码,请根据实际情况处理。
| 错误码 | 错误描述 |
|---|---|
| AuthFailure.SignatureExpire | 签名过期。Timestamp 与服务器接收到请求的时间相差不得超过五分钟。 |
| AuthFailure.SecretIdNotFound | 密钥不存在。请到控制台查看密钥是否被禁用,是否少复制了字符或者多了字符。 |
| AuthFailure.SignatureFailure | 签名错误。可能是签名计算错误,或者签名与实际发送的内容不相符合,也有可能是密钥 SecretKey 错误导致的。 |
| AuthFailure.TokenFailure | 临时证书 Token 错误。 |
| AuthFailure.InvalidSecretId | 密钥非法(不是云 API 密钥类型)。 |
文档反馈