テンセントクラウドのUserSig署名の生成について

## Tencent Cloudのご紹介
- Tencent CloudにはIaaS、Paas、SaaSに別れて、プロダクト数は２００以上
- アカウントは下記２種類
  - [中国サイト](https://cloud.tencent.com/)のアカウント：中国法人向け
  - [国際サイト](https://intl.cloud.tencent.com/)のアカウント：グローバル向け

## UserSigの紹介
- UserSigは、悪意のある攻撃者がクラウドサービスを使用する権利を悪用するのを防ぐために、Tencent Cloudによって設計されたセキュリティ保護署名です。
- 現在、Tencent Cloudのモバイルライブ配信（MLVB）、リアルタイム音声ビデオ通信（TRTC）、およびインスタントメッセージング（IM）サービスは、この一連のセキュリティ保護メカニズムを採用しています。 これらのサービスを使用するには、対応するSDK初期化またはログイン関数でSDKAppID、UserID、およびUserSigキー情報を提供する必要があります。
- このうち、SDKAppIDはアプリケーションの識別に使用され、UserIDはユーザーの識別に使用されます。UserSigは、HMAC SHA256暗号化アルゴリズムによって計算される最初の2つに基づいて計算されるセキュリティ署名です。 攻撃者がUserSigを偽造できない限り、クラウドサービストラフィックを盗むことはできません。

- UserSigの計算原理は次のとおりです。その本質は、SDKAppID、UserID、ExpireTimeなどのキー情報をハッシュおよび暗号化することです

```
//UserSigの求める方法。secretkeyはusersigを求めるための秘密鍵
usersig = hmacsha256(secretkey, (userid + sdkappid + currtime + expire + 
　　　　　　　　　　　　　　　　　　　 base64(userid + sdkappid + currtime + expire)))
```

- 上記のから見ると、PKIのメカニズムと同じ仕組みです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/86cca03f-7644-570d-2682-914b00532ea2.png)

## 秘密鍵の取得

前提条件：テンセントクラウドでIMアプリを作成したこと。まだ作成していない場合、[ここ](https://qiita.com/hiSirius/items/0e50604d7502439a2989)に参考すること。

- [IMコンソール](https://console.cloud.tencent.com/im)でにアクセスして、アプリの情報にクリックすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/66e9a7cd-3665-d198-674c-41daaa52ac4f.png)

## UserSig署名の生成
- アプリでUserSig署名の直接生成
- サーバでUserSig署名の生成

#### アプリで直接生成
Javaの場合

```java
userSig = GenTLSSignature(TCGlobalConfig.SDKAPPID, userId, TCGlobalConfig.EXPIRETIME, null, TCGlobalConfig.SECRETKEY);
```
MLVB/TRTC/IMのDEMOはユーザーを早くを体験するために、秘密鍵をアプリに保持して、直接生成しますが、実際アプリを実際運用する時にUserSig署名の生成の部分はサーバで行うのはおすすめです。なぜかというと、アプリをデコンパイルしてしまうと、第三者にプ秘密鍵が漏れてしまいます。

#### サーバで生成

UserSigのサーバー側の計算方法を使用すると、リバースアプリよりもサーバーを破壊することが難しいため、UserSigの計算に使用されるキーが漏洩しないようにすることができます。 具体的なアプローチは次のとおりです。

- アプリがSDKの初期化関数を呼び出す前に、まずサーバーからUserSigをリクエストする必要があります。
- サーバーはSDKAppIDとUserIDに基づいてUserSigを計算します。

pythonでUserSigを求める例：(他の言語の求める方法は最後のテーブルをご参考ください)


```python
### pip install tls-sig-api-v2 でTLSSigAPIv2をインストールすること
import TLSSigAPIv2
### 秘密鍵:5bd2850fff3ecb11d7c805251c51ee463a25727bddc2385f3fa8bfee1bb93b5e
### SDKAppID:1400000000
### APIを取得
api = TLSSigAPIv2.TLSSigAPIv2(1400000000, '5bd2850fff3ecb11d7c805251c51ee463a25727bddc2385f3fa8bfee1bb93b5e')
### "秘密鍵で「こんにちは」を暗号化する。いわゆる電子書名を行う"
sig = api.gen_sig("こんにちは")
### 暗号化したものを出力（署名したもの）
print(sig)
```
- サーバーは、計算されたUserSigをアプリに返します。
- アプリが取得したUserSigは、特定のAPIを介してSDKに渡されます。
- SDKは、検証のためにSDKAppID + UserID + UserSigをTencent Cloud Serverに送信します。
- Tencent Cloudは、その合法性を確認するためにUserSigを検証します。
- 検証を通過すると、TRTC/MLVB/IM SDKはサービスを提供します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/39007c32-b42d-05d0-c6d7-f3e70c19690f.png)


#### 他の言語でUserSigの求める方法
| 言語 | 署名の生成方法| 関数| リンク |
|:---------:|:---------:|:---------:|:---------:|
| Java | HMAC-SHA256 | [genSig](https://github.com/tencentyun/tls-sig-api-v2-java/blob/master/src/main/java/com/tencentyun/TLSSigAPIv2.java)  | [Github](https://github.com/tencentyun/tls-sig-api-v2-java)|
| GO | HMAC-SHA256 | [GenSig](https://github.com/tencentyun/tls-sig-api-v2-golang/blob/master/tencentyun/TLSSigAPI.go) | [Github](https://github.com/tencentyun/tls-sig-api-v2-golang)|
| PHP | HMAC-SHA256 | [genSig](https://github.com/tencentyun/tls-sig-api-v2-php/blob/master/src/TLSSigAPIv2.php) | [Github](https://github.com/tencentyun/tls-sig-api-v2-php)|
| Nodejs | HMAC-SHA256 | [genSig](https://github.com/tencentyun/tls-sig-api-v2-node/blob/master/TLSSigAPIv2.js) | [Github](https://github.com/tencentyun/tls-sig-api-v2-node)|
| Python | HMAC-SHA256 | [gen_sig](https://github.com/tencentyun/tls-sig-api-v2-python/blob/master/TLSSigAPIv2.py) | [Github](https://github.com/tencentyun/tls-sig-api-v2-python)|
| C# | HMAC-SHA256 | [GenSig](https://github.com/tencentyun/tls-sig-api-v2-cs/blob/master/tls-sig-api-v2-cs/TLSSigAPIv2.cs) | [Github](https://github.com/tencentyun/tls-sig-api-v2-cs)|