HS* jwt)RS* , PS* , ES* dan EdDSA )boringImplementasi JWT (JSON Web Token) baru untuk Rust yang berfokus pada kesederhanaan, sambil menghindari jebakan keamanan JWT yang umum.
jwt-simple tidak teropini dan mendukung semua algoritma otentikasi dan tanda tangan yang biasa digunakan:
| Nama Algoritma JWT | Keterangan |
|---|---|
HS256 | HMAC-SHA-256 |
HS384 | HMAC-SHA-384 |
HS512 | HMAC-SHA-512 |
BLAKE2B | Blake2b-256 |
RS256 | RSA dengan PKCS#1V1.5 Padding / SHA-256 |
RS384 | RSA dengan PKCS#1V1.5 Padding / SHA-384 |
RS512 | RSA dengan PKCS#1V1.5 Padding / SHA-512 |
PS256 | RSA dengan PSS Padding / SHA-256 |
PS384 | RSA dengan PSS Padding / SHA-384 |
PS512 | RSA dengan PSS Padding / SHA-512 |
ES256 | ECDSA lebih dari P256 / SHA-256 |
ES384 | ECDSA lebih dari P384 / SHA-384 |
ES256K | ECDSA melalui SecP256K1 / SHA-256 |
EdDSA | ED25519 |
jwt-simple dapat dikompilasi di luar kotak ke WebAssembly/Wasi. Ini sepenuhnya kompatibel dengan layanan komputasi dengan cepat.
Penting: Tujuan JWT adalah untuk memverifikasi bahwa data telah dibuat oleh pihak yang mengetahui kunci rahasia. Itu tidak memberikan kerahasiaan apa pun: data JWT hanya dikodekan sebagai base64, dan tidak dienkripsi.
cargo.toml :
[ dependencies ]
jwt-simple = " 0.12 "Karat:
use jwt_simple :: prelude :: * ; Kesalahan dikembalikan sebagai jwt_simple::Error (alias untuk jenis Error dari peti thiserror ).
HS* jwt)Skema otentikasi menggunakan kunci yang sama untuk membuat dan memverifikasi token. Dengan kata lain, kedua belah pihak perlu saling percaya, atau verifier juga dapat membuat token sewenang -wenang.
Penciptaan kunci:
use jwt_simple :: prelude :: * ;
// create a new key for the `HS256` JWT algorithm
let key = HS256Key :: generate ( ) ; Kunci dapat diekspor sebagai byte dengan key.to_bytes() , dan dipulihkan dengan HS256Key::from_bytes() .
Kreasi Token:
/// create claims valid for 2 hours
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) ;
let token = key . authenticate ( claims ) ? ;-> selesai!
let claims = key . verify_token :: < NoCustomClaims > ( & token , None ) ? ;-> selesai! Tidak diperlukan langkah tambahan.
Kekaringan utama, waktu mulai, tag otentikasi, dll. Secara otomatis diverifikasi. Fungsi gagal dengan JWTError::InvalidAuthenticationTag Jika tag otentikasi tidak valid untuk kunci yang diberikan.
Set lengkap klaim dapat diperiksa di objek claims jika perlu. NoCustomClaims berarti bahwa hanya set standar klaim yang digunakan oleh aplikasi, tetapi klaim yang ditentukan aplikasi juga dapat didukung.
Langkah -langkah verifikasi tambahan secara opsional dapat diaktifkan melalui struktur 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 ) ) ? ; Perhatikan bahwa allowed_issuers dan allowed_audiences bukanlah string, tetapi set string (menggunakan jenis HashSet dari perpustakaan standar karat), karena aplikasi dapat memungkinkan beberapa nilai pengembalian.
RS* , PS* , ES* dan EdDSA )Tanda tangan membutuhkan pasangan kunci: kunci rahasia yang digunakan untuk membuat token, dan kunci publik, yang hanya dapat memverifikasi.
Selalu gunakan skema tanda tangan jika kedua belah pihak pada akhirnya tidak saling percaya, seperti token yang dipertukarkan antara klien dan penyedia API.
Penciptaan kunci:
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 ( ) ;Kunci dapat diekspor sebagai byte untuk digunakan kembali kemudian, dan diimpor dari byte atau, untuk RSA, dari parameter individu, data yang dikodekan atau data yang dikodekan PEM.
Pembuatan Pasangan Kunci RSA, menggunakan OpenSSL dan impor PEM dari kunci rahasia:
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 ) ? ; Penciptaan dan verifikasi token bekerja dengan cara yang sama seperti dengan algoritma HS* , kecuali bahwa token dibuat dengan pasangan kunci, dan diverifikasi menggunakan kunci publik yang sesuai.
Kreasi Token:
/// create claims valid for 2 hours
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) ;
let token = key_pair . sign ( claims ) ? ;Verifikasi Token:
let claims = public_key . verify_token :: < NoCustomClaims > ( & token , None ) ? ;Opsi verifikasi yang tersedia identik dengan yang digunakan dengan algoritma simetris.
Objek klaim mendukung semua klaim standar secara default, dan mereka dapat diatur secara langsung atau melalui pembantu yang nyaman:
let claims = Claims :: create ( Duration :: from_hours ( 2 ) ) .
with_issuer ( "Example issuer" ) . with_subject ( "Example subject" ) ; Tetapi klaim yang ditentukan aplikasi juga dapat didefinisikan. Ini hanya harus hadir dalam jenis serial (ini membutuhkan peti 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 ( ) ,
} ;Pembuatan Klaim dengan Data Kustom:
let claims = Claims :: with_custom_claims ( my_additional_data , Duration :: from_secs ( 30 ) ) ;Verifikasi klaim dengan data khusus. Perhatikan keberadaan tipe data khusus:
let claims = public_key . verify_token :: < MyAdditionalData > ( & token , None ) ? ;
let user_is_admin = claims . custom . user_is_admin ;Properti seperti pengidentifikasi kunci dapat berguna sebelum tag atau verifikasi tanda tangan untuk memilih kunci yang tepat dari suatu set.
let metadata = Token :: decode_metadata ( & token ) ? ;
let key_id = metadata . key_id ( ) ;
let algorithm = metadata . algorithm ( ) ;
// all other standard properties are also accessiblePenting: Baik ID kunci maupun algoritma tidak dapat dipercaya. Ini adalah cacat desain yang tidak dapat diperbaiki dari standar JWT.
Akibatnya, algorithm harus digunakan hanya untuk tujuan debugging, dan tidak pernah memilih jenis kunci. Demikian pula, key_id harus digunakan hanya untuk memilih kunci dalam satu set kunci yang dibuat untuk algoritma yang sama.
Minimal, verifikasi menggunakan HS* harus dilarang jika skema tanda tangan awalnya digunakan untuk membuat token.
Pengidentifikasi kunci menunjukkan untuk memverifikasi apa yang kunci publik (atau kunci bersama) harus digunakan untuk verifikasi. Mereka dapat dilampirkan kapan saja ke kunci bersama yang ada, pasangan kunci dan kunci publik:
let public_key_with_id = public_key . with_key_id ( & "unique key identifier" ) ; Alih-alih mendelegasikan ini ke aplikasi, jwt-simple juga dapat membuat pengidentifikasi seperti itu untuk kunci yang ada:
let key_id = public_key . create_key_id ( ) ;Ini menciptakan pengidentifikasi yang dikodekan teks untuk kunci, melampirkannya, dan mengembalikannya.
Jika pengidentifikasi telah dilampirkan pada kunci bersama atau pasangan kunci, token yang dibuat dengan mereka akan memasukkannya.
jwt-simple termasuk mekanisme untuk mengurangi serangan replay:
create_nonce() . Prosedur verifikasi nantinya dapat menolak token apa pun yang tidak termasuk nonce yang diharapkan (opsi verifikasi required_nonce ). Kode pengembangan mencakup fitur kargo cwt yang memungkinkan penguraian eksperimental dan validasi token CWT.
Harap dicatat bahwa CWT tidak mendukung klaim khusus. Pengidentifikasi yang diperlukan belum distandarisasi.
Juga, peti karat yang ada untuk deserialisasi JSON dan CBOR tidak aman. Pihak yang tidak percaya dapat mengirim objek serial yang membutuhkan banyak memori dan CPU untuk deserialize. Band-Aids telah ditambahkan untuk JSON, tetapi dengan perkakas karat saat ini, akan sulit dilakukan untuk CBOR.
Sebagai mitigasi, kami sangat merekomendasikan menolak token yang terlalu besar dalam konteks aplikasi Anda. Itu dapat dilakukan dengan dengan opsi verifikasi max_token_length .
boring Sebagai solusi sementara untuk masalah portabilitas dengan salah satu dependensi (peti boring ), perpustakaan ini dapat dikompilasi untuk hanya menggunakan implementasi karat.
Untuk melakukannya, impor peti dengan default-features=false, features=["pure-rust"] dalam konfigurasi kargo Anda.
Jangan lakukan itu tanpa syarat. Ini hanya diperlukan untuk pengaturan dan target yang sangat spesifik, dan hanya sampai masalah dengan peti boring telah diselesaikan. Cara untuk mengkonfigurasi ini dalam kargo juga dapat berubah dalam versi mendatang.
Bangunan statis yang menargetkan perpustakaan musl tidak memerlukan solusi itu. Cukup gunakan cargo-zigbuild untuk membangun proyek Anda.
Target wasm32-freestanding (masih kadang-kadang disebut wasm32-unknown-unknown di Rust) didukung (seperti dalam "itu kompilasi").
Namun, menggunakan implementasi JavaScript asli sangat dianjurkan sebagai gantinya. Ada implementasi JWT berkualitas tinggi dalam JavaScript, memanfaatkan API webcrypto, yang memberikan kinerja dan jaminan keamanan yang lebih baik daripada modul WebAssembly.
Peti ini bukan merupakan dukungan dari JWT. JWT adalah desain yang mengerikan, dan salah satu dari banyak contoh bahwa "tetapi ini adalah standar" tidak selalu berarti bahwa itu baik.
Saya akan sangat merekomendasikan Paseto atau Biskuit sebagai gantinya jika Anda mengendalikan penciptaan dan verifikasi token.
Namun, JWT masih banyak digunakan dalam industri ini, dan tetap wajib untuk berkomunikasi dengan API populer.
Peti ini dirancang untuk:
None untuk alasan yang jelas).