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\n host:${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