Logo Logo
GitHub Designed by Logto

O que é uma chave de assinatura?

No contexto de OpenID Connect (OIDC) , uma chave de assinatura, geralmente um par de chaves assimétricas, é usada para assinar e verificar JSON Web Tokens (JWTs) . Os fornecedores OpenID usam chaves de assinatura para assinar tokens como ID tokens e access tokens para garantir sua integridade e autenticidade.

Embora o conceito de chaves de assinatura possa ser mais amplo, focaremos em como elas são usadas no OIDC para proteger tokens. Outros casos de uso incluem a assinatura de e-mails, documentos e pacotes de software, podendo derivar dos mesmos princípios.

Exemplo: Assinatura de ID token

Quando um utilizador se autentica com um fornecedor OpenID, o fornecedor emite um ID token que contém informações do utilizador ( claims ) e é assinado pela chave de assinatura do fornecedor. Como o ID token é um JWT, ele consiste em três partes: cabeçalho, payload e assinatura.

1. Cabeçalho

Vamos supor que o cabeçalho seja:

{
  "alg": "ES384",
  "typ": "JWT"
}

O JSON indica que o ID token é assinado usando o algoritmo ECDSA com a curva P-384. O campo typ especifica que o tipo de token é JWT.

2. Payload

O payload contém informações básicas do utilizador:

{
  "sub": "1234567890",
  "name": "Alice"
}

O sub claim é o identificador único do utilizador, e name é o seu nome de exibição.

3. Assinar o token

De acordo com o formato JWT, o cabeçalho e o payload devem ser codificados em Base64URL e concatenados com um . para assinatura:

{{header}}.{{payload}}

Neste caso, o valor seria:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0

Vamos supor que o fornecedor OpenID use a seguinte chave privada para assinar o token:

-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBW9PDXInlNT2hjOtQr
g4pkVkyJsKia33dHrsbOG4Z77pfYN7SYZCHh9YdLXTTKinehZANiAAQX/FB1s6Gj
YnDSGCY08PRUAQ8CCRCt8Ph/VDHfLj1xSbrjp8wFf0NjH7jcfNebpV1fvu4XKbP3
Ro7h0G6elN1TMsVECJPv4ieDNkYOsgT4UboJypC5E/rmvrlJTMM6Y/k=
-----END PRIVATE KEY-----

Para assinar o token, o fornecedor OpenID precisa usar a chave privada para gerar uma assinatura por:

signature = sign(header + '.' + payload, private_key)

Então, a assinatura codificada em Base64URL é:

Cjy6A_FHnwQBP0hRawoGTkRy8m8o0Ncc1q4BeyxYr0fxhKYmJJinIWZPXJdaAXRO9wOFuH2-UML2yWHjot_LnCPO6362asMvgNkEJMZ6UtqyOPlsCOJ7voTPOCT6sYu2

4. Montar o JWT

Finalmente, o fornecedor OpenID monta o JWT concatenando o cabeçalho, payload e assinatura com .:

{{header}}.{{payload}}.{{signature}}

Neste caso, o ID token seria:

eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0.Cjy6A_FHnwQBP0hRawoGTkRy8m8o0Ncc1q4BeyxYr0fxhKYmJJinIWZPXJdaAXRO9wOFuH2-UML2yWHjot_LnCPO6362asMvgNkEJMZ6UtqyOPlsCOJ7voTPOCT6sYu2

O ID token está agora pronto para ser enviado ao Cliente para processamento posterior.

5. Verificar o token

Quando o cliente recebe o ID token, ele pode verificar a assinatura usando a chave pública do fornecedor OpenID. Normalmente, a chave pública é disponibilizada através do endpoint Descoberta do OpenID Connect (OIDC) (jwks_uri) no formato de um Conjunto de Chaves da Web JSON (JWKS) .

Para este exemplo, a chave pública é:

-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEF/xQdbOho2Jw0hgmNPD0VAEPAgkQrfD4
f1Qx3y49cUm646fMBX9DYx-43HzXm6VdX77uFymz90aO4dBunpTdUzLFRAiT7+In
gzZGDrIE+FG6CcqQuRP65r65SUzDOmP5
-----END PUBLIC KEY-----

E o valor correspondente do JWK é:

{
  "kty": "EC",
  "crv": "P-384",
  "x": "F_xQdbOho2Jw0hgmNPD0VAEPAgkQrfD4f1Qx3y49cUm646fMBX9DYx-43HzXm6Vd",
  "y": "X77uFymz90aO4dBunpTdUzLFRAiT7-IngzZGDrIE-FG6CcqQuRP65r65SUzDOmP5"
}

Agora, o cliente pode verificar a assinatura usando a chave pública.

Escolher o algoritmo certo

Existem vários algoritmos disponíveis para assinar JWTs:

  • Algoritmos simétricos: HMAC com a família SHA (por exemplo, HS256, HS384, HS512) é um algoritmo simétrico que usa a mesma chave para assinar e verificar. Não é recomendado para a maioria dos casos, pois a chave secreta precisa ser compartilhada entre as partes.
  • Algoritmos assimétricos: RSA (por exemplo, RS256, RS384, RS512) e ECDSA (por exemplo, ES256, ES384, ES512) são algoritmos assimétricos que usam um par de chaves: uma chave privada para assinar e uma chave pública para verificar.
    • RSA é amplamente utilizado e suportado por muitas bibliotecas e plataformas. No entanto, tem um tamanho de chave e assinatura muito maior em comparação com o ECDSA.
    • ECDSA é mais performante e gera assinaturas menores, tornando-o uma escolha melhor para ambientes restritos. Como é menos comum, certifique-se de que sua plataforma o suporte.

ECDSA deve ser a escolha preferida para novas aplicações devido aos seus benefícios de desempenho e segurança.

Outros cenários de chave de assinatura

Embora o exemplo acima se concentre em ID tokens no OIDC, o conceito de chave de assinatura é amplamente utilizado em vários cenários, como assinatura de e-mails, documentos e pacotes de software. Os princípios-chave permanecem os mesmos:

  • Para chaves simétricas, a mesma chave é usada para assinar e verificar. Isso é adequado para cenários onde as partes podem compartilhar a chave com segurança, ou há uma única entidade responsável por assinar e verificar.
  • Para chaves assimétricas, uma chave privada é usada para assinar, e uma chave pública correspondente é usada para verificar. Isso é adequado para a maioria dos cenários onde as partes de assinatura e verificação são entidades diferentes.

Veja também