HS* JWTアルゴリズム)の例RS* 、 PS* 、 ES* 、 EdDSAアルゴリズム)例boring枠での編集の問題を中心に取り組んでいます一般的なJWTセキュリティの落とし穴を避けながら、シンプルさに焦点を当てた錆のための新しいJWT(JSON Web Tokens)の実装。
jwt-simpleは感染しておらず、一般的に展開されているすべての認証と署名アルゴリズムをサポートしています。
| JWTアルゴリズム名 | 説明 |
|---|---|
HS256 | HMAC-SHA-256 |
HS384 | HMAC-SHA-384 |
HS512 | HMAC-SHA-512 |
BLAKE2B | Blake2B-256 |
RS256 | PKCS#1V1.5パディング / SHA-256を備えたRSA |
RS384 | PKCS#1V1.5パディング / SHA-384を備えたRSA |
RS512 | PKCS#1V1.5パディング / SHA-512を備えたRSA |
PS256 | PSSパディング / SHA-256を備えたRSA |
PS384 | PSSパディング / SHA-384を備えたRSA |
PS512 | PSSパディング / SHA-512を備えたRSA |
ES256 | P256 / SHA-256を超えるECDSA |
ES384 | P384 / SHA-384を超えるECDSA |
ES256K | SECP256K1 / SHA-256を超えるECDSA |
EdDSA | ED25519 |
jwt-simple 、箱から出してWebAssembly/WASIにコンパイルできます。高速コンピューティートサービスと完全に互換性があります。
重要:JWTの目的は、秘密の鍵を知っている当事者によってデータが作成されていることを確認することです。それはいかなる種類の機密性も提供しません。JWTデータは単純にbase64としてエンコードされ、暗号化されていません。
cargo.toml :
[ dependencies ]
jwt-simple = " 0.12 "さび:
use jwt_simple :: prelude :: * ;エラーはjwt_simple::Error値( thiserror crateのErrorタイプのエイリアス)として返されます。
HS* JWTアルゴリズム)の例認証スキームは、トークンを作成および検証するために同じキーを使用します。言い換えれば、両当事者は最終的にお互いを信頼する必要があります。そうしないと、検証者が任意のトークンを作成することもできます。
キー作成:
use jwt_simple :: prelude :: * ;
// create a new key for the `HS256` JWT algorithm
let key = HS256Key :: generate ( ) ;キーは、 key.to_bytes()を使用してバイトとしてエクスポートし、 HS256Key::from_bytes()で復元できます。
トークンの作成:
/// create claims valid for 2 hours
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) ;
let token = key . authenticate ( claims ) ? ;- >終了!
let claims = key . verify_token :: < NoCustomClaims > ( & token , None ) ? ;- >終了!追加の手順は必要ありません。
主要な有効期限、開始時間、認証タグなどが自動的に検証されます。 JWTError::InvalidAuthenticationTagで機能が失敗します。特定のキーに対して認証タグが無効である場合。
必要に応じて、 claimsオブジェクトで一連のクレームを検査できます。 NoCustomClaimsは、標準のクレームセットのみがアプリケーションで使用されることを意味しますが、アプリケーション定義のクレームもサポートできます。
追加の検証手順は、 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 ) ) ? ; allowed_issuersおよびallowed_audiences文字列ではなく、一連の文字列(Rust Standard LibraryのHashSetタイプを使用)であることに注意してください。
RS* 、 PS* 、 ES* 、 EdDSAアルゴリズム)例署名にはキーペアが必要です。トークンを作成するために使用される秘密キーと、それらを検証するだけの公開キーです。
クライアントとAPIプロバイダーの間で交換されるトークンなど、両方の当事者が最終的に互いに信頼しない場合は、常に署名スキームを使用します。
キー作成:
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 ( ) ;キーは、後で再利用するためにバイトとしてエクスポートし、バイトから、またはRSAの場合、個々のパラメーター、DerエンコードデータまたはPEMエンコードデータからインポートできます。
RSAキーペアの作成、OpenSSLとSecret KeyのPEMインポートを使用してください:
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 ) ? ;トークンの作成と検証は、トークンがキーペアで作成され、対応する公開キーを使用して検証されていることを除いて、 HS*アルゴリズムと同じように機能します。
トークンの作成:
/// create claims valid for 2 hours
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) ;
let token = key_pair . sign ( claims ) ? ;トークン検証:
let claims = public_key . verify_token :: < NoCustomClaims > ( & token , None ) ? ;利用可能な検証オプションは、対称アルゴリズムで使用されるものと同一です。
クレームオブジェクトはデフォルトですべての標準クレームをサポートし、直接または便利なヘルパーを介して設定できます。
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) .
with_issuer ( "Example issuer" ) . with_subject ( "Example subject" ) ;ただし、アプリケーション定義のクレームも定義できます。これらは単にシリアル化可能なタイプで存在する必要があります(これにはserde Crateが必要です):
# [ 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 ( ) ,
} ;カスタムデータを使用して作成の主張:
let claims = Claims :: with_custom_claims ( my_additional_data , Duration :: from_secs ( 30 ) ) ;カスタムデータを使用して検証を請求します。カスタムデータ型の存在に注意してください。
let claims = public_key . verify_token :: < MyAdditionalData > ( & token , None ) ? ;
let user_is_admin = claims . custom . user_is_admin ;キー識別子などのプロパティは、セットから正しいキーを選択するために、タグまたは署名検証の前に役立ちます。
let metadata = Token :: decode_metadata ( & token ) ? ;
let key_id = metadata . key_id ( ) ;
let algorithm = metadata . algorithm ( ) ;
// all other standard properties are also accessible重要:キーIDもアルゴリズムも信頼できません。これは、JWT標準の不可能な設計上の欠陥です。
その結果、 algorithmデバッグ目的でのみ使用し、キータイプを選択しないでください。同様に、 key_id 、同じアルゴリズム用に作成された一連のキーのキーを選択するためにのみ使用する必要があります。
最低限、署名スキームがトークンを作成するために最初に使用された場合、 HS*を使用した検証を禁止する必要があります。
キー識別子は、検証に使用する公開キー(または共有キー)を検証する必要があるものを検証に示します。既存の共有キー、キーペア、パブリックキーにいつでも取り付けることができます。
let public_key_with_id = public_key . with_key_id ( & "unique key identifier" ) ;これをアプリケーションに委任する代わりに、 jwt-simple既存のキーのこのような識別子を作成することもできます。
let key_id = public_key . create_key_id ( ) ;これにより、キーのテキストエンコード識別子が作成され、添付され、返されます。
識別子が共有キーまたはキーペアに接続されている場合、それらと一緒に作成されたトークンにはそれが含まれます。
jwt-simpleには、リプレイ攻撃を緩和するメカニズムが含まれています。
create_nonce()クレーム関数を使用して、Noncesを作成して新しいトークンに添付できます。検証手順は、予想されるNonCE( required_nonce検証オプション)を含まないトークンを後で拒否できます。開発コードには、CWTトークンの実験的解析と検証を可能にするcwt貨物機能が含まれています。
CWTはカスタムクレームをサポートしていないことに注意してください。必要な識別子はまだ標準化されていません。
また、JSONとCborの脱介入の既存の錆びは安全ではありません。信頼されていない当事者は、多くのメモリとCPUを脱皮する必要があるシリアル化されたオブジェクトを送信できます。 JSONのためにバンドエイドが追加されていますが、現在の錆ツールでは、CBORのために行うのが難しいでしょう。
緩和として、アプリケーションのコンテキストでは大きすぎるトークンを拒否することを強くお勧めします。これは、 max_token_length VISILISITIONオプションで実行できます。
boring枠での編集の問題を中心に取り組んでいます依存関係の1つ( boring木枠)の携帯性問題の一時的な回避策として、このライブラリは錆の実装のみを使用するようにコンパイルできます。
そうするために、貨物構成にdefault-features=false, features=["pure-rust"]でクレートをインポートします。
無条件にそれをしないでください。これは、非常に特定のセットアップとターゲットにのみ必要であり、 boring木枠の問題が解決されるまでのみです。これを貨物で構成する方法も、将来のバージョンで変更される可能性があります。
muslライブラリをターゲットにする静的ビルドは、その回避策を必要としません。 cargo-zigbuildを使用してプロジェクトを構築してください。
wasm32-freestandingターゲット(錆びにはまだwasm32-unknown-unknown呼ばれることもあります)がサポートされています(「ITコンパイル」のように)。
ただし、代わりにネイティブJavaScriptの実装を使用することを強くお勧めします。 JavaScriptには、WebCrypto APIを活用する高品質のJWT実装があり、WebSasemblyモジュールよりも優れたパフォーマンスとセキュリティの保証を提供します。
このクレートはJWTの支持ではありません。 JWTはひどいデザインであり、「これは標準である」という多くの例の1つは、必ずしもそれが良いことを意味するわけではありません。
トークンの作成と検証の両方を制御する場合は、代わりにパセトまたはビスケットを強くお勧めします。
ただし、JWTは依然として業界で広く使用されており、人気のあるAPIとの通信に絶対に必須です。
このクレートは次のように設計されています。
None選択肢をED25519に制限したいと思いますが、既存のAPIに接続するには他の方法が必要です。