Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Add the following to Cargo.toml:

```toml
# You will have to select either `aws_lc_rs` or `rust_crypto` as backend if you're not using your own
jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
jsonwebtoken = { version = "11", features = ["aws_lc_rs"] }
# If you do not need pem decoding, you can disable the default feature `use_pem` that way:
# jsonwebtoken = {version = "10", default-features = false, features = ["aws_lc_rs"] }
serde = {version = "1.0", features = ["derive"] }
Expand All @@ -18,7 +18,7 @@ serde = {version = "1.0", features = ["derive"] }
Two crypto backends are available via features, `aws_lc_rs` and `rust_crypto`, at most one of which must be enabled. If you select neither feature, you need to provide your own `CryptoProvider`.

For examples of how to implement a `CryptoProvider`, see
- [arckoor/jsonwebtoken-botan](https://github.com/arckoor/jsonwebtoken-botan)
- [arckoor/jsonwebtoken-providers](https://github.com/arckoor/jsonwebtoken-providers)

The minimum required Rust version (MSRV) is specified in the `rust-version` field in this project's [Cargo.toml](Cargo.toml).

Expand All @@ -45,7 +45,7 @@ Complete examples are available in the examples directory: a basic one and one w
In terms of imports and structs:
```rust
use serde::{Serialize, Deserialize};
use jsonwebtoken::{encode, decode, Header, Algorithm, Validation, EncodingKey, DecodingKey};
use jsonwebtoken::{encode, decode, Header, Extras, Algorithm, Validation, EncodingKey, DecodingKey};

/// Our claims struct, it needs to derive `Serialize` and/or `Deserialize`
#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -86,7 +86,7 @@ If you want to set the `kid` parameter or change the algorithm for example:
let mut header = Header::new(Algorithm::HS512);
header.kid = Some("blabla".to_owned());

let mut extras = HashMap::with_capacity(1);
let mut extras = Extras::default();
extras.insert("custom".to_string(), "header".to_string());
header.extras = Some(extras);

Expand Down Expand Up @@ -134,8 +134,8 @@ when the Jws is nested in another struct.

If you have a JWK object, you can generate a thumbprint like

```
let tp = my_jwk.thumbprint(&jsonwebtoken::DIGEST_SHA256);
```rust
let tp = my_jwk.thumbprint(&jsonwebtoken::DIGEST_SHA256)?;
```

### Decoding
Expand Down
8 changes: 4 additions & 4 deletions src/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ impl CryptoProvider {

#[allow(unreachable_code)]
{
const NOT_INSTALLED_ERROR: &str = r###"
const NOT_INSTALLED_ERROR: &str = r"
Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features.
Call CryptoProvider::install_default() before this point to select a provider manually, or make sure exactly one of the 'rust_crypto' and 'aws_lc_rs' features is enabled.
See the documentation of the CryptoProvider type for more information.
"###;
";

static INSTANCE: CryptoProvider = CryptoProvider {
signer_factory: |_, _| panic!("{}", NOT_INSTALLED_ERROR),
Expand Down Expand Up @@ -151,11 +151,11 @@ impl JwkUtils {
/// Initialises all values to dummies.
/// Will lead to a panic when JWKs are required, so only use it if you don't want to support JWKs.
pub const fn new_unimplemented() -> Self {
const NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR: &str = r###"
const NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR: &str = r"
Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features, or your CryptoProvider does not support JWKs.
Call CryptoProvider::install_default() before this point to select a provider manually, or make sure exactly one of the 'rust_crypto' and 'aws_lc_rs' features is enabled.
See the documentation of the CryptoProvider type for more information.
"###;
";
Self {
extract_rsa_public_key_components: |_| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
Expand Down
6 changes: 3 additions & 3 deletions src/crypto/rust_crypto/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use sha2::{Sha256, Sha384, Sha512};
use signature::{Signer, Verifier};

use crate::crypto::{JwtSigner, JwtVerifier};
use crate::errors::Result;
use crate::errors::{ErrorKind, Result};
use crate::{Algorithm, DecodingKey, EncodingKey};

type HmacSha256 = Hmac<Sha256>;
Expand All @@ -21,7 +21,7 @@ macro_rules! define_hmac_signer {
impl $name {
pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
let inner = <$hmac_type>::new_from_slice(encoding_key.try_get_hmac_secret()?)
.map_err(|_e| crate::errors::ErrorKind::InvalidKeyFormat)?;
.map_err(|_| ErrorKind::InvalidKeyFormat)?;

Ok(Self(inner))
}
Expand Down Expand Up @@ -53,7 +53,7 @@ macro_rules! define_hmac_verifier {
impl $name {
pub(crate) fn new(decoding_key: &DecodingKey) -> Result<Self> {
let inner = <$hmac_type>::new_from_slice(decoding_key.try_get_hmac_secret()?)
.map_err(|_e| crate::errors::ErrorKind::InvalidKeyFormat)?;
.map_err(|_| ErrorKind::InvalidKeyFormat)?;

Ok(Self(inner))
}
Expand Down
2 changes: 1 addition & 1 deletion src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ impl Header {
zip: None,
url: None,
nonce: None,
extras: Default::default(),
extras: Extras::default(),
}
}

Expand Down
35 changes: 20 additions & 15 deletions src/jwk.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![allow(missing_docs)]
//! This crate contains types only for working JWK and JWK Sets
//! This is only meant to be used to deal with public JWK, not generate ones.
//! Most of the code in this file is taken from <https://github.com/lawliet89/biscuit> but
Expand All @@ -11,7 +10,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
use crate::crypto::CryptoProvider;
use crate::serialization::b64_encode;
use crate::{
Algorithm, EncodingKey,
Algorithm, AlgorithmFamily, EncodingKey,
errors::{self, Error, ErrorKind},
};

Expand Down Expand Up @@ -242,8 +241,8 @@ pub struct CommonParameters {
#[serde(rename = "use", skip_serializing_if = "Option::is_none", default)]
pub public_key_use: Option<PublicKeyUse>,

/// The "key_ops" (key operations) parameter identifies the operation(s)
/// for which the key is intended to be used. The "key_ops" parameter is
/// The `key_ops` (key operations) parameter identifies the operation(s)
/// for which the key is intended to be used. The `key_ops` parameter is
/// intended for use cases in which public, private, or symmetric keys
/// may be present.
/// Should not be specified with `public_key_use`.
Expand Down Expand Up @@ -403,6 +402,7 @@ pub struct OctetKeyPairParameters {
/// Algorithm specific parameters
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
#[serde(untagged)]
#[allow(missing_docs)]
pub enum AlgorithmParameters {
EllipticCurve(EllipticCurveKeyParameters),
RSA(RSAKeyParameters),
Expand All @@ -412,13 +412,15 @@ pub enum AlgorithmParameters {

/// The function to use to hash the intermediate thumbprint data.
#[derive(Debug, Clone, Eq, PartialEq)]
#[allow(missing_docs)]
pub enum ThumbprintHash {
SHA256,
SHA384,
SHA512,
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
#[allow(missing_docs)]
pub struct Jwk {
#[serde(flatten)]
pub common: CommonParameters,
Expand All @@ -435,7 +437,11 @@ impl Jwk {
_ => false,
}
}
pub fn from_encoding_key(key: &EncodingKey, alg: Algorithm) -> crate::errors::Result<Self> {

/// Create a `JWK` from an `EncodingKey`.
///
/// Edwards curve based keys are not supported.
pub fn from_encoding_key(key: &EncodingKey, alg: Algorithm) -> errors::Result<Self> {
Ok(Self {
common: CommonParameters {
key_algorithm: Some(match alg {
Expand All @@ -455,13 +461,11 @@ impl Jwk {
..Default::default()
},
algorithm: match key.family() {
crate::algorithms::AlgorithmFamily::Hmac => {
AlgorithmParameters::OctetKey(OctetKeyParameters {
key_type: OctetKeyType::Octet,
value: b64_encode(key.inner()),
})
}
crate::algorithms::AlgorithmFamily::Rsa => {
AlgorithmFamily::Hmac => AlgorithmParameters::OctetKey(OctetKeyParameters {
key_type: OctetKeyType::Octet,
value: b64_encode(key.inner()),
}),
AlgorithmFamily::Rsa => {
let (n, e) = (CryptoProvider::get_default()
.jwk_utils
.extract_rsa_public_key_components)(
Expand All @@ -473,7 +477,7 @@ impl Jwk {
e: b64_encode(e),
})
}
crate::algorithms::AlgorithmFamily::Ec => {
AlgorithmFamily::Ec => {
let (curve, x, y) = (CryptoProvider::get_default()
.jwk_utils
.extract_ec_public_key_coordinates)(
Expand All @@ -486,8 +490,8 @@ impl Jwk {
y: b64_encode(y),
})
}
crate::algorithms::AlgorithmFamily::Ed => {
unimplemented!();
AlgorithmFamily::Ed => {
unimplemented!("Edwards curves are not supported");
}
},
})
Expand Down Expand Up @@ -549,6 +553,7 @@ impl Jwk {

/// A JWK set
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
#[allow(missing_docs)]
pub struct JwkSet {
pub keys: Vec<Jwk>,
}
Expand Down
11 changes: 5 additions & 6 deletions src/pem/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,8 @@ impl PemEncodedKey {
pub fn new(input: &[u8]) -> Result<PemEncodedKey> {
match pem::parse(input) {
Ok(content) => {
let asn1_content = match simple_asn1::from_der(content.contents()) {
Ok(asn1) => asn1,
Err(_) => return Err(ErrorKind::InvalidKeyFormat.into()),
let Ok(asn1_content) = simple_asn1::from_der(content.contents()) else {
return Err(ErrorKind::InvalidKeyFormat.into());
};

match content.tag() {
Expand All @@ -78,7 +77,7 @@ impl PemEncodedKey {
// "there is no such thing as a "PKCS#1 format" for elliptic curve (EC) keys"

// This handles PKCS#8 certificates and public & private keys
tag @ "PRIVATE KEY" | tag @ "PUBLIC KEY" | tag @ "CERTIFICATE" => {
tag @ ("PRIVATE KEY" | "PUBLIC KEY" | "CERTIFICATE") => {
match classify_pem(&asn1_content) {
Some(c) => {
let is_private = tag == "PRIVATE KEY";
Expand Down Expand Up @@ -187,7 +186,7 @@ impl PemEncodedKey {
// Though PKCS#11 keys shouldn't have anything else.
// It will get confusing with certificates.
fn extract_first_bitstring(asn1: &[simple_asn1::ASN1Block]) -> Result<&[u8]> {
for asn1_entry in asn1.iter() {
for asn1_entry in asn1 {
match asn1_entry {
simple_asn1::ASN1Block::Sequence(_, entries) => {
if let Ok(result) = extract_first_bitstring(entries) {
Expand Down Expand Up @@ -215,7 +214,7 @@ fn classify_pem(asn1: &[simple_asn1::ASN1Block]) -> Option<Classification> {
let rsa_public_key_oid = simple_asn1::oid!(1, 2, 840, 113_549, 1, 1, 1);
let ed25519_oid = simple_asn1::oid!(1, 3, 101, 112);

for asn1_entry in asn1.iter() {
for asn1_entry in asn1 {
match asn1_entry {
simple_asn1::ASN1Block::Sequence(_, entries) => {
if let Some(classification) = classify_pem(entries) {
Expand Down
2 changes: 1 addition & 1 deletion src/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub(crate) fn b64_encode_part<T: Serialize>(input: &T) -> Result<String> {

/// This is used to decode from base64 then deserialize from JSON to several structs:
/// - The user-provided struct
/// - The ClaimsForValidation struct from this crate to run validation on
/// - The `ClaimsForValidation` struct from this crate to run validation on
pub(crate) struct DecodedJwtPartClaims {
b64_decoded: Vec<u8>,
}
Expand Down
4 changes: 2 additions & 2 deletions src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,13 @@ impl Validation {
/// `aud` is a collection of one or more acceptable audience members
/// The simple usage is `set_audience(&["some aud name"])`
pub fn set_audience<T: ToString>(&mut self, items: &[T]) {
self.aud = Some(items.iter().map(|x| x.to_string()).collect())
self.aud = Some(items.iter().map(|x| x.to_string()).collect());
}

/// `iss` is a collection of one or more acceptable issuers members
/// The simple usage is `set_issuer(&["some iss name"])`
pub fn set_issuer<T: ToString>(&mut self, items: &[T]) {
self.iss = Some(items.iter().map(|x| x.to_string()).collect())
self.iss = Some(items.iter().map(|x| x.to_string()).collect());
}

/// Which claims are required to be present for this JWT to be considered valid.
Expand Down
Loading