jwt_rustcrypto/
decode.rs

1use crate::validation::validate_header;
2use crate::{
3    pem::PemEncodedKey, validation::validate, Algorithm, Error, Header, SecretKey,
4    ValidationOptions, VerifyingKey,
5};
6use base64::Engine;
7use ecdsa::der::Signature as EcdsaDerSignature;
8use hmac::{Hmac, Mac};
9use k256::ecdsa::VerifyingKey as K256VerifyingKey;
10use p256::ecdsa::VerifyingKey as P256VerifyingKey;
11use p384::ecdsa::VerifyingKey as P384VerifyingKey;
12use p521::ecdsa::VerifyingKey as P521VerifyingKey;
13use rsa::signature::Verifier as RsaVerifier;
14use rsa::{
15    pkcs1v15::Signature as Pkcs1v15Signature, pkcs1v15::VerifyingKey as Pkcs1v15VerifyingKey,
16    pss::VerifyingKey as PssVerifyingKey,
17};
18use serde_json::Value as JsonValue;
19use sha2::{Sha256, Sha384, Sha512};
20use simple_asn1::{to_der, ASN1Block, BigUint};
21
22#[derive(Debug, Clone)]
23pub struct DecodedJwt {
24    pub header: Header,
25    pub payload: JsonValue,
26}
27
28/// Decodes and validates a JWT using the provided verification key and validation options.
29///
30/// # Arguments
31///
32/// * `token` - The encoded JWT string.
33/// * `verifying_key` - The key to be used for signature verification.
34/// * `options` - The validation options for the claims within the JWT.
35///
36/// # Returns
37///
38/// Returns a `DecodedJwt` structure containing the header, payload, and signature if successful,
39/// or an `Error` if decoding or validation fails.
40pub fn decode(
41    token: &str,
42    verifying_key: &VerifyingKey,
43    validation_options: &ValidationOptions,
44) -> Result<DecodedJwt, Error> {
45    let (header, payload, signature) = split_jwt(token)?;
46
47    validate_header(&header, validation_options)?;
48
49    let signing_input = format!(
50        "{}.{}",
51        token.split('.').collect::<Vec<&str>>()[0],
52        token.split('.').collect::<Vec<&str>>()[1]
53    );
54    verify_signature(&signing_input, &signature, &header.alg, verifying_key)
55        .map_err(|_| Error::InvalidSignature)?;
56    validate(
57        payload.as_object().ok_or(Error::InvalidKeyFormat)?,
58        validation_options,
59    )?;
60
61    Ok(DecodedJwt { header, payload })
62}
63
64/// Decodes a JWT without verifying the signature.
65/// This is useful when you only need to read the claims from the JWT.
66///
67/// # Arguments
68///
69/// * `token` - The encoded JWT string.
70///
71/// # Returns
72///
73/// Returns a `DecodedJwt` structure containing the header and payload if successful,
74/// or an `Error` if decoding fails.
75pub fn decode_only(token: &str) -> Result<DecodedJwt, Error> {
76    let (header, payload, _) = split_jwt(token)?;
77    Ok(DecodedJwt { header, payload })
78}
79
80fn split_jwt(token: &str) -> Result<(Header, JsonValue, Vec<u8>), Error> {
81    let parts: Vec<&str> = token.split('.').collect();
82    if parts.len() != 3 {
83        return Err(Error::InvalidKeyFormat);
84    }
85
86    let header_data = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(parts[0])?;
87    let payload_data = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(parts[1])?;
88    let signature = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(parts[2])?;
89
90    let header: Header = serde_json::from_slice(&header_data)?;
91    let payload: JsonValue = serde_json::from_slice(&payload_data)?;
92
93    Ok((header, payload, signature))
94}
95
96/// Verifies the signature of the JWT.
97///
98/// # Arguments
99///
100/// * `signing_input` - The input string to be signed (typically header.payload).
101/// * `signature` - The actual signature from the JWT.
102/// * `alg` - The algorithm specified in the JWT header.
103/// * `verifying_key` - The key to be used for verification.
104///
105/// # Returns
106///
107/// Returns `Ok(())` if the signature is valid, or an `Error` otherwise.
108fn verify_signature(
109    signing_input: &str,
110    signature: &[u8],
111    alg: &Algorithm,
112    verifying_key: &VerifyingKey,
113) -> Result<(), Error> {
114    match verifying_key {
115        VerifyingKey::Secret(secret) => match alg {
116            Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => {
117                verify_hmac(signing_input, signature, secret, alg)
118            }
119            _ => Err(Error::UnsupportedAlgorithm),
120        },
121        VerifyingKey::RsaKey(rsa_key) => match alg {
122            Algorithm::RS256 | Algorithm::RS384 | Algorithm::RS512 => {
123                verify_rsa(signing_input, signature, rsa_key, alg)
124            }
125            Algorithm::PS256 | Algorithm::PS384 | Algorithm::PS512 => {
126                verify_pss(signing_input, signature, rsa_key, alg)
127            }
128            _ => Err(Error::UnsupportedAlgorithm),
129        },
130        VerifyingKey::EcKey(ec_key) => match alg {
131            Algorithm::ES256 | Algorithm::ES256K | Algorithm::ES384 | Algorithm::ES512 => {
132                verify_ecdsa(signing_input, signature, ec_key, alg)
133            }
134            _ => Err(Error::UnsupportedAlgorithm),
135        },
136        _ => Err(Error::UnsupportedAlgorithm),
137    }
138}
139
140/// Verifies an RSA PKCS#1 signature.
141fn verify_rsa(
142    signing_input: &str,
143    signature: &[u8],
144    rsa_key: &PemEncodedKey,
145    alg: &Algorithm,
146) -> Result<(), Error> {
147    let rsa_public_key = rsa_key.as_rsa_public_key()?;
148    let pkcs1_signature = Pkcs1v15Signature::try_from(signature)?;
149    match alg {
150        Algorithm::RS256 => {
151            let verifying_key = Pkcs1v15VerifyingKey::<sha2::Sha256>::new(rsa_public_key);
152            verifying_key.verify(signing_input.as_bytes(), &pkcs1_signature)?;
153        }
154        Algorithm::RS384 => {
155            let verifying_key = Pkcs1v15VerifyingKey::<sha2::Sha384>::new(rsa_public_key);
156            verifying_key.verify(signing_input.as_bytes(), &pkcs1_signature)?;
157        }
158        Algorithm::RS512 => {
159            let verifying_key = Pkcs1v15VerifyingKey::<sha2::Sha512>::new(rsa_public_key);
160            verifying_key.verify(signing_input.as_bytes(), &pkcs1_signature)?;
161        }
162        _ => return Err(Error::UnsupportedAlgorithm),
163    };
164
165    Ok(())
166}
167
168/// Verifies an RSA-PSS signature.
169fn verify_pss(
170    signing_input: &str,
171    signature: &[u8],
172    rsa_key: &PemEncodedKey,
173    alg: &Algorithm,
174) -> Result<(), Error> {
175    let rsa_public_key = rsa_key.as_rsa_public_key()?;
176    let pss_signature = rsa::pss::Signature::try_from(signature)?;
177
178    match alg {
179        Algorithm::PS256 => {
180            let verifying_key = PssVerifyingKey::<sha2::Sha256>::new(rsa_public_key);
181            verifying_key.verify(signing_input.as_bytes(), &pss_signature)?
182        }
183        Algorithm::PS384 => {
184            let verifying_key = PssVerifyingKey::<sha2::Sha384>::new(rsa_public_key);
185            verifying_key.verify(signing_input.as_bytes(), &pss_signature)?
186        }
187        Algorithm::PS512 => {
188            let veryfing_key = PssVerifyingKey::<sha2::Sha512>::new(rsa_public_key);
189            veryfing_key.verify(signing_input.as_bytes(), &pss_signature)?
190        }
191        _ => {
192            return Err(Error::UnsupportedAlgorithm);
193        }
194    };
195
196    Ok(())
197}
198
199/// Verifies an HMAC signature.
200fn verify_hmac(
201    signing_input: &str,
202    signature: &[u8],
203    secret: &SecretKey,
204    alg: &Algorithm,
205) -> Result<(), Error> {
206    let key = secret.inner();
207    let computed_signature = match alg {
208        Algorithm::HS256 => {
209            let mut hmac = Hmac::<Sha256>::new_from_slice(key)?;
210            hmac.update(signing_input.as_bytes());
211            hmac.finalize().into_bytes().to_vec()
212        }
213        Algorithm::HS384 => {
214            let mut hmac = Hmac::<Sha384>::new_from_slice(key)?;
215            hmac.update(signing_input.as_bytes());
216            hmac.finalize().into_bytes().to_vec()
217        }
218        Algorithm::HS512 => {
219            let mut hmac = Hmac::<Sha512>::new_from_slice(key)?;
220            hmac.update(signing_input.as_bytes());
221            hmac.finalize().into_bytes().to_vec()
222        }
223        _ => return Err(Error::UnsupportedAlgorithm),
224    };
225
226    if computed_signature == signature {
227        Ok(())
228    } else {
229        Err(Error::InvalidSignature)
230    }
231}
232
233/// Verifies an ECDSA signature using the specified curve and algorithm.
234fn verify_ecdsa(
235    signing_input: &str,
236    signature: &[u8],
237    ec_key: &PemEncodedKey,
238    alg: &Algorithm,
239) -> Result<(), Error> {
240    let public_key_bytes = ec_key.as_ec_public_key()?;
241
242    match alg {
243        Algorithm::ES256 => {
244            let verifying_key = P256VerifyingKey::from_sec1_bytes(public_key_bytes)
245                .map_err(|_| Error::InvalidEcdsaKey)?;
246            let ecdsa_signature_vec = determine_signature_type(signature, 64);
247            let ecdsa_signature = EcdsaDerSignature::from_bytes(&ecdsa_signature_vec)?;
248            verifying_key
249                .verify(signing_input.as_bytes(), &ecdsa_signature)
250                .map_err(|_| Error::InvalidSignature)
251        }
252        Algorithm::ES256K => {
253            let verifying_key = K256VerifyingKey::from_sec1_bytes(public_key_bytes)
254                .map_err(|_| Error::InvalidEcdsaKey)?;
255            let ecdsa_signature_vec = determine_signature_type(signature, 64);
256            let ecdsa_signature = EcdsaDerSignature::from_bytes(&ecdsa_signature_vec)?;
257            verifying_key
258                .verify(signing_input.as_bytes(), &ecdsa_signature)
259                .map_err(|_| Error::InvalidSignature)
260        }
261        Algorithm::ES384 => {
262            let verifying_key = P384VerifyingKey::from_sec1_bytes(public_key_bytes)
263                .map_err(|_| Error::InvalidEcdsaKey)?;
264            let ecdsa_signature_vec = determine_signature_type(signature, 96);
265            let ecdsa_signature = EcdsaDerSignature::from_bytes(&ecdsa_signature_vec)?;
266            verifying_key
267                .verify(signing_input.as_bytes(), &ecdsa_signature)
268                .map_err(|_| Error::InvalidSignature)
269        }
270        Algorithm::ES512 => {
271            let verifying_key = P521VerifyingKey::from_sec1_bytes(public_key_bytes)
272                .map_err(|_| Error::InvalidEcdsaKey)?;
273            let ecdsa_signature_vec = determine_signature_type(signature, 132);
274            let ecdsa_signature = EcdsaDerSignature::from_bytes(&ecdsa_signature_vec)?;
275            verifying_key
276                .verify(signing_input.as_bytes(), &ecdsa_signature.try_into()?)
277                .map_err(|_| Error::InvalidSignature)
278        }
279        _ => Err(Error::UnsupportedAlgorithm),
280    }
281}
282
283fn determine_signature_type(signature: &[u8], signature_len: usize) -> Vec<u8> {
284    // convert signature to DER format if already not in DER format
285    if signature.len() == signature_len {
286        let r = &signature[..signature_len / 2];
287        let s = &signature[signature_len / 2..];
288
289        let asn1_signature = ASN1Block::Sequence(
290            0,
291            vec![
292                ASN1Block::Integer(0, BigUint::from_bytes_be(r).into()),
293                ASN1Block::Integer(0, BigUint::from_bytes_be(s).into()),
294            ],
295        );
296
297        to_der(&asn1_signature).unwrap()
298    } else {
299        signature.to_vec()
300    }
301}