Skip to content

Commit d43cdd2

Browse files
SundoggyNewarchurtan
authored andcommitted
使用签名方法 v3 的公共参数Authorization生成的测试用例。
Change-Id: Ie32a0fe94d6a07ba8a90e89ed96254ab01d02c7b
1 parent f57e2df commit d43cdd2

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package com.tencent.iot.explorer.video
2+
3+
import android.util.Log
4+
import com.alibaba.fastjson.JSON
5+
import junit.framework.TestCase
6+
import org.junit.Test
7+
import java.lang.Long
8+
import java.nio.charset.Charset
9+
import java.security.InvalidKeyException
10+
import java.security.MessageDigest
11+
import java.security.NoSuchAlgorithmException
12+
import java.text.SimpleDateFormat
13+
import java.util.*
14+
import javax.crypto.Mac
15+
import javax.crypto.spec.SecretKeySpec
16+
import kotlin.experimental.and
17+
18+
class SignForV3Test {
19+
20+
private var secretId = "YourSecretId"
21+
private var secretKey = "YourSecretKey"
22+
private var VIDEO_SERVICE = "iotvideo" // video
23+
24+
companion object {
25+
val UTF8: Charset = Charset.forName("UTF-8")
26+
27+
val REST_HOST_URL = ".tencentcloudapi.com"
28+
}
29+
30+
@Test
31+
fun testSign() {
32+
try {
33+
var headerParams = commonHeaderParams("DescribeCloudStorageDate", "2020-12-15")
34+
val param = TreeMap<String, Any>()
35+
param["ProductId"] = "productId"
36+
param["DeviceName"] = "devName"
37+
val authorization = generateAuthorization(VIDEO_SERVICE, headerParams, param)
38+
println(authorization)
39+
TestCase.assertTrue(true)
40+
} catch (e: java.lang.Exception) {
41+
e.printStackTrace()
42+
TestCase.fail()
43+
}
44+
}
45+
46+
fun commonHeaderParams(action: String, version: String): HashMap<String, String> {
47+
val param = HashMap<String, String>()
48+
param["X-TC-Action"] = action
49+
param["X-TC-Version"] = version
50+
param["X-TC-Region"] = "ap-guangzhou"
51+
param["X-TC-Timestamp"] = (System.currentTimeMillis() / 1000).toString()
52+
return param
53+
}
54+
55+
open fun generateAuthorization(
56+
service: String,
57+
headers: Map<String, String>,
58+
param: TreeMap<String, Any>
59+
): String? {
60+
val algorithm = "TC3-HMAC-SHA256"
61+
val timestamp: String = headers?.get("X-TC-Timestamp") as String
62+
val sdf = SimpleDateFormat("yyyy-MM-dd")
63+
// 注意时区,否则容易出错
64+
sdf.timeZone = TimeZone.getTimeZone("UTC")
65+
val date =
66+
sdf.format(Date(Long.valueOf(timestamp + "000")))
67+
68+
// ************* 步骤 1:拼接规范请求串 *************
69+
val httpRequestMethod = "POST"
70+
val canonicalUri = "/"
71+
val canonicalQueryString = ""
72+
val canonicalHeadersBuilder = "content-type:application/json; charset=utf-8\nhost:${service}${REST_HOST_URL}\n"
73+
val signedHeadersBuilder = "content-type;host"
74+
val canonicalHeaders = canonicalHeadersBuilder
75+
val signedHeaders = signedHeadersBuilder.toLowerCase()
76+
77+
// 将Extra参数加到待签名字符串中,否则会签名失败
78+
var payload: String? = toJson(param)
79+
val hashedRequestPayload: String? = payload?.let { sha256Hex(it) }
80+
val canonicalRequest = "${httpRequestMethod}\n${canonicalUri}\n${canonicalQueryString}\n${canonicalHeaders}\n${signedHeaders}\n${hashedRequestPayload}"
81+
println(canonicalRequest)
82+
83+
// ************* 步骤 2:拼接待签名字符串 *************
84+
val credentialScope = "$date/$service/tc3_request"
85+
val hashedCanonicalRequest: String? = sha256Hex(canonicalRequest)
86+
val stringToSign =
87+
"""
88+
$algorithm
89+
$timestamp
90+
$credentialScope
91+
$hashedCanonicalRequest
92+
""".trimIndent()
93+
println(stringToSign)
94+
95+
// ************* 步骤 3:计算签名 ************* SecretKey
96+
val secretDate: ByteArray = hmac256(
97+
("TC3" + secretKey).toByteArray(UTF8),
98+
date
99+
)
100+
val secretService: ByteArray = hmac256(secretDate, service)
101+
val secretSigning: ByteArray = hmac256(
102+
secretService,
103+
"tc3_request"
104+
)
105+
val byteArray: ByteArray = hmac256(secretSigning, stringToSign)
106+
val signature: String? = encodeHexString(byteArray)
107+
108+
// ************* 步骤 4:拼接 Authorization ************* SecretId
109+
return algorithm + " " + "Credential=" + secretId + "/" + credentialScope + ", " + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature
110+
}
111+
112+
/**
113+
* 功能描述:把指定的java对象转为json数据
114+
*/
115+
fun toJson(clazz: Any?): String? {
116+
return try {
117+
JSON.toJSONString(clazz)
118+
} catch (e: Exception) {
119+
Log.e("ToJsonEntity", "fastjson转换错误:${e.message} \n原因是:${e.cause}")
120+
null
121+
}
122+
}
123+
124+
open fun sha256Hex(s: String): String? {
125+
var md: MessageDigest? = null
126+
var d: ByteArray? = null
127+
try {
128+
md = MessageDigest.getInstance("SHA-256")
129+
d = md.digest(s.toByteArray(UTF8))
130+
} catch (e: NoSuchAlgorithmException) {
131+
e.printStackTrace()
132+
}
133+
return d?.let { encodeHexString(it)?.toLowerCase() }
134+
}
135+
136+
open fun encodeHexString(byteArray: ByteArray): String? {
137+
val hexStringBuffer = StringBuffer()
138+
for (i in byteArray.indices) {
139+
hexStringBuffer.append(
140+
byteToHex(
141+
byteArray[i]
142+
)
143+
)
144+
}
145+
return hexStringBuffer.toString()
146+
}
147+
148+
open fun byteToHex(num: Byte): String? {
149+
val hexDigits = CharArray(2)
150+
hexDigits[0] = Character.forDigit((num.toInt() shr 4) and 0xF, 16)
151+
hexDigits[1] = Character.forDigit((num and 0xF).toInt(), 16)
152+
return String(hexDigits)
153+
}
154+
155+
open fun hmac256(key: ByteArray, msg: String): ByteArray {
156+
var mac: Mac? = null
157+
try {
158+
mac = Mac.getInstance("HmacSHA256")
159+
val secretKeySpec =
160+
SecretKeySpec(key, mac.algorithm)
161+
mac.init(secretKeySpec)
162+
} catch (e: NoSuchAlgorithmException) {
163+
e.printStackTrace()
164+
} catch (e: InvalidKeyException) {
165+
e.printStackTrace()
166+
}
167+
return mac!!.doFinal(msg.toByteArray(UTF8))
168+
}
169+
}

0 commit comments

Comments
 (0)