> ## 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는 237바이트의 데이터를 암호화할 수 있는 Base 64 인코딩된 RSA CSP blob 바이트 배열을 반환합니다.

계정을 만들 수 있게 하는 모든 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

- [멀티플레이어 서비스 구성](/ko/services/xbox-services/multiplayer/concepts/live-configure-the-multiplayer-service.md)
- [서비스 간 멀티플레이어 세션 관리](/ko/services/xbox-services/fundamentals/s2s-auth-calls/s2s-calls/s2s-call-patterns/live-mpsd-service-to-service.md)
- [XBOX 플레이어 데이터 개요](/ko/services/xbox-services/player-data/live-playerdata-overview.md)
- [암호화된 로그인](/ko/services/playfab/identity/player-identity/encryption/encrypted-logins.md)
- [타이틀 서비스에 대한 XBOX 서비스 인증](/ko/services/xbox-services/fundamentals/s2s-auth-calls/service-authentication/live-title-service-authentication.md)
