Expand description
§JOSE: JSON Object Signing and Encryption
JOSE is mostly known for so called Jwt
. Jwt stands for JsonWebToken
and
is actually only a subset of the whole JOSE specifications.
In the majority of cases, JsonWebToken
are a signed token that act as small
certificates for authentication. However, JOSE is way more complex than just a
simple signed certificate.
Because of this complexity, most implementation are incomplete. Even worse, bad
library design often lead to critical security vulnerabilities, such as the
famous none
Algorithm bug.
In order to prevent such vulnerabilities, this crate uses the Rust type system to make illegal states impossible and marks insecure or unverified /! states directly on the types themselves.
§Example
§Create a basic Jwt
In this crate, cryptographic keys are always represented as a type, never as a
String
or some other format that would lose essential information about a
key, such as its algorithm.
One should usually use the JsonWebKey
type, because it abstracts away the
complexity of different key types. Your application should not care what kind of
key it gets.
extern crate alloc;
use alloc::string::ToString;
use jose::{
format::{Compact, DecodeFormat},
jwk::{JwkSigner, JwkVerifier},
jws::Unverified,
jwt::Claims,
policy::{Checkable, StandardPolicy},
JsonWebKey, Jwk, Jwt, UntypedAdditionalProperties,
};
// This is a serialized asymmetric key. The private key part is stored in
// the `d` parameter
let serialized_private_key = r#"
{
"crv": "P-256",
"kty": "EC",
"x": "1uiXGPoQ3eLR3VOsCfnx1YzIJZGUQLbVfbl1CpCHcs0",
"y": "danaoyQqKi48vlB2jnCoFmq3PdIbYwIRJyNKWiindZM",
"d": "eLGzm5zd242okyN9SQBvmaC_4EPvASCgMhFgwtBvf3k",
"alg": "ES256"
}
"#;
let private_key: JsonWebKey = serde_json::from_str(serialized_private_key).expect("valid key");
// A JsonWebToken is just a specific version of a JsonWebSignature where
// the payload is defined as a JSON Object
// This JSON Object is easiest represented by the Claims struct of this crate.
// UntypedAdditionalProperties is used to keep any members of the JSON Object
// that are not directly handled in this implementation.
let claims: Claims<UntypedAdditionalProperties> = Claims {
subject: Some("Erik".to_string()),
issuer: Some("AuthenticationProvider".to_string()),
// sets the rest to None
..Default::default()
};
// because the key has the private component, it is able to create signatures
assert!(private_key.is_signing_key());
// A policy is used to ensure a key uses secure algorithm, key size etc.
let policy = StandardPolicy::default();
// a signer can create signatures
let mut signer: JwkSigner = private_key
.check(&policy)
.expect("valid key")
.try_into()
.expect("key has algorithm");
let jwt = Jwt::builder_jwt().build(claims).expect("header valid");
// this creates a signed JWT that can be serialized.
let signed_jwt = jwt.sign(&mut signer).unwrap();
let serialized = signed_jwt.to_string();
// Note: not all signatures are deterministic, meaning their signature is
// not always the same. That's why we only check the first part here
assert!(
serialized.starts_with("eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJBdXRoZW50aWNhdGlvblByb3ZpZGVyIiwic3ViIjoiRXJpayJ9.")
);
// The serialized public key. Note the missing `d` parameter
let serialized_public_key = r#"
{
"crv": "P-256",
"kty": "EC",
"x": "1uiXGPoQ3eLR3VOsCfnx1YzIJZGUQLbVfbl1CpCHcs0",
"y": "danaoyQqKi48vlB2jnCoFmq3PdIbYwIRJyNKWiindZM",
"alg": "ES256"
}
"#;
let public_key: Jwk = serde_json::from_str(&serialized_public_key).unwrap();
// This key can only verify signatures
assert_eq!(public_key.is_signing_key(), false);
let mut verifier: JwkVerifier = public_key
.check(&policy)
.unwrap()
.try_into()
.unwrap();
// deserialize the JWT
let encoded: Compact = serialized.parse().expect("valid format");
// decode the JWT
// Note: this JWT is not yet verified!
let unverified: Unverified<Jwt<UntypedAdditionalProperties>> =
Jwt::decode(encoded).expect("valid JWT");
// now the JWT is verified and we can trust the payload
let verified = unverified.verify(&mut verifier).expect("valid signature");
assert_eq!(verified.payload().subject, Some("Erik".to_string()));
This crate implements various RFCs related to JOSE:
- RFC 7519: JSON Web Token (JWT)
- RFC 7518: JSON Web Algorithms (JWA)
- RFC 7517: JSON Web Key (JWK)
RFC 7516: JSON Web Encryption (JWE)(Encryption is not supported in this first release)- RFC 7515: JSON Web Signature (JWS)
§Crypto backends
One of the core features of the jose
crate is the ability to choose between
different libraries for performing cryptographic operations. This gives the user
maximum flexibility to include jose
in their codebase and make it work under
their cryptographic requirements.
A backend is selected at compile time via feature flags. If no feature is enabled, this crate won’t compile. Additionally, if multiple backends are selected, it wont compile either.
The following backends are supported:
-
crypto-rustcrytpo
: Uses the RustCrypto ecosystem of crates. The main benefit of this backend is the possibility to compile this crate withoutstd
. -
crypto-openssl
: Uses the OpenSSL library.crypto-openssl-vendored
: Same as the other OpenSSL feature, but additionally enabled theopenssl/vendored
feature
-
crypto-aws-lc
: Uses the AWS-LC library,by making use of the OpenSSL compatible API aws-lc provides. -
crypto-ring
: Uses thering
pure-Rust library. Note, that thering
library is no longer actively maintained. However, due to wide usage of the crate, it is still provided as a viable backend
§License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
§Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Modules§
- crypto
- Cryptographic primitives.
- format
- Contains abstractions for different kinds of serialization formats.
- header
JoseHeader
and associated abstractions as defined in section 4 of RFC 7515.- jwa
- Implementation of JSON Web Algorithms (JWA) as defined in RFC 7518
- jwe
- Implementation of JSON Web Encryption (JWE) as defined in RFC 7516
- jwk
JsonWebKey
and connected things- jws
- Implementation of JSON Web Signature (JWS) as defined in RFC 7515
- jwt
- JsonWebToken (JWT) implementation
- policy
- Validate jose data against some
Policy
Structs§
- Base64
UrlString - A wrapper around a
String
that guarantees that the inner string is a valid Base64Url string. - Jose
Header - A
JoseHeader
is primarily used to specify how a JSON Web Signature or JSON Web Encryption should be processed. - Json
WebKey - A
JsonWebKey
is a JSON Object representing the components of a cryptographic keys that can be used for JWE and JWS. - Json
WebSignature - Represents a JSON Web Signature (JWS) as defined in RFC 7515.
- Uri
- A serializable URI type implemented using
serde
andfluent_uri
.
Type Aliases§
- Json
WebToken - A JSON Web Token (JWT) as defined in RFC 7519.
- Jwk
- Type alias to make
JsonWebKey
easier to access. - Jws
- Type alias to make
JsonWebSignature
easier to access. - Jwt
- Type alias to make
JsonWebToken
easier to access. - Untyped
Additional Properties - This type is used when the type of the additional parameters
of a
JsonWebKey
, or aJoseHeader
can not be specified, but must not be discarded.