Type Definition biscuit::JWE [] [src]

type JWE<T, H, I> = Compact<JWT<T, H>, I>;

A convenience type alias of a "JWE" which is a compact JWE that contains a signed/unsigned compact JWS.

Type T is the type of private claims for the encapsulated JWT, and type H is the type of the private header fields of the encapsulated JWT. Type I is the private header fields fo the encapsulating JWE.

Usually, you would set H and I to biscuit::Empty because you usually do not need any private header fields.

In general, you should sign a JWT claims set, then encrypt it, although there is nothing stopping you from doing it the other way round.

Examples

Sign with HS256, then encrypt with A256GCMKW and A256GCM

extern crate biscuit;
extern crate num;
#[macro_use]
extern crate serde_derive;

use std::str::FromStr;
use biscuit::{ClaimsSet, RegisteredClaims, Empty, SingleOrMultiple, JWT, JWE};
use biscuit::jwk::JWK;
use biscuit::jws::{self, Secret};
use biscuit::jwe;
use biscuit::jwa::{EncryptionOptions, SignatureAlgorithm, KeyManagementAlgorithm,
                   ContentEncryptionAlgorithm};

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

#[allow(unused_assignments)]
// Craft our JWS
let expected_claims = ClaimsSet::<PrivateClaims> {
    registered: RegisteredClaims {
        issuer: Some(FromStr::from_str("https://www.acme.com").unwrap()),
        subject: Some(FromStr::from_str("John Doe").unwrap()),
        audience: Some(SingleOrMultiple::Single(
            FromStr::from_str("htts://acme-customer.com").unwrap(),
        )),
        not_before: Some(1234.into()),
        ..Default::default()
    },
    private: PrivateClaims {
        department: "Toilet Cleaning".to_string(),
        company: "ACME".to_string(),
    },
};

let expected_jwt = JWT::new_decoded(
    From::from(jws::RegisteredHeader {
        algorithm: SignatureAlgorithm::HS256,
        ..Default::default()
    }),
    expected_claims.clone(),
);

let jws = expected_jwt
    .into_encoded(&Secret::Bytes("secret".to_string().into_bytes()))
    .unwrap();

// 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<Empty> = JWK::new_octect_key(&vec![0; 256 / 8], Default::default());

// We need to create an `EncryptionOptions` with 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
let mut nonce_counter = num::BigUint::from_bytes_le(&vec![0; 96 / 8]);
// Make sure it's no more than 96 bits!
assert!(nonce_counter.bits() <= 96);
let mut nonce_bytes = nonce_counter.to_bytes_le();
// We need to ensure it is exactly 96 bits
nonce_bytes.resize(96 / 8, 0);
let options = EncryptionOptions::AES_GCM { nonce: nonce_bytes };

// Construct the JWE
let jwe = JWE::new_decrypted(
    From::from(jwe::RegisteredHeader {
        cek_algorithm: KeyManagementAlgorithm::A256GCMKW,
        enc_algorithm: ContentEncryptionAlgorithm::A256GCM,
        media_type: Some("JOSE".to_string()),
        content_type: Some("JOSE".to_string()),
        ..Default::default()
    }),
    jws.clone(),
);

// Encrypt
let encrypted_jwe = jwe.encrypt(&key, &options).unwrap();

let token = encrypted_jwe.unwrap_encrypted().to_string();

// Now, send `token` to your clients

// ... some time later, we get token back!
let token: JWE<PrivateClaims, ::Empty, ::Empty> = JWE::new_encrypted(&token);

// Decrypt
let decrypted_jwe = token
    .into_decrypted(
        &key,
        KeyManagementAlgorithm::A256GCMKW,
        ContentEncryptionAlgorithm::A256GCM,
    )
    .unwrap();

let decrypted_jws = decrypted_jwe.payload().unwrap();
assert_eq!(jws, *decrypted_jws);

// Don't forget to increment the nonce!
nonce_counter = nonce_counter + 1u8;