jsonwebtoken/
encoding.rs

1use serde::ser::Serialize;
2
3use crate::algorithms::AlgorithmFamily;
4use crate::crypto;
5use crate::errors::{new_error, ErrorKind, Result};
6use crate::header::Header;
7use crate::pem::decoder::PemEncodedKey;
8use crate::serialization::b64_encode_part;
9
10/// A key to encode a JWT with. Can be a secret, a PEM-encoded key or a DER-encoded key.
11/// This key can be re-used so make sure you only initialize it once if you can for better performance
12#[derive(Debug, Clone, PartialEq)]
13pub struct EncodingKey {
14    pub(crate) family: AlgorithmFamily,
15    content: Vec<u8>,
16}
17
18impl EncodingKey {
19    /// If you're using a HMAC secret that is not base64, use that.
20    pub fn from_secret(secret: &[u8]) -> Self {
21        EncodingKey { family: AlgorithmFamily::Hmac, content: secret.to_vec() }
22    }
23
24    /// If you have a base64 HMAC secret, use that.
25    pub fn from_base64_secret(secret: &str) -> Result<Self> {
26        let out = base64::decode(&secret)?;
27        Ok(EncodingKey { family: AlgorithmFamily::Hmac, content: out })
28    }
29
30    /// If you are loading a RSA key from a .pem file.
31    /// This errors if the key is not a valid RSA key.
32    pub fn from_rsa_pem(key: &[u8]) -> Result<Self> {
33        let pem_key = PemEncodedKey::new(key)?;
34        let content = pem_key.as_rsa_key()?;
35        Ok(EncodingKey { family: AlgorithmFamily::Rsa, content: content.to_vec() })
36    }
37
38    /// If you are loading a ECDSA key from a .pem file
39    /// This errors if the key is not a valid private EC key
40    pub fn from_ec_pem(key: &[u8]) -> Result<Self> {
41        let pem_key = PemEncodedKey::new(key)?;
42        let content = pem_key.as_ec_private_key()?;
43        Ok(EncodingKey { family: AlgorithmFamily::Ec, content: content.to_vec() })
44    }
45
46    /// If you know what you're doing and have the DER-encoded key, for RSA only
47    pub fn from_rsa_der(der: &[u8]) -> Self {
48        EncodingKey { family: AlgorithmFamily::Rsa, content: der.to_vec() }
49    }
50
51    /// If you know what you're doing and have the DER-encoded key, for ECDSA
52    pub fn from_ec_der(der: &[u8]) -> Self {
53        EncodingKey { family: AlgorithmFamily::Ec, content: der.to_vec() }
54    }
55
56    pub(crate) fn inner(&self) -> &[u8] {
57        &self.content
58    }
59}
60
61/// Encode the header and claims given and sign the payload using the algorithm from the header and the key.
62/// If the algorithm given is RSA or EC, the key needs to be in the PEM format.
63///
64/// ```rust
65/// use serde::{Deserialize, Serialize};
66/// use jsonwebtoken::{encode, Algorithm, Header, EncodingKey};
67///
68/// #[derive(Debug, Serialize, Deserialize)]
69/// struct Claims {
70///    sub: String,
71///    company: String
72/// }
73///
74/// let my_claims = Claims {
75///     sub: "b@b.com".to_owned(),
76///     company: "ACME".to_owned()
77/// };
78///
79/// // my_claims is a struct that implements Serialize
80/// // This will create a JWT using HS256 as algorithm
81/// let token = encode(&Header::default(), &my_claims, &EncodingKey::from_secret("secret".as_ref())).unwrap();
82/// ```
83pub fn encode<T: Serialize>(header: &Header, claims: &T, key: &EncodingKey) -> Result<String> {
84    if key.family != header.alg.family() {
85        return Err(new_error(ErrorKind::InvalidAlgorithm));
86    }
87    let encoded_header = b64_encode_part(&header)?;
88    let encoded_claims = b64_encode_part(&claims)?;
89    let message = [encoded_header.as_ref(), encoded_claims.as_ref()].join(".");
90    let signature = crypto::sign(&*message, key, header.alg)?;
91
92    Ok([message, signature].join("."))
93}