Crate no_way

Source
Expand description

§No Way, Jose!

A library to work with Javascript Object Signing and Encryption (JOSE), including:

  • JSON Web Tokens (JWT)
  • JSON Web Signature (JWS)
  • JSON Web Encryption (JWE)
  • JSON Web Algorithms (JWA)
  • JSON Web Keys (JWK)

§Examples

§Sign a token with HS256, then encrypt with A256GCMKW and A256GCM

use no_way::{ClaimsSet, RegisteredClaims, JWT, JWE};
use no_way::jwk;
use no_way::jwe::Encrypted;
use no_way::jwa::{kma, cea, sign};
use serde::{Serialize, Deserialize};

// Define our own private claims
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
struct PrivateClaims {
    company: String,
    department: String,
}

let signing_key = jwk::OctetKey::new("secret".to_string().into_bytes());

let expected_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
       eyJpc3MiOiJodHRwczovL3d3dy5hY21lLmNvbS8iLCJzdWIiOiJKb2huIERvZSIsImF1ZCI6Imh0dHBzOi8vYWNtZ\
       S1jdXN0b21lci5jb20vIiwibmJmIjoxMjM0LCJjb21wYW55IjoiQUNNRSIsImRlcGFydG1lbnQiOiJUb2lsZXQgQ2\
       xlYW5pbmcifQ.VFCl2un1Kc17odzOe2Ehf4DVrWddu3U4Ux3GFpOZHtc";

let expected_claims = ClaimsSet::<PrivateClaims> {
    registered: RegisteredClaims {
        issuer: Some("https://www.acme.com/".into()),
        subject: Some("John Doe".to_string()),
        audience: Some("https://acme-customer.com/".into()),
        not_before: Some(1234.try_into().unwrap()),
        ..Default::default()
    },
    private: PrivateClaims {
        department: "Toilet Cleaning".to_string(),
        company: "ACME".to_string(),
    },
};

let jwt = JWT::new(expected_claims.clone());

let jws_token = jwt.encode::<sign::HS256>(&signing_key).unwrap();
assert_eq!(expected_token, jws_token.to_string());

// Encrypt the token

// You would usually have your own AES key for this, but we will use a zeroed key as an example
let key = jwk::OctetKey::new(vec![0; 256 / 8]);

/// We need to create a nonce for AES GCM encryption.
/// You must take care NOT to reuse the nonce.
/// You can simply treat the nonce as a 96 bit
/// counter that is incremented after every use
///
/// In this case, we're using a 64bit counter + a 32bit random prefix tag
fn generate_nonce() -> [u8; 96/8] {
    static NONCE: AtomicU64 = AtomicU64::new(0);
    // use some lazy random generation so each service has a separate tag
    static TAG: u32 = 0xDEADCAFE;

    // fetch and increment the nonce counter
    let nonce = NONCE.fetch_add(1, Ordering::Release);

    // collect the bytes together and return them
    let mut output = [0; 96/8];
    output[0..32/8].copy_from_slice(&TAG.to_be_bytes());
    output[32/8..].copy_from_slice(&nonce.to_be_bytes());
    output
}
let nonce = generate_nonce();

// Construct the JWE
let jwe = JWE::new(jws_token.clone());

// Encrypt
let encrypted_jwe = jwe.encrypt::<
    cea::A256GCM,   // encrypt the contents with AES256 GCM
    kma::A256GCMKW, // perform key wrapping with AES256 GCM
>(&key, nonce).unwrap();

let jwe_token = encrypted_jwe.to_string();

// Now, send `token` to your clients

// ... some time later, we get token back!
let encrypted_jwe: Encrypted<kma::A256GCMKW> = jwe_token.parse().unwrap();

// Decrypt
let decrypted_jwe: JWE<_> = encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();

// Verify the JWT signature
let decoded_jwt = decrypted_jwe.payload.verify::<sign::HS256>(&signing_key).unwrap();

assert_eq!(decoded_jwt.payload, expected_claims);

Modules§

errors
Errors returned will be converted to one of the structs in this module.
jwa
JSON Web Algorithms
jwe
JSON Web Encryption
jwk
JSON Web Key
jws
JSON Web Signatures, including JWT signing and headers

Structs§

ClaimPresenceOptions
Options for claims presence validation
ClaimsSet
A collection of claims, both registered and your custom private claims.
Json
A [CompactPart] type that parses data as json using serde_json
RegisteredClaims
Registered claims defined by RFC7519#4.1
TemporalOptions
Options for validating temporal claims
Timestamp
Wrapper around OffsetDateTime to allow us to do custom de(serialization)
ValidationOptions
Options for claims validation

Enums§

Presence
Defines whether a claim is required or not
SingleOrMultiple
Represents a choice between a single value or multiple string values.
Validation
Defines whether a claim is validated or not

Traits§

FromCompactPart
A trait to describe how to parse components of a compact form JWS or JWE
ToCompactPart
A trait to describe how to produce components of a compact form JWS or JWE

Type Aliases§

JWE
A convenience type alias of a JSON Web Encryption token in it’s decrypted form. It contains an encoded JWT as it’s contents.
JWT
A convenience type alias of a JSON Web Encryption token in it’s decoded form. It contains a ClaimsSet as it’s contents