Branca é uma escolha interessante para mensagens usando o padrão IETF XChaCha20-Poly1305 AEAD, com dados extras de número de versão e um carimbo de data/hora.
Ele é perfeito para ser usado como uma alternativa em tokens de API, sendo uma forma segura e criptografada.
A especificação do Branca não limita o tipo de dados que você insere dentro do payload, então dá pra usar payloads como JWT, mas com a vantagem de uma criptografia moderna e um token mais compacto.
Atenção! O JWT é, na verdade, só uma parte de um padrão maior chamado JSON Object Signing and Encryption (JOSE). Mas, com o tempo, JWT virou praticamente sinônimo de JSON Web Signature (JWS) ou JSON Web Encryption (JWE). É comum todo mundo falar “JWT” para simplificar, mesmo que tecnicamente esteja falando só de uma assinatura ou criptografia em JSON. Neste texto, sempre que falarmos de JWT, estamos nos referindo ao “JWS” — a parte que garante a autenticidade e integridade dos dados.
Branca é baseado na especificação Fernet.
O que é Fernet?
Fernet pega uma mensagem fornecida pelo usuário, uma chave secreta e o horário atual e gera um token Authenticated Encrypted (AE).
A criptografia autenticada especifica uma maneira de proteger uma mensagem para que um terceiro não possa falsificá-la, alterá-la ou lê-la.
O token Fernet é uma concatenação codificada em Base64URL dos seguintes campos:
Version (1B) | Timestamp (8B) | IV (16B) | Ciphertext (*B) | HMAC (32B)
Onde HMAC é SHA256 HMAC de 256 bits da concatenação dos seguintes campos:
Version (1B) | Timestamp (8B) | IV (16B) | Ciphertext (*B)
Fernet parece não ser mais mantido. Não houve atualizações para a especificação em três anos. Os desenvolvedores originais estão em desde então.
Especificação do Branca
O token Branca é uma versão modernizada do Fernet. O Branca tem como objetivo ser seguro, fácil de implementar e ter um tamanho de token pequeno.
O token Branca é uma concatenação codificada em Base62 dos seguintes campos:
Version (1B) | Timestamp (4B) | Nonce (24B) | Ciphertext (*B) | Tag (16B)
As principais diferenças em relação à especificação Fernet são:
- Em vez de AES 128 CBC e SHA256 HMAC, Branca usa criptografia autenticada XChaCha20-Poly1305 com dados adicionais (AEAD).
- Em vez da codificação Base64URL, Branca usa Base62 para uma representação de string do token mais compatível.
- Em vez de um inteiro big-endian sem sinal de 64 bits, o timestamp é um inteiro big-endian sem sinal de 32 bits. Isso é um pouco mais fácil de implementar e economiza alguns bytes, mas ainda é válido até o ano 2106, quando o estouro de inteiros ocorrerá.
Alternativa ao JWT?
A especificação Branca define apenas o formato externo do token.
O formato do payload é intencionalmente indefinido. Isso significa que você ainda pode usar o payload JWT sem a sobrecarga do JOSE.
Para comparação, vamos usar a configuração típica do JWT amplamente vista na natureza.
O payload não é criptografado, mas tanto o cabeçalho quanto o payload são autenticados usando HMAC SHA-256.
Em outras palavras, um token JWS. O cabeçalho descreve o tipo de paylod e o algoritmo de assinatura.
Header:
{ "typ" : "JWT", "alg" : "HS256" }
Payload (retirado do RFC7515):
{ "iss" : "joe", "exp" : 1300819380, "<http://example.com/is_root>" : true }
O token completo assinado e codificado em Base64URL é uma sequência de 168 caracteres
:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4M
TkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQnf_uy1ZrKiO9F4vq
hK7mXrqIbDS799K0DhfDi5g0im8
Agora vamos comparar com um token Branca com exatamente o mesmo payload.
O resultado é um token de 148 caracteres
. No entanto, diferente do JWT acima, que é apenas autenticado, o token Branca também é criptografado.
4ghanLf33KQKBdEKvL5BpAUWXW6YzPbep54y9211upTQx7tzS2smFO5TWUw7PUdNvPh18
2FUIvQkZfp8kAk3XaE1xVQhhhApErJiIjgw4aC6gyOzmTwFvERIkkw2x2SLjvzHYjTA1f
7ihVL06Xh
Podemos otimizar um pouco esse exemplo.
Como o token Branca tem um timestamp no cabeçalho, podemos nos livrar do claim exp
.
Na realidade, o timestamp deve ser o momento em que o token foi gerado. A expiração é verificada pelo consumidor quando o token é decodificado.
Agora temos 125 caracteres
, mas ainda temos todos os recursos do JWT original:
92FHUGUxd0EHJkHRnHtX1XuTHzJBzD2BHH0LhOWBWloRP5pmZ0TpGNUhBEMmjnm1ZpfB7
4Deba2xGshuewIpvWpGDP5xgOi8OAro7h79Lc10QPa7rtyWuYo76XzT
Ainda podemos reduzir o tamanho do token usando um serializador binário como MessagePack ou Protocol Buffers. Isso reduziria o token para 112 caracteres
.
Seja o primeiro a comentar