Skip to content

Instantly share code, notes, and snippets.

@insinfo
Created June 29, 2025 18:57
Show Gist options
  • Select an option

  • Save insinfo/700ce4a91014a9fdc9471c635ce40e99 to your computer and use it in GitHub Desktop.

Select an option

Save insinfo/700ce4a91014a9fdc9471c635ce40e99 to your computer and use it in GitHub Desktop.

Documentação da Biblioteca JOSE 0.3.4 para Dart

Esta é uma documentação completa para a biblioteca jose em Dart. A biblioteca implementa os padrões de Javascript Object Signing and Encryption (JOSE), fornecendo funcionalidades para JWS, JWE, JWK, JWT e JWA.

Índice


Visão Geral da Biblioteca

A biblioteca jose é uma implementação dos padrões JOSE definidos em várias RFCs da IETF. Ela permite a criação, manipulação, assinatura e criptografia de dados usando estruturas JSON.

Os principais componentes exportados são:

  • jose.dart: Classes centrais e estruturas base.
  • jwk.dart: Manipulação de chaves criptográficas (JSON Web Key).
  • jws.dart: Assinaturas digitais (JSON Web Signature).
  • jwe.dart: Criptografia de conteúdo (JSON Web Encryption).
  • jwt.dart: Tokens de acesso (JSON Web Token).
  • jwa.dart: Definições de algoritmos (JSON Web Algorithm).

Core (jose.dart)

Este módulo contém as classes e estruturas fundamentais que formam a base para JWS e JWE.

Classe JoseHeader

Representa os parâmetros de cabeçalho JOSE, que são comuns a JsonWebSignature e JsonWebEncryption.

Construtores

  • JoseHeader.fromJson(Map<String, dynamic> json): Constrói um JoseHeader a partir de um mapa JSON.
  • JoseHeader.fromBase64EncodedString(String encodedString): Constrói um JoseHeader a partir de sua representação JSON codificada em base64url.

Propriedades

  • algorithm (String?): Identifica o algoritmo criptográfico (alg).
  • jwkSetUrl (Uri?): URL para um conjunto de chaves públicas JWK (jku).
  • jsonWebKey (JsonWebKey?): A chave pública JWK embutida (jwk).
  • keyId (String?): Um hint para identificar a chave usada (kid).
  • type (String?): O tipo de mídia do objeto JOSE completo (typ), como "JWT".
  • contentType (String?): O tipo de mídia do payload (cty).
  • critical (List<String>?): Indica extensões que devem ser entendidas e processadas (crit).
  • encryptionAlgorithm (String?): O algoritmo de criptografia de conteúdo (usado apenas em JWE) (enc).
  • compressionAlgorithm (String?): O algoritmo de compressão (usado apenas em JWE) (zip).

Classe Abstrata JoseObject

Classe base para JsonWebSignature e JsonWebEncryption.

Propriedades

  • data (List<int>): Os dados binários contidos no objeto (payload para JWS, ciphertext para JWE).
  • recipients (List<JoseRecipient>): O conteúdo por destinatário (assinaturas para JWS, chaves criptografadas para JWE).
  • commonHeader (JoseHeader): Um cabeçalho unificado contendo os parâmetros compartilhados e comuns entre os destinatários.
  • commonProtectedHeader (JoseHeader): Um cabeçalho contendo apenas os parâmetros protegidos que são comuns.

Fábricas (Factories)

  • JoseObject.fromJson(Map<String, dynamic> json): Constrói um JWS ou JWE a partir de sua representação JSON.
  • JoseObject.fromCompactSerialization(String serialization): Constrói um JWS ou JWE a partir de sua representação compacta.

Métodos

  • toCompactSerialization(): Serializa o objeto para o formato de string compacta. Lança uma exceção se houver múltiplos destinatários/assinaturas.
  • toJson(): Serializa o objeto para sua representação JSON.
  • verify(JsonWebKeyStore keyStore): Verifica se a assinatura/criptografia do objeto é válida usando as chaves do keyStore. Retorna Future<bool>.
  • getPayload(JsonWebKeyStore keyStore, {List<String>? allowedAlgorithms}): Tenta descriptografar/verificar o objeto usando as chaves do keyStore e retorna o payload (JosePayload). Lança uma JoseException em caso de falha.

Classe Abstrata JoseRecipient

Representa o conteúdo específico para cada destinatário de um JoseObject.

Propriedades

  • protectedHeader (JsonObject?): Parâmetros de cabeçalho por destinatário que são protegidos por integridade.
  • unprotectedHeader (JsonObject?): Parâmetros de cabeçalho por destinatário que não são protegidos.
  • header (JoseHeader): Cabeçalho combinado (protegido e não protegido).
  • data (List<int>): Os dados binários (assinatura para JWS, chave de conteúdo criptografada para JWE).

Classe JosePayload

Representa o payload de um JWS ou JWE após a verificação/descriptografia.

Propriedades

  • data (List<int>): Os dados binários do payload.
  • protectedHeader (JsonObject?): Os parâmetros de cabeçalho que foram protegidos.
  • stringContent (String): O conteúdo do payload como uma string UTF-8.
  • jsonContent (dynamic): O conteúdo do payload decodificado como JSON.
  • mediaType (String?): O tipo de mídia do payload (parâmetro cty do cabeçalho).

Classe Abstrata JoseObjectBuilder<T>

Classe base para os builders JsonWebSignatureBuilder e JsonWebEncryptionBuilder.

Métodos e Propriedades

  • content (setter): Define o payload (pode ser String, List<int> ou um objeto JSON).
  • setProtectedHeader(String key, dynamic value): Define um parâmetro de cabeçalho protegido compartilhado.
  • addRecipient(JsonWebKey? key, {String? algorithm}): Adiciona um destinatário (com sua chave e algoritmo) para assinar ou criptografar o objeto.
  • build(): Constrói o objeto JoseObject final.

Exceção JoseException

Uma exceção personalizada lançada pela biblioteca para indicar erros relacionados a operações JOSE.


JSON Web Algorithms (jwa.dart)

Este módulo define os algoritmos criptográficos suportados, conforme especificado na RFC 7518.

Classe JsonWebAlgorithm

Representa um algoritmo criptográfico JWA.

Propriedades

  • name (String): O nome do algoritmo (ex: HS256, RS256).
  • type (String): A família do algoritmo (ex: oct, RSA, EC).
  • use (String): O uso pretendido do algoritmo (sig para assinatura, enc para criptografia, key para gerenciamento de chaves).

Constantes Estáticas

A classe define constantes para todos os algoritmos suportados, como:

  • hs256, hs384, hs512 (HMAC com SHA)
  • rs256, rs384, rs512 (RSASSA-PKCS1-v1_5 com SHA)
  • es256, es384, es512, es256k (ECDSA)
  • rsa1_5, rsa_oaep, rsa_oaep_256 (Criptografia com RSA)
  • a128kw, a192kw, a256kw (AES Key Wrap)
  • a128cbc_hs256, a192cbc_hs384, a256cbc_hs512 (AES-CBC com HMAC-SHA)
  • a128gcm, a192gcm, a256gcm (AES-GCM)

Métodos Estáticos

  • getByName(String? name): Retorna uma instância de JsonWebAlgorithm pelo seu nome.
  • find({String? operation, String? keyType}): Encontra algoritmos que correspondem a uma operação ou tipo de chave.

Métodos de Instância

  • generateRandomKey({int? keyBitLength}): Gera uma JsonWebKey aleatória adequada para este algoritmo.

JSON Web Encryption (jwe.dart)

Este módulo implementa a especificação JSON Web Encryption (JWE) para criptografar conteúdo.

Classe JsonWebEncryption

Representa um objeto JWE com conteúdo criptografado.

Construtores/Fábricas

  • JsonWebEncryption.fromCompactSerialization(String serialization): Constrói um JWE a partir de sua representação compacta.
  • JsonWebEncryption.fromJson(Map<String, dynamic> json): Constrói um JWE a partir de sua representação JSON (geral ou achatada).

Propriedades Adicionais

  • initializationVector (List<int>): O Vetor de Inicialização (IV) usado na criptografia.
  • authenticationTag (List<int>): A tag de autenticação gerada pela criptografia autenticada.
  • additionalAuthenticatedData (List<int>?): Dados adicionais que são protegidos por integridade, mas não criptografados.

Classe JsonWebEncryptionBuilder

Builder para criar objetos JsonWebEncryption.

Propriedades

  • encryptionAlgorithm (String?): O algoritmo de criptografia de conteúdo a ser usado (ex: A128CBC-HS256).
  • additionalAuthenticatedData (List<int>?): Define os dados adicionais autenticados.

Métodos

  • build(): Constrói o objeto JsonWebEncryption. Exige que um payload, um algoritmo de criptografia e pelo menos um destinatário tenham sido definidos.

JSON Web Key (jwk.dart)

Este módulo implementa a especificação JSON Web Key (JWK) para representar chaves criptográficas.

Classe JsonWebKey

Representa uma chave criptográfica no formato JWK.

Construtores/Fábricas

  • JsonWebKey.fromJson(Map<String, dynamic> json): A partir de um mapa JSON.
  • JsonWebKey.fromCryptoKeys({PublicKey?, PrivateKey?}): A partir de chaves da biblioteca crypto_keys.
  • JsonWebKey.rsa(...), JsonWebKey.ec(...), JsonWebKey.symmetric(...): Construtores de conveniência para tipos de chave específicos.
  • JsonWebKey.fromPem(String pem): Analisa uma chave em formato PEM.
  • JsonWebKey.generate(String? algorithm): Gera uma nova chave aleatória para um algoritmo específico.

Propriedades

  • keyType (String): O tipo de chave (kty), como RSA, EC, oct.
  • keyId (String?): O identificador da chave (kid).
  • algorithm (String?): O algoritmo pretendido para uso com a chave (alg).
  • publicKeyUse (String?): O uso pretendido da chave pública (use), como sig ou enc.
  • keyOperations (Set<String>?): As operações permitidas para a chave (key_ops), como sign, verify, encrypt, decrypt.

Métodos de Operação

  • sign(List<int> data, {String? algorithm}): Cria uma assinatura digital dos dados.
  • verify(List<int> data, List<int> signature, {String? algorithm}): Verifica uma assinatura digital.
  • encrypt(...): Criptografa dados.
  • decrypt(...): Descriptografa dados.
  • wrapKey(JsonWebKey key, ...): Criptografa outra chave (key wrapping).
  • unwrapKey(List<int> data, ...): Descriptografa uma chave (key unwrapping).

Classe JsonWebKeySet

Representa um conjunto de JsonWebKeys.

Propriedades

  • keys (List<JsonWebKey>): A lista de chaves no conjunto.

Classe JsonWebKeyStore

Um armazenamento para procurar e encontrar JsonWebKeys.

Métodos

  • addKey(JsonWebKey key): Adiciona uma chave individual.
  • addKeySet(JsonWebKeySet keys): Adiciona um conjunto de chaves.
  • addKeySetUrl(Uri url): Adiciona uma URL de onde um conjunto de chaves pode ser baixado.
  • findJsonWebKeys(JoseHeader header, String operation): Encontra chaves aplicáveis para uma determinada operação e cabeçalho JOSE.

Classe JsonWebKeySetLoader

Classe abstrata para carregar JsonWebKeySet de uma URL. A implementação padrão (DefaultJsonWebKeySetLoader) lida com esquemas http(s) e data, com cache para requisições HTTP.


JSON Web Signature (jws.dart)

Este módulo implementa a especificação JSON Web Signature (JWS) para assinar conteúdo.

Classe JsonWebSignature

Representa um objeto JWS com conteúdo assinado.

Construtores/Fábricas

  • JsonWebSignature.fromCompactSerialization(String serialization): Constrói um JWS a partir de sua representação compacta.
  • JsonWebSignature.fromJson(Map<String, dynamic> json): Constrói um JWS a partir de sua representação JSON (geral ou achatada).

Propriedades

  • unverifiedPayload (JosePayload): Retorna o payload sem verificar a assinatura. Use com cuidado!

Classe JsonWebSignatureBuilder

Builder para criar objetos JsonWebSignature.

Métodos

  • build(): Constrói o objeto JsonWebSignature. Exige que um payload e pelo menos um destinatário (para assinatura) tenham sido definidos.

JSON Web Token (jwt.dart)

Este módulo implementa a especificação JSON Web Token (JWT), que é comumente serializado como um JWS.

Classe JsonWebTokenClaims

Representa o conjunto de claims (reivindicações) de um JWT.

Propriedades (Claims Padrão)

  • issuer (Uri?): O emissor do token (iss).
  • subject (String?): O "assunto" do token (sub).
  • audience (List<String>?): Os destinatários pretendidos do token (aud).
  • expiry (DateTime?): A data de expiração do token (exp).
  • notBefore (DateTime?): A data antes da qual o token não deve ser aceito (nbf).
  • issuedAt (DateTime?): A data em que o token foi emitido (iat).
  • jwtId (String?): Um identificador único para o token (jti).

Métodos

  • validate(...): Valida as claims contra critérios como tempo de expiração, emissor e audiência. Retorna uma lista de exceções se a validação falhar.

Classe JsonWebToken

Representa um JWT.

Construtores/Fábricas

  • JsonWebToken.unverified(String serialization): Decodifica um JWT de uma string JWS compacta, sem verificar a assinatura.
  • JsonWebToken.decodeAndVerify(String serialization, JsonWebKeyStore keyStore, ...): O método principal e seguro para decodificar e verificar/descriptografar um JWT.

Propriedades e Métodos

  • claims (JsonWebTokenClaims): As claims contidas no token.
  • toCompactSerialization(): Serializa o JWT de volta para sua forma compacta.
  • isVerified (bool?): Retorna true se o token foi verificado com sucesso, false se a verificação falhou, ou null se não foi tentada.
  • verify(JsonWebKeyStore keyStore, ...): Tenta verificar a assinatura do JWT.

Utilitários (util.dart)

Contém classes e funções auxiliares usadas em toda a biblioteca.

Classe JsonObject

Uma classe base para objetos JSON imutáveis, com funcionalidades de (de)serialização e acesso a propriedades tipadas.

Funções Auxiliares

  • decodeBase64EncodedBytes(String encodedString): Decodifica uma string base64url para bytes.
  • encodeBase64EncodedBytes(List<int> data): Codifica bytes para uma string base64url.
  • encodeBigInt(BigInt? v): Codifica um BigInt para base64url, como exigido pelo padrão JWK.
  • safeUnion(...) e commonUnion(...): Funções para mesclar mapas de cabeçalho.

Documentação Detalhada da Biblioteca jose para Dart/Flutter

1. Visão Geral

A biblioteca jose para Dart é uma implementação robusta das especificações IETF JavaScript Object Signing and Encryption (JOSE).
Ela fornece as ferramentas necessárias para trabalhar com os padrões de segurança mais comuns – fundamentais em sistemas de autenticação e autorização modernos como OpenID Connect e OAuth 2.0.

Padrões contemplados

  • JWSJSON Web Signature (RFC 7515): cria e verifica assinaturas digitais em payloads, garantindo integridade e autenticidade.
  • JWEJSON Web Encryption (RFC 7516): criptografa conteúdos, garantindo confidencialidade.
  • JWKJSON Web Key (RFC 7517): representa chaves criptográficas em JSON, facilitando distribuição e uso de chaves públicas.
  • JWAJSON Web Algorithm (RFC 7518): define os algoritmos criptográficos utilizados em JWS e JWE.
  • JWTJSON Web Token (RFC 7519): padrão para criar tokens que carregam claims; muito usado para transmitir identidade entre provedor de identidade e aplicação.

2. Instalação

Adicione a dependência no arquivo pubspec.yaml:

dependencies:
  jose: ^0.3.3   # Use a versão mais recente disponível em pub.dev

Depois execute:

dart pub get        # ou
flutter pub get

3. Principais Conceitos e Classes

Classe Descrição
JsonWebKey Representa uma chave criptográfica (simétrica, RSA ou EC). Base para assinatura e criptografia.
JsonWebKeySet Coleção de JsonWebKey – normalmente exposta por provedores em /.well‑known/jwks.json.
JsonWebKeyStore “Cofre” local de chaves utilizado para localizar a chave correta na verificação ou descriptografia.
JsonWebSignatureBuilder Constrói um JWS (e, portanto, um JWT).
JsonWebEncryptionBuilder Constrói um JWE.
JsonWebToken Representa um JWT; contém as claims e pode ser verificado.
JoseHeader Cabeçalho de um JWS ou JWE: inclui algoritmo (alg), identificador da chave (kid) etc.

4. Exemplos de Uso

4.1 Gerando Chaves Criptográficas (JWK)

import 'package:jose/jose.dart';
import 'dart:convert';

void main() {
  // Gera chave RSA 2048 bits para RS256
  final jwk = JsonWebKey.generate('RS256');
  print('Chave JWK completa:');
  print(JsonEncoder.withIndent('  ').convert(jwk.toJson()));

  // Criar JWK somente com parte pública
  final publicKeyJwk = JsonWebKey.fromJson({
    'kty': jwk.keyType,
    'alg': jwk.algorithm,
    'use': 'sig',
    'kid': jwk.keyId,
    'n': jwk['n'],
    'e': jwk['e'],
  });
  print('\nChave JWK pública:');
  print(JsonEncoder.withIndent('  ').convert(publicKeyJwk.toJson()));

  // Exemplo de chave EC (ES256)
  final ecJwk = JsonWebKey.generate('ES256');
  print('\nChave EC JWK:');
  print(JsonEncoder.withIndent('  ').convert(ecJwk.toJson()));
}

Por que usar kid?
O Key ID permite identificar rapidamente qual chave usar durante rotação de chaves.


4.2 Criando e Verificando um JWT

import 'package:jose/jose.dart';
import 'dart:convert';

Future<void> main() async {
  // 1) Gera chave de assinatura
  final signingKey = JsonWebKey.generate('RS256');

  // 2) Define claims
  final claims = JsonWebTokenClaims.fromJson({
    'iss': 'https://my-auth-server.com',
    'sub': 'user-123',
    'aud': ['my-api', 'another-service'],
    'exp': DateTime.now().add(Duration(hours: 1)).millisecondsSinceEpoch ~/ 1000,
    'iat': DateTime.now().millisecondsSinceEpoch ~/ 1000,
    'name': 'John Doe',
    'admin': true,
  });

  // 3) Constrói JWS/JWT
  final builder = JsonWebSignatureBuilder()
    ..jsonContent = claims.toJson()
    ..addRecipient(signingKey, algorithm: 'RS256');

  final jws = builder.build();
  final token = jws.toCompactSerialization();
  print('JWT gerado:\n$token');

  // 4) Verifica token (usando somente a chave pública)
  final publicKey = JsonWebKey.fromJson(
    Map.of(signingKey.toJson())..removeWhere((k, _) => ['d', 'p', 'q'].contains(k)),
  );

  final keyStore = JsonWebKeyStore()..addKey(publicKey);
  final jwt = await JsonWebToken.decodeAndVerify(token, keyStore);

  if (jwt.isVerified == true) {
    print('\nToken verificado!');
    final issues = jwt.claims.validate(
      issuer: Uri.parse('https://my-auth-server.com'),
      clientId: 'my-api',
    );
    print(issues.isEmpty ? 'Claims OK' : 'Problemas: $issues');
  }
}

5. Exemplo Avançado: Provedor OpenID Connect Simples

O provedor oferece:

  1. Endpoint JWKS/.well-known/jwks.json
  2. Endpoint de emissão de id_token/token
import 'package:jose/jose.dart';
import 'dart:convert';

// ---------- Servidor OIDC ----------
final JsonWebKey serverSigningKey = JsonWebKey.generate('RS256')
  ..['use'] = 'sig'
  ..['kid'] = 'key-01-2023';

const issuerUrl = 'https://my-simple-oidc-provider.com';

// JWKS endpoint
String jwksResponse() {
  final pubKey = JsonWebKey.fromJson(
    Map.of(serverSigningKey.toJson())..removeWhere((k, _) => ['d', 'p', 'q'].contains(k)),
  );
  return JsonWebKeySet.fromKeys([pubKey]).toJson();
}

// Emite id_token
String issueIdToken(String userId, String clientId) {
  final claims = JsonWebTokenClaims.fromJson({
    'iss': issuerUrl,
    'sub': userId,
    'aud': [clientId],
    'exp': DateTime.now().add(Duration(minutes: 30)).millisecondsSinceEpoch ~/ 1000,
    'iat': DateTime.now().millisecondsSinceEpoch ~/ 1000,
    'nonce': 'random-nonce',
  });

  final builder = JsonWebSignatureBuilder()
    ..jsonContent = claims.toJson()
    ..addRecipient(serverSigningKey, algorithm: 'RS256');

  return builder.build().toCompactSerialization();
}

// ---------- Cliente ----------
Future<void> validate(String idToken) async {
  final keySet = JsonWebKeySet.fromJson(json.decode(jwksResponse()));
  final keyStore = JsonWebKeyStore()..addKeySet(keySet);

  final jwt = await JsonWebToken.decodeAndVerify(idToken, keyStore);
  if (jwt.isVerified == true) {
    final issues = jwt.claims.validate(
      issuer: Uri.parse(issuerUrl),
      clientId: 'my-awesome-app',
    );
    print(issues.isEmpty ? 'Token válido!' : 'Issues: $issues');
  }
}

// ---------- Execução ----------
Future<void> main() async {
  final token = issueIdToken('user-jane-doe', 'my-awesome-app');
  await validate(token);
}

Fluxo resumido

  1. Servidor gera/par de chaves e disponibiliza a parte pública em /.well‑known/jwks.json.
  2. Cliente busca o JWKS, verifica a assinatura do id_token e valida claims (exp, aud, iss…).
  3. Durante rotação de chaves, um novo kid é publicado — clientes continuam funcionando sem mudanças de código.

⚠️ Segurança em produção

  • Armazene chaves privadas em cofres seguros (HSM, KMS, Secret Manager).
  • Use HTTPS em todos os endpoints.
  • Faça rotação periódica de chaves e valide claims estritamente.

Referências

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment