HS* JWT)RS* , PS* , ES* e EdDSA )boringUma nova implementação do JWT (JSON Web Tokens) para ferrugem que se concentra na simplicidade, evitando armadilhas comuns de segurança JWT.
jwt-simple é poucopinado e suporta todos os algoritmos de autenticação e assinatura comumente implantados:
| Nome do algoritmo JWT | Descrição |
|---|---|
HS256 | HMAC-SHA-256 |
HS384 | HMAC-SHA-384 |
HS512 | HMAC-SHA-512 |
BLAKE2B | Blake2b-256 |
RS256 | RSA com PKCS#1V1.5 Padding / SHA-256 |
RS384 | RSA com PKCS#1V1.5 Padding / SHA-384 |
RS512 | RSA com PKCS#1V1.5 Padding / SHA-512 |
PS256 | RSA com PSS Padding / SHA-256 |
PS384 | RSA com PSS Padding / SHA-384 |
PS512 | RSA com PSS Padding / SHA-512 |
ES256 | ECDSA sobre P256 / SHA-256 |
ES384 | ECDSA sobre P384 / SHA-384 |
ES256K | ECDSA sobre Secp256k1 / SHA-256 |
EdDSA | ED25519 |
jwt-simple pode ser compilado pela caixa para WebAssembly/Wasi. É totalmente compatível com o serviço de computação rapidamente.
IMPORTANTE: O objetivo da JWT é verificar se os dados foram criados por uma parte conhecendo uma chave secreta. Ele não fornece nenhum tipo de confidencialidade: os dados do JWT são simplesmente codificados como base64 e não são criptografados.
cargo.toml :
[ dependencies ]
jwt-simple = " 0.12 "Ferrugem:
use jwt_simple :: prelude :: * ; Os erros são retornados como Valores jwt_simple::Error (Alias para o tipo de Error da caixa thiserror ).
HS* JWT)Os esquemas de autenticação usam a mesma chave para criar e verificar tokens. Em outras palavras, ambas as partes precisam confiar, ou então, o verificador também pode criar tokens arbitrários.
Criação -chave:
use jwt_simple :: prelude :: * ;
// create a new key for the `HS256` JWT algorithm
let key = HS256Key :: generate ( ) ; Uma chave pode ser exportada como bytes com key.to_bytes() e restaurada com HS256Key::from_bytes() .
Criação simbólica:
/// create claims valid for 2 hours
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) ;
let token = key . authenticate ( claims ) ? ;-> Feito!
let claims = key . verify_token :: < NoCustomClaims > ( & token , None ) ? ;-> Feito! Nenhuma etapa adicional necessária.
Expiração das chaves, tempo de início, tags de autenticação etc. são verificados automaticamente. A função falha com JWTError::InvalidAuthenticationTag se a tag de autenticação for inválida para a chave fornecida.
O conjunto completo de reivindicações pode ser inspecionado no objeto claims se necessário. NoCustomClaims significa que apenas o conjunto padrão de reivindicações é usado pelo aplicativo, mas as reivindicações definidas pelo aplicativo também podem ser suportadas.
Etapas de verificação extras podem opcionalmente ser ativadas por meio da estrutura ValidationOptions :
let mut options = VerificationOptions :: default ( ) ;
// Accept tokens that will only be valid in the future
options . accept_future = true ;
// Accept tokens even if they have expired up to 15 minutes after the deadline,
// and/or they will be valid within 15 minutes.
// Note that 15 minutes is the default, since it is very common for clocks to be slightly off.
options . time_tolerance = Some ( Duration :: from_mins ( 15 ) ) ;
// Reject tokens if they were issued more than 1 hour ago
options . max_validity = Some ( Duration :: from_hours ( 1 ) ) ;
// Reject tokens if they don't include an issuer from that set
options . allowed_issuers = Some ( HashSet :: from_strings ( & [ "example app" ] ) ) ;
// see the documentation for the full list of available options
let claims = key . verify_token :: < NoCustomClaims > ( & token , Some ( options ) ) ? ; Observe que allowed_issuers e allowed_audiences não são strings, mas conjuntos de strings (usando o tipo de HashSet da biblioteca padrão da ferrugem), pois o aplicativo pode permitir vários valores de retorno.
RS* , PS* , ES* e EdDSA )Uma assinatura requer um par chave: uma chave secreta usada para criar tokens e uma chave pública que só pode verificá -los.
Sempre use um esquema de assinatura se ambas as partes não confiarem uma na outra, como os tokens trocados entre os clientes e os provedores de API.
Criação -chave:
use jwt_simple :: prelude :: * ;
// create a new key pair for the `ES256` JWT algorithm
let key_pair = ES256KeyPair :: generate ( ) ;
// a public key can be extracted from a key pair:
let public_key = key_pair . public_key ( ) ; use jwt_simple :: prelude :: * ;
// create a new key pair for the `ES384` JWT algorithm
let key_pair = ES384KeyPair :: generate ( ) ;
// a public key can be extracted from a key pair:
let public_key = key_pair . public_key ( ) ;As chaves podem ser exportadas como bytes para reutilização posterior e importadas de bytes ou, para RSA, a partir de parâmetros individuais, dados codificados por Der ou dados codificados por PEM.
Criação de pares de chaves da RSA, usando a importação OpenSSL e PEM da chave secreta:
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -outform PEM -pubout -out public.pem let key_pair = RS384KeyPair :: from_pem ( private_pem_file_content ) ? ;
let public_key = RS384PublicKey :: from_pem ( public_pem_file_content ) ? ; A criação e verificação do token funcionam da mesma maneira que nos algoritmos HS* , exceto que os tokens são criados com um par de chaves e verificados usando a chave pública correspondente.
Criação simbólica:
/// create claims valid for 2 hours
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) ;
let token = key_pair . sign ( claims ) ? ;Verificação do token:
let claims = public_key . verify_token :: < NoCustomClaims > ( & token , None ) ? ;As opções de verificação disponíveis são idênticas às usadas com algoritmos simétricos.
Os objetos de reivindicação suportam todas as reivindicações padrão por padrão e podem ser definidas diretamente ou através de ajudantes convenientes:
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) .
with_issuer ( "Example issuer" ) . with_subject ( "Example subject" ) ; Mas reivindicações definidas por aplicativos também podem ser definidas. Eles simplesmente precisam estar presentes em um tipo serializável (isso requer a caixa de serde ):
# [ derive ( Serialize , Deserialize ) ]
struct MyAdditionalData {
user_is_admin : bool ,
user_country : String ,
}
let my_additional_data = MyAdditionalData {
user_is_admin : false ,
user_country : "FR" . to_string ( ) ,
} ;Criação de reivindicações com dados personalizados:
let claims = Claims :: with_custom_claims ( my_additional_data , Duration :: from_secs ( 30 ) ) ;Verificação de reclamação com dados personalizados. Observe a presença do tipo de dados personalizado:
let claims = public_key . verify_token :: < MyAdditionalData > ( & token , None ) ? ;
let user_is_admin = claims . custom . user_is_admin ;Propriedades como o principal identificador podem ser úteis antes da verificação da tag ou da assinatura para escolher a chave certa de um conjunto.
let metadata = Token :: decode_metadata ( & token ) ? ;
let key_id = metadata . key_id ( ) ;
let algorithm = metadata . algorithm ( ) ;
// all other standard properties are also accessibleIMPORTANTE: Nem o ID principal nem o algoritmo podem ser confiáveis. Esta é uma falha de design não acessível do padrão JWT.
Como resultado, algorithm deve ser usado apenas para fins de depuração e nunca selecionar um tipo de chave. Da mesma forma, key_id deve ser usado apenas para selecionar uma chave em um conjunto de chaves feitas para o mesmo algoritmo.
No mínimo, a verificação usando HS* deve ser proibida se um esquema de assinatura foi originalmente usado para criar o token.
Os principais identificadores indicam aos verificadores qual chave pública (ou chave compartilhada) deve ser usada para verificação. Eles podem ser anexados a qualquer momento às chaves compartilhadas existentes, pares de chaves e chaves públicas:
let public_key_with_id = public_key . with_key_id ( & "unique key identifier" ) ; Em vez de delegar isso a aplicativos, jwt-simple também pode criar esse identificador para uma chave existente:
let key_id = public_key . create_key_id ( ) ;Isso cria um identificador codificado por texto para a chave, a anexa e o retorna.
Se um identificador tiver sido anexado a uma chave compartilhada ou a um par de chaves, os tokens criados com eles o incluirão.
jwt-simple inclui mecanismos para mitigar ataques de repetição:
create_nonce() . O procedimento de verificação pode rejeitar posteriormente qualquer token que não inclua a opção de verificação NONCE ( required_nonce ). O código de desenvolvimento inclui um recurso de carga cwt que permite a análise experimental e a validação dos tokens CWT.
Observe que a CWT não suporta reivindicações personalizadas. Os identificadores necessários ainda não foram padronizados.
Além disso, as caixas de ferrugem existentes para a deserivação de JSON e CBOR não são seguras. Uma parte não confiável pode enviar um objeto serializado que requer muita memória e CPU para deseralizar. Band-AIDS foram adicionados ao JSON, mas com as ferramentas de ferrugem atuais, seria complicado fazer pelo CBOR.
Como mitigação, é altamente recomendável rejeitar tokens que seriam muito grandes no contexto do seu aplicativo. Isso pode ser feito com a opção de verificação max_token_length .
boring Como uma solução alternativa temporária para problemas de portabilidade com uma das dependências (a caixa boring ), esta biblioteca pode ser compilada para usar apenas implementações de ferrugem.
Para fazer isso, importe o caixote com default-features=false, features=["pure-rust"] na sua configuração de carga.
Não faça isso incondicionalmente. Isso é necessário apenas para configurações e metas muito específicos e apenas até que problemas com a caixa boring sejam resolvidos. A maneira de configurar isso na carga também pode mudar em versões futuras.
Construções estáticas direcionadas à biblioteca musl não exigem essa solução alternativa. Basta usar cargo-zigbuild para construir seu projeto.
O alvo wasm32-freestanding (ainda às vezes chamado wasm32-unknown-unknown em ferrugem) é suportado (como em "It Compile").
No entanto, o uso de uma implementação nativa de JavaScript é altamente recomendado. Existem implementações JWT de alta qualidade no JavaScript, alavancando a API WebCrypto, que fornecem melhores garantias de desempenho e segurança do que um módulo WebAssembly.
Esta caixa não é um endosso do JWT. O JWT é um design horrível, e um dos muitos exemplos de que "mas esse é um padrão" não significa necessariamente que é bom.
Eu recomendo o PASETO ou o biscoito se você controlar a criação e a verificação do token.
No entanto, o JWT ainda é amplamente utilizado no setor e permanece absolutamente obrigatório para se comunicar com as APIs populares.
Esta caixa foi projetada para:
None por razões óbvias).