> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 玩家加密服務

> 了解 PlayFab 玩家共用秘密、遊戲公開金鑰，以及用來保護帳戶建立和用戶端登入要求的 RSA 加密註冊承載。

## 玩家共用秘密

玩家共用秘密是一種新型的虛擬秘密金鑰，在遊戲用戶端之間共用。透過 API，可用它來交換遊戲的公開 RSA 金鑰，並可用來執行帳戶註冊。

遊戲可以擁有多個玩家共用金鑰，並可透過 Admin API 呼叫 [Create](xref:titleid.playfabapi.com.admin.authentication.createplayersharedsecret)、[Update](xref:titleid.playfabapi.com.admin.authentication.updateplayersharedsecret)、[Delete](xref:titleid.playfabapi.com.admin.authentication.deleteplayersharedsecret)、[List](xref:titleid.playfabapi.com.admin.authentication.getplayersharedsecrets) 隨意設定和撤銷這些金鑰。

玩家共用秘密應內建於各自的用戶端中，因為沒有任何用戶端 API 可以擷取它們，無論是否經過驗證。

## 遊戲公開金鑰

接著將玩家共用秘密傳送至 [GetTitlePublicKey](xref:titleid.playfabapi.com.client.authentication.gettitlepublickey)。如果金鑰有效，API 會傳回 Base 64 編碼的 RSA CSP blob 位元組陣列，可加密 237 個位元組的資料。

所有允許建立帳戶的 API，現在都接受將註冊要求以加密承載的形式張貼至 `EncryptedRequest` 欄位。

<Note>
  標準欄位 **`TitleId`**、**`InfoRequestParameters`** 和 **`CreateAccount`** *不應*包含在加密承載中。
</Note>

## 使用遊戲公開金鑰進行註冊

以下是使用 `LoginWithCustomID` 和遊戲公開金鑰註冊玩家的範例程式碼。

```csharp theme={null}
var titleKeyResult = PlayFabClientAPI.GetTitlePublicKey(new GetTitlePublicKeyRequest{ TitleId = "TITLE", TitleSharedSecret = "player shared secret" });

var cspBlob = Convert.FromBase64String(titleKeyResult.RSAPublicKey);

var encryptionModel = JsonConvert.SearializeObject(new LoginWithCustomIDRequest

{
    CustomID = "my player's custom id",
    PlayerSecret = "my player's individual secret"
});

string encryptedPayload;

using (var rsa = new RSACryptoServiceProvider())
{
    rsa.ImportCspBlob(cspBlob);
    var bytesToEncrypt = Encoding.UTF8.GetBytes(encryptionModel);
    var encryptedBytes = rsa.Encrypt(bytesToEncrypt, false);
    encryptedPayload = Convert.ToBase64String(encryptedBytes);
}

var postModel = new LoginWithCustomIDRequest
{
    TitleId = "TITLEID",
    EncryptedRequest = encryptedPayload,
    CreateAccount = True
};

var createAccountResult = PlayFabClientAPI.LoginWithCustomID(postModel);
```

## 玩家秘密

新註冊系統的一部分是名為 `PlayerSecret` 的新欄位。如果已設定，它可讓您簽署要求標頭，伺服器會在對所有服務 (包括登入要求) 進行 API 呼叫期間驗證這些標頭。

每位使用者在每個遊戲中只能設定*一次*玩家秘密。在同一工作室擁有多個遊戲的使用者，必須為每個遊戲設定玩家秘密。

如果在註冊期間尚未設定玩家秘密，可以呼叫 [SetPlayerSecret](xref:titleid.playfabapi.com.client.authentication.setplayersecret) 來設定。有一些管理員和伺服器 API 允許將玩家秘密設定為*新*值，即使先前已設定過也一樣。

<Note>
  設定之後，玩家秘密應安全地儲存在裝置上，因為一旦遺失就*無法*復原，而且*沒有*任何 API 可以復原它。
</Note>

## 使用玩家秘密簽署 API 要求

下列程式碼範例會建構可用來簽署 API 要求的簽章標頭。簽章標頭的格式如下所示。

`jsonRequestModel.utcTimeStampInISO.playerSecret`

```csharp theme={null}
var postModel = new LoginWithCustomIDRequest

{
    TitleId = "TITLEID",
    CustomID =  "my player's custom id",
    CreateAccount = False
};

string signatureHeader;
string timestampHeader = DateTime.UtcNow.ToString("O");

string playerSecret; // the player secret that was sent during registration.

 using (var hash = new SHA256Managed())
{
    var bytesToHash = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(postModel)+"." + timestampHeader + "." + playerSecret);
    signatureHeader = hash.ComputeHash(bytesToHash);
}

var customHeaders = new Dictionary<string, string>
{
    { "X-PlayFab-Signature", signatureHeader },
    { "X-PlayFab-Timestamp", timestampHeader }
}

var loginResult = PLayFabClientAPI.LoginWithCustomID(postModel, customHeaders);
```

## 使用原則強制執行

[API 原則](https://playfab.com/blog/permission-policies/)現在可用來強制執行下列案例。

* 用戶端要求為加密承載。
* 用戶端要求包含已簽署的標頭。

即使*未*使用原則強制執行，如果傳送了加密承載 (或傳送了標頭)，它們仍會經過驗證。如果格式不正確，就會發生錯誤。

若要建立原則以要求特定 API 上必須有標頭，請使用 `Deny` 陳述式。這會建立一個原則，要求您所發出的、未經 `Allow` 陳述式允許的*所有*呼叫都必須有標頭。

原則陳述式有一個名為 `ApiConditions` 的屬性。`ApiConditions` 包含一個名為 `HasSignatureOrEncryption` 的屬性，它是具有三個可能值的列舉：

* `Any`
* `True`
* `False`

<Note>
  預設值 (如果原則*未*設定) 為 **`Any`**。
</Note>

下列範例原則允許對 `LoginWithCustomID` 的*所有* API 呼叫 (未加密或缺少標頭的呼叫除外)。

```json theme={null}
{
    "PolicyName": "ApiPolicy",
    "OverwritePolicy": true,
    "Statements":
    [
        {
            "Comment": "Require Headers on LoginWithCustomID",
            "Action": "*",
            "Principal": "*",
            "Effect": "Deny",
            "Resource": "pfrn:api--/Client/LoginWithCustomID",
            "ApiConditions": { "HasSignatureOrEncryption": "False" }
        },
        {
            "Comment": "Allow the rest policy",
            "Action": "*",
            "Principal": "*",
            "Effect": "Allow",
            "Resource": "pfrn:api--*"
        }
    ]
}
```

上述 `Deny` 陳述式包含 `HasSignatureOrEncryption: False`。這表示所有沒有簽章或加密的要求都會遭到拒絕。換句話說，所有*具有*簽章標頭或加密的要求，都會根據 `Allow the rest policy` 而獲得允許。


## Related topics

- [適用於遊戲服務的 XBOX 服務驗證](/zh-TW/services/xbox-services/fundamentals/s2s-auth-calls/service-authentication/live-title-service-authentication.md)
- [邀請](/zh-TW/services/xbox-services/multiplayer/invites/index.md)
- [加密登入](/zh-TW/services/playfab/identity/player-identity/encryption/encrypted-logins.md)
- [邀請玩家加入遊戲工作階段](/zh-TW/services/xbox-services/multiplayer/invites/live-invites-nav.md)
- [概念](/zh-TW/services/xbox-services/multiplayer/mpa/concepts/index.md)
