Artigo
· Ago. 8, 2023 11min de leitura

Referência para as Classes Web JSON

Prefácio

O InterSystems IRIS a partir da versão 2022.2 inclui uma funcionalidade reformulada para JSON web tokens (JWTs). Antes localizada no pacote da classe %OAuth2, a classe JWT, junto com as outras classes da Web JSON (JWCs), agora está em %Net.JSON. Essa migração ocorreu para modularizar as JWCs. Antes, eles estavam estreitamente ligados à implementação do framework OAuth 2.0. Agora, eles podem ser mantidos e usados separadamente.

Observação: para a compatibilidade com as versões anteriores, as classes ainda existem no pacote %OAuth2, mas a codebase agora usa %Net.JSON.

O objetivo deste artigo é servir como uma espécie de referência para as JWCs porque, ao tentar escrever uma documentação, não encontrei nenhuma fonte com informações abrangentes sobre todas elas e como se relacionam entre si. Espero que este artigo seja essa fonte.

Prólogo

O que são as JWCs?

As classes da Web JSON são os protocolos da Web que usam estruturas de dados baseadas em JSON. Elas são úteis para a autorização e a troca de informações, como OAuth 2.0 e OpenID Connect.

No momento, o InterSystems IRIS 2022.2+ é compatível com sete classes em %Net.JSON: (clique para abrir a definição)


> JSON Object Signing and Encryption (JOSE)
Um conjunto de padrões para assinar e criptografar dados usando estruturas de dados baseadas em JSON. Isso inclui JWT, JWS, JWE, JWA, JWK e JWKS.

> JSON Web Token (JWT)
Uma maneira compacta e segura para o URL de representar informações transferidas entre duas partes que podem ser assinadas digitalmente, criptografadas ou ambos.

> JSON Web Signature (JWS)
Uma JWS representa o conteúdo assinado usando estruturas de dados baseadas em JSON. O JWA define os algoritmos de assinatura e verificação para a JWS. Ou seja, um JWT assinado.

> JSON Web Encryption (JWE)
Uma JWE representa o conteúdo criptografado usando estruturas de dados baseadas em JSON. A JWA define os algoritmos de criptografia e descriptografia para a JWE. Ou seja, um JWT criptografado.

> JSON Web Algorithms (JWA)
Um JWA define um conjunto de algoritmos criptográficos e identificadores usados com as classes JWS, JWE e JWK.

> JSON Web Key (JWK)
Uma JWK representa uma chave criptográfica usada como entrada para os algoritmos definidos na classe JWA.

> JSON Web Key Set (JWKS)
Um JWKS é um conjunto de JWKs

O diagrama a seguir demonstra a relação entre as JWCs, conforme definido abaixo: Fluxo de JWCs

Vamos analisar cada parte na seção a seguir.

Um estudo do JWT

Um JSON web token (JWT) é uma maneira compacta e segura para o URL de representar informações transferidas entre duas partes que podem ser assinadas digitalmente, criptografadas ou ambos.

Há dois tipos de JWTs:
- JWS
- JWE

Uma JWS é um JWT assinado e uma JWE é um JWT criptografado. Na linguagem corrente, falamos "JWT" ou "JWT criptografado". Para JWTs, o padrão é que sejam assinados, ainda que possam não ser assinados (JWTs não seguros).

Mas vamos voltar um pouco — o que é uma informação? É apenas um pedaço de informação representado em um par de chave/valor que um cliente está afirmando ser verdadeiro. Por exemplo, pode ser uma informação sobre um cliente que está tentando fazer login de um determinado local. O seguinte objeto JSON contém três informações (username, location, and admin):

{
    "username": "persephone",
    "location": "underworld",
    "admin": "true"
}

Então, os JWTs transferem informações assim entre duas partes, como cliente e servidor. No entanto, se apenas essas informações fossem transferidas, não haveria garantia de que ninguém adulterou ou viu o conteúdo, além do destinatário. Nossa mensagem não teria integridade ou confidencialidade. Felizmente, os JWTs fornecem uma maneira opcional de garantia com ambos os padrões JSON web signature (JWS) e JSON web encryption (JWE). Seja uma JWS ou JWE, um JWT tem várias partes.

JSON Web Signature (JWS)

Um JWT não criptografado e assinado (portanto, chamado de JWS) possui três partes:

  1. Header (cabeçalho)
  2. Payload (carga útil)
  3. Signature (assinatura)

Cada parte é um objeto JSON. Se você fizer a codificação Base64URL de cada parte e concatená-las com um ponto (.) entre elas, você terá um JWT (header.payload.signature).

Vamos analisar cada parte.

Cabeçalho

O cabeçalho de uma JWS consiste em metadados sobre o tipo de token e, se especificado, o JSON web algorithm (JWA) necessário para a validação da assinatura do token. Por exemplo:

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

Codifique o texto abaixo em Base64URL e você terá a primeira parte de um JWT!

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Para resumir, o cabeçalho contém o JWA e o tipo do token.

Carga útil

A segunda parte de uma JWS é a carga útil. Ela contém as informações. Usando o exemplo anterior, a carga útil pode ser o seguinte:

{
    "username": "persephone",
    "location": "underworld",
    "admin": "true"
}

Depois de codificar em Base64URL, obtemos isto:

eyJ1c2VybmFtZSI6InBlcnNlcGhvbmUiLCJsb2NhdGlvbiI6InVuZGVyd29ybGQiLCJhZG1pbiI6InRydWUifQ

Agora, nossa JWS está desta forma:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InBlcnNlcGhvbmUiLCJsb2NhdGlvbiI6InVuZGVyd29ybGQiLCJhZG1pbiI6InRydWUifQ

Para resumir, a carga útil contém as informações que você quer transmitir.

Assinatura

A terceira parte de uma JWS é a assinatura. Você pega o JWT até o momento (o cabeçalho e a carga útil criptografados), um segredo [também chamado de chave privada ou JSON web key (JWK)], o algoritmo especificado no JWA e assina isso. Desta forma:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

Usando o segredo/valor da JWK thecatsmeow, nossa JWS ficará assim no final:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InBlcnNlcGhvbmUiLCJsb2NhdGlvbiI6InVuZGVyd29ybGQiLCJhZG1pbiI6InRydWUifQ.KAZcjC9tqRV4DunI3sSma3k6fvL5ntgLXe9Gl7hKg5o

Para resumir, a assinatura contém a validação da integridade.

Abstraindo um pouco, temos:

JSON web signature

Você notou que eu falei...

Talvez você tenha percebido que eu qualifiquei nosso JWT como "pode ser assinado digitalmente, criptografado ou ambos".

Vamos falar sobre a parte da assinatura primeiro e depois abordar a criptografia na próxima seção. É possível não assinar a JWS e só ter um cabeçalho e uma carga útil (então, não é mais uma JWS, e sim um JWT não assinado e não criptografado). Isso é possível se o JWA especificado no cabeçalho para "none".

Desta forma:

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

Então, o JWT resultante seria apenas o cabeçalho criptografado em Base64URL + . + carga útil criptografada em Base64URL + .. A assinatura seria uma string vazia, então um JWT não seguro ficaria, por exemplo, desta forma:

eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.

Mas não envie JWTs não seguros, porque qualquer pessoa poderá adulterá-los e você não saberá se as informações são válidas.

JSON Web Encryption (JWE)

Repetindo, um JWT pode ser assinado digitalmente, criptografado ou ambos. Já discutimos as assinaturas com JWSs, então vamos seguir para a criptografia.

Como observado acima, um JWT não criptografado e assinado (JWS) tem três partes: cabeçalho, carga útil e assinatura.

Agora, um JWT criptografado (portanto, uma JWE) possui cinco partes:

  1. Cabeçalho protegido
  2. Chave criptografada
  3. Vetor de inicialização (IV)
  4. Carga útil/texto cifrado
  5. Tag de autenticação

Cabeçalho protegido

O cabeçalho protegido é a primeira parte de uma JWE. Ele não é criptografado porque o destinatário precisa saber como descriptografar o restante da JWE. Para informá-lo sobre como fazer isso, ele contém informações, como 1) o algoritmo usado para criptografar a chave de criptografia do conteúdo (CEK) e também produzir a chave criptografada e 2) o algoritmo usado para criptografar a carga útil e produzir o texto cifrado e a tag de autenticação.

Veja a seguir um exemplo de cabeçalho protegido:

{
  "alg":"RSA-OAEP",
  "enc":"A256GCM"
}

Ele é codificado em Base64URL para produzir o seguinte:

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ

Chave criptografada

A segunda parte da JWE é a chave criptografada. A chave criptografada é a forma criptografada da CEK, que é uma chave simétrica usada para criptografar a carga útil e produzir o texto cifrado e a tag de autenticação. A CEK é criptografada usando o algoritmo especificado no valor "alg" no cabeçalho protegido e na chave pública do destinatário.

Com uma CEK de thecatsmeowmeows e uma chave pública RSA de 1024 bits gerada aleatoriamente, o valor da chave criptografada usando o algoritmo RSA-OAEP pode ser:

X6znPIKWHnO8MhHD2scnUv7PVAo8VfxHYxmZQR0J8/rqGOB+udq8DkXd93n7S2cS3LT1Inx4qQ5J8GquQyc2xfS5n2INgKjSedYac4LBCkmpYRbRyNawK2eMEUDkcdBlqBE4NlWcAhl6X0H4AiNs7r+P8ffipvyztd51JdLoTlw=

A chave criptografada é codificada em Base64URL e concatenada ao cabeçalho protegido. Portanto, temos esta JWE até o momento:

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.WDZ6blBJS1dIbk84TWhIRDJzY25VdjdQVkFvOFZmeEhZeG1aUVIwSjgvcnFHT0IrdWRxOERrWGQ5M243UzJjUzNMVDFJbng0cVE1SjhHcXVReWMyeGZTNW4ySU5nS2pTZWRZYWM0TEJDa21wWVJiUnlOYXdLMmVNRVVEa2NkQmxxQkU0TmxXY0FobDZYMEg0QWlOczdyK1A4ZmZpcHZ5enRkNTFKZExvVGx3PQ

Vetor de inicialização (IV)

O IV é a terceira parte da JWE. Ele é gerado aleatoriamente e codificado em Base64URL. Não precisa ser secreto, portanto não é criptografado. Por exemplo, catsarefantastic. Em seguida, codificamos em Base64URL e concatenamos com o cabeçalho protegido codificado e as partes da chave criptografada para obter:

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.WDZ6blBJS1dIbk84TWhIRDJzY25VdjdQVkFvOFZmeEhZeG1aUVIwSjgvcnFHT0IrdWRxOERrWGQ5M243UzJjUzNMVDFJbng0cVE1SjhHcXVReWMyeGZTNW4ySU5nS2pTZWRZYWM0TEJDa21wWVJiUnlOYXdLMmVNRVVEa2NkQmxxQkU0TmxXY0FobDZYMEg0QWlOczdyK1A4ZmZpcHZ5enRkNTFKZExvVGx3PQ.Y2F0c2FyZWZhbnRhc3RpYw

Carga útil/texto cifrado

A quarta parte de uma JWE é a carga útil/texto cifrado. É onde aninhamos o JWT. Até aqui, abordamos como proteger e depois ler esses dados após o recebimento, mas agora podemos falar sobre os dados. Tudo o que discutimos na seção de JWS é aplicável aqui. Temos nossa JWS de três partes com o cabeçalho, a carga útil e a assinatura. Em seguida, usando a CEK e o IV, criptografamos a JWS usando AES GCM e solicitamos uma saída de tag de autenticação de 128 bits.

Um exemplo de um possível texto cifrado codificado em Base64URL:

NjI0YjZkZTlmMGEzNjk0MTgyMTYyNTc3MmEyMjM4ZWY0MTJhMzljMzJiOGVjNzVjMzU4MGIzNTVhMGUyN2M1MWYyY2Y2OGIyYmNkODM2YmNiZjBkOGIzZjMzMmQyODBlZWZhNjBkYTQ5M2VlNjRhMTg4NmMzYTFlY2E2OGQ0NjkyOGQzNTFjOWFjODdhY2QzZDc0ZTY4OTc1MTA4NzQ0NTEyNTJhOGM5N2U3OGFkNjJhMmNmMWQwNzM5MmQwYzcyM2EzMjg5MWI2YjlmMzRkNmYxMDU5YTVlMTljZThjMTNkNzFlMjgzZWY1ZGM0ZDdmZTNhMzk1YmM2MDE5NjRmZmMwYmZlMDM2YWY1MzZmYTdiYTYzNWU3NTJmMzk1OTBhY2Y2ZWM4YjlmZjBmYzY1ZTM0M2U5YzE4OTk0ZjAyYTZlNDA0NjEzNDM1ZTVhMQ

Temos esta JWE até o momento:

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.WDZ6blBJS1dIbk84TWhIRDJzY25VdjdQVkFvOFZmeEhZeG1aUVIwSjgvcnFHT0IrdWRxOERrWGQ5M243UzJjUzNMVDFJbng0cVE1SjhHcXVReWMyeGZTNW4ySU5nS2pTZWRZYWM0TEJDa21wWVJiUnlOYXdLMmVNRVVEa2NkQmxxQkU0TmxXY0FobDZYMEg0QWlOczdyK1A4ZmZpcHZ5enRkNTFKZExvVGx3PQ.Y2F0c2FyZWZhbnRhc3RpYw.NjI0YjZkZTlmMGEzNjk0MTgyMTYyNTc3MmEyMjM4ZWY0MTJhMzljMzJiOGVjNzVjMzU4MGIzNTVhMGUyN2M1MWYyY2Y2OGIyYmNkODM2YmNiZjBkOGIzZjMzMmQyODBlZWZhNjBkYTQ5M2VlNjRhMTg4NmMzYTFlY2E2OGQ0NjkyOGQzNTFjOWFjODdhY2QzZDc0ZTY4OTc1MTA4NzQ0NTEyNTJhOGM5N2U3OGFkNjJhMmNmMWQwNzM5MmQwYzcyM2EzMjg5MWI2YjlmMzRkNmYxMDU5YTVlMTljZThjMTNkNzFlMjgzZWY1ZGM0ZDdmZTNhMzk1YmM2MDE5NjRmZmMwYmZlMDM2YWY1MzZmYTdiYTYzNWU3NTJmMzk1OTBhY2Y2ZWM4YjlmZjBmYzY1ZTM0M2U5YzE4OTk0ZjAyYTZlNDA0NjEzNDM1ZTVhMQ

Tag de autenticação

A tag de autenticação é a parte final da JWE. É um resultado do texto cifrado (JWS aninhada criptografada). A tag de autenticação recebida ao criptografar o texto cifrado na última seção é:

9f19e30efeddf20f5232b76f07c755ac

Codificamos em Base64URL e concatenamos com a JWE para obter a JWE finalizada como:

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.WDZ6blBJS1dIbk84TWhIRDJzY25VdjdQVkFvOFZmeEhZeG1aUVIwSjgvcnFHT0IrdWRxOERrWGQ5M243UzJjUzNMVDFJbng0cVE1SjhHcXVReWMyeGZTNW4ySU5nS2pTZWRZYWM0TEJDa21wWVJiUnlOYXdLMmVNRVVEa2NkQmxxQkU0TmxXY0FobDZYMEg0QWlOczdyK1A4ZmZpcHZ5enRkNTFKZExvVGx3PQ.Y2F0c2FyZWZhbnRhc3RpYw.NjI0YjZkZTlmMGEzNjk0MTgyMTYyNTc3MmEyMjM4ZWY0MTJhMzljMzJiOGVjNzVjMzU4MGIzNTVhMGUyN2M1MWYyY2Y2OGIyYmNkODM2YmNiZjBkOGIzZjMzMmQyODBlZWZhNjBkYTQ5M2VlNjRhMTg4NmMzYTFlY2E2OGQ0NjkyOGQzNTFjOWFjODdhY2QzZDc0ZTY4OTc1MTA4NzQ0NTEyNTJhOGM5N2U3OGFkNjJhMmNmMWQwNzM5MmQwYzcyM2EzMjg5MWI2YjlmMzRkNmYxMDU5YTVlMTljZThjMTNkNzFlMjgzZWY1ZGM0ZDdmZTNhMzk1YmM2MDE5NjRmZmMwYmZlMDM2YWY1MzZmYTdiYTYzNWU3NTJmMzk1OTBhY2Y2ZWM4YjlmZjBmYzY1ZTM0M2U5YzE4OTk0ZjAyYTZlNDA0NjEzNDM1ZTVhMQ.OWYxOWUzMGVmZWRkZjIwZjUyMzJiNzZmMDdjNzU1YWM

Vamos abstrair a codificação em Base64URL e analisar a visão geral de alto nível de uma JWE:

JSON web encryption

Observações sobre os termos

Em busca de clareza, em vez de usar alguns nomes de classes da Web JSON, dei preferência para os nomes descritivos. Especificamente, JWK/JWKS em vez de chaves públicas, criptográficas, de criptografia, etc. A chave usada para a criptografia ou assinatura é uma JSON web key (JWK) e o conjunto delas (a chave simétrica e os pares de chaves assimétricas) é um JSON web key set (JWKS).

Queria fazer uma pausa para mencionar isso e retomar a terminologia. Um JWT é uma JWS ou JWE. Os algoritmos usados em uma JWS/JWE são definidos no JWA. As chaves usadas como entrada para os algoritmos no JWA são JWKs, armazenadas como um conjunto JWKS.

E o que é JOSE? JOSE é a coleção de padrões. Assim como temos bando para corvos ou gataria para gatos, temos JOSE para os padrões da Web JSON.

Conclusão

Espero que este artigo seja um bom ponto de referência para quem quer trabalhar com as classes da Web JSON (JWCs).

As JWCs têm três casos de uso diferentes:

  1. Autenticação
  2. Autorização
  3. Troca de informações

No InterSystems IRIS 2022.2+, você pode configurar o OAuth 2.0 para usar JWTs. Isso está descrito no OAuth 2.0 e OpenID Connect. Seu código personalizado pode usar as JWCs conforme definido no %Net.JSON para esses casos de uso.

Me avise se você achou este artigo útil!

Discussão (0)1
Entre ou crie uma conta para continuar