> ## 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.

# Logins criptografados

> Habilite a criptografia personalizada para chamadas de API de login de cliente do PlayFab para proteger os payloads de autenticação e reforçar a segurança do aplicativo contra adulteração.

O PlayFab permite que você reforce a segurança do aplicativo protegendo determinadas chamadas de API do cliente com criptografia personalizada. Este tutorial mostra como habilitar a criptografia para o seu cliente.

O método que usaremos permite proteger *qualquer* chamada de API de login. Como o processo é *sempre* semelhante, mostramos apenas como proteger *um* método específico, `LoginWithCustomID`.

<Info>
  A criptografia de login deve ser usada para *todos* os jogadores após a criação do título, ou não deve ser usada. Este *não* é um recurso que pode ser habilitado posteriormente. Você deve usá-lo *desde o início* ou não usá-lo. Em particular, jogadores *criptografados* nunca poderão fazer login *sem criptografia*, e jogadores *não criptografados* nunca poderão se tornar jogadores *criptografados*.
</Info>

Neste guia, vamos:

1. Criar um segredo compartilhado do jogador.
2. Introduzir uma regra de Política de API para habilitar a proteção em um determinado método.
3. Alterar o cliente para usar uma chave compartilhada do jogador para recuperar a chave pública do título e criptografar o payload.

<Note>
  O PlayFab faz o seguinte aviso: "Todas as nossas chamadas de API já são criptografadas com segurança de acordo com os padrões modernos, e a criptografia padrão das chamadas de API é tudo de que a maioria dos clientes precisará. Este recurso representa uma camada *adicional* de segurança criada para dificultar que os jogadores usem um cliente não autorizado. Ele *não* é infalível; apenas aumenta o nível de dificuldade para os hackers. Para a maioria dos desenvolvedores, o leve aumento de segurança não compensará o esforço extra necessário."
</Note>

## Criando um segredo compartilhado do jogador

A API Admin do PlayFab expõe um método para gerenciar seus segredos compartilhados do jogador.

<Note>
  Criar um novo segredo compartilhado com um determinado nome substituirá a chave existente com o mesmo nome, se houver. Além disso, você pode ter *vários* segredos compartilhados registrados com nomes diferentes.
</Note>

Execute o código a seguir para adicionar um segredo compartilhado do jogador ao seu título.

```csharp theme={null}
PlayFabSettings.staticSettings.DeveloperSecretKey = "__DEVELOPER_KEY__";
PlayFabSettings.staticSettings.TitleId = "__TITLE_ID__";
var response = await PlayFabAdminAPI.CreatePlayerSharedSecretAsync(new CreatePlayerSharedSecretRequest()
{
    FriendlyName = "__KEY_NAME__"
});

if (response.Error != null)
{
    Console.WriteLine(response.Error.GenerateErrorReport());
}
else
{
    Console.WriteLine(response.Result.SecretKey);
}
```

Para executar este código, você precisa de uma chave secreta de desenvolvedor. Para obter mais informações sobre chaves secretas, consulte [Gerenciamento de chaves secretas](/pt-BR/services/playfab/live-service-management/gamemanager/secret-key-management).

Este aplicativo deve imprimir um segredo compartilhado do jogador recém-criado. *Certifique-se de salvá-lo*. Se ele for perdido, você terá que gerar um novo segredo executando o aplicativo novamente.

O segredo tem esta aparência:

`QC953WQ3TU6ZJTZMAT1FNJQIKR92FPUQTISW4Q6WD8SY841MQQ`

## Atualizando a política

Temos um novo segredo compartilhado criado. Agora precisamos informar ao PlayFab quais chamadas de API devem ser protegidas.

Execute o código mostrado abaixo para proteger a chamada de API `LoginWithCustomId` e *desproteger* o restante das chamadas de API.

```csharp theme={null}
// Set development key and title id
PlayFabSettings.DeveloperSecretKey = "__DEVELOPER_KEY__";
PlayFabSettings.TitleId = "__TITLE_ID__";

public static async Task SetApiPermission(bool restrictCustomId)
{
    // The first statement denies every call to LoginWithCustomID that is not properly encrypted
    var filterCustom = new PermissionStatement
    {
        // Statement effects any action
        Action = "*",
        // Filter the case where there is no signature and payload is not encrypted
        ApiConditions = new ApiCondition()
        {
            HasSignatureOrEncryption = Conditionals.False
        },
        Comment = "Deny every request to LoginWithCustomID that is not properly encrypted",
        // Specify the resource name
        Resource = "pfrn:api--/Client/LoginWithCustomID", // Resource name
        // Deny any of such requests
        Effect = EffectType.Deny,
        // For any user
        Principal = "*"
    };
    // The second statement allows every other API call
    var filterNothing = new PermissionStatement()
    {
        // Statement effects any action
        Action = "*",
        Comment = "Allow the rest API calls",
        // For any resource name
        Resource = "pfrn:api--*",
        // Allow any request
        Effect = EffectType.Allow,
        // For any user
        Principal = "*"
    };

    // Update the policy
    var request = new UpdatePolicyRequest()
    {
        // ApiPolicy controls access to API methods
        PolicyName = "ApiPolicy",
        // In this example we overwrite the policy. Consider appending to the existing policy instead.
        OverwritePolicy = true,
        // Introduce policy statements
        Statements = new List<PermissionStatement> { filterNothing }
    };
    if (restrictCustomId)
        request.Statements.Add(filterCustom);
    var result = await PlayFabAdminAPI.UpdatePolicyAsync(request);

    // Handle possible errors
    if (result.Error != null)
        Console.WriteLine(result.Error.GenerateErrorReport());
    else
        Console.WriteLine("Policy updated");
}
```

## Configurando o cliente

Agora que a política foi atualizada, você não consegue mais simplesmente chamar a API `LoginWithCustomID`. Considere o código mostrado abaixo.

```csharp theme={null}
var result = await PlayFabClientAPI.LoginWithCustomIDAsync(new LoginWithCustomIDRequest()
{
    CreateAccount = true,
    CustomId = "Some_Custom_Id"
});

if (result.Error != null)
{
    Console.WriteLine(result.Error.GenerateErrorReport());
}
else
{
    Console.WriteLine(result.Result.PlayFabId);
}
```

Normalmente, isso faria o login do usuário sem problemas. No entanto, *agora* essa chamada de API está *protegida*, e o código gerará um erro `Not Authorized` (não confundir com `Not Authenticated`).

Precisamos modificar o cliente para criptografar corretamente o payload da chamada. Isso é feito em 2 etapas:

1. Usar o segredo compartilhado do jogador para buscar a chave pública do título.
2. Usar a chave pública do título para criptografar o payload.

O código mostrado abaixo ilustra isso.

```csharp theme={null}
public static async Task DoEncryptedLogin()
{
    Console.WriteLine("Begin DoEncryptedLogin");

    // Use Player Shared Secret to get Title Public Key
    var titleKeyResult = await PlayFabClientAPI.GetTitlePublicKeyAsync(new GetTitlePublicKeyRequest
    {
        TitleId = TITLE_ID,
        TitleSharedSecret = CLIENT_SECRET_KEY
    });

    Console.WriteLine("Encrypt request");
    // Convert public key to bytes
    var cspBlob = Convert.FromBase64String(titleKeyResult.Result.RSAPublicKey);

    // Serialize certain part of the model into string (this will be encrypted).
    var encryptionModel = JsonWrapper.SerializeObject(new LoginWithCustomIDRequest { CustomId = "SOME_PLAYER_ID_ENCRYPTED" });
    string encryptedPayload;

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

    // Use encrypted payload to construct a model
    var model = new LoginWithCustomIDRequest
    {
        EncryptedRequest = encryptedPayload,
        PlayerSecret = CLIENT_SECRET_KEY,
        CreateAccount = true
    };

    Console.WriteLine("Call LoginWithCustomIDAsync");
    // Finally execute the call
    var result = await PlayFabClientAPI.LoginWithCustomIDAsync(model);
    Console.WriteLine("LoginWithCustomIDAsync done");
    bool successful = result.Error == null && result.Result != null;
    if (!successful)
        Console.WriteLine(result.Error.GenerateErrorReport());
    else
        Console.WriteLine("Login Successful" + result.Result.PlayFabId);
}
```

Depois de executar o código, você deverá conseguir fazer login. Lembre-se de que, após a criação de um segredo compartilhado do jogador, ele deve ser codificado diretamente no código do cliente, pois *não há como* buscá-lo ou solicitá-lo usando qualquer chamada de API.


## Related topics

- [Serviços de criptografia do jogador](/pt-BR/services/playfab/identity/player-identity/encryption/player-encryption-services.md)
- [Modelo de criptografia do MSIXVC2](/pt-BR/build/core-features/common/packaging/packaging-encryption-msixvc2.md)
- [Atualizações de conteúdo com MSIXVC2](/pt-BR/build/core-features/common/packaging/packaging-updates-msixvc2.md)
- [Introdução ao empacotamento de títulos para consoles XBOX](/pt-BR/build/core-features/common/packaging/overviews/packaging-getting-started-for-console.md)
- [Empacotamento de aplicativos durante o desenvolvimento](/pt-BR/build/core-features/common/packaging/packaging-packaging-during-development.md)
