1use std::fmt::{Debug, Formatter};
2
3use base64::{
4 Engine,
5 engine::general_purpose::{STANDARD, URL_SAFE},
6};
7use serde::ser::Serialize;
8use zeroize::{Zeroize, ZeroizeOnDrop};
9
10use crate::algorithms::AlgorithmFamily;
11use crate::crypto::CryptoProvider;
12use crate::errors::{ErrorKind, Result, new_error};
13use crate::header::Header;
14#[cfg(feature = "use_pem")]
15use crate::pem::decoder::PemEncodedKey;
16use crate::serialization::{b64_encode, b64_encode_part};
17
18#[derive(Clone, Zeroize, ZeroizeOnDrop)]
21pub struct EncodingKey {
22 #[zeroize(skip)]
23 family: AlgorithmFamily,
24 content: Vec<u8>,
25}
26
27impl EncodingKey {
28 pub fn family(&self) -> AlgorithmFamily {
30 self.family
31 }
32
33 pub fn from_secret(secret: &[u8]) -> Self {
35 EncodingKey { family: AlgorithmFamily::Hmac, content: secret.to_vec() }
36 }
37
38 pub fn from_base64_secret(secret: &str) -> Result<Self> {
40 let out = STANDARD.decode(secret)?;
41 Ok(EncodingKey { family: AlgorithmFamily::Hmac, content: out })
42 }
43
44 pub fn from_urlsafe_base64_secret(secret: &str) -> Result<Self> {
46 let out = URL_SAFE.decode(secret)?;
47 Ok(EncodingKey { family: AlgorithmFamily::Hmac, content: out })
48 }
49
50 #[cfg(feature = "use_pem")]
60 pub fn from_rsa_pem(key: &[u8]) -> Result<Self> {
61 let pem_key = PemEncodedKey::new(key)?;
62 let content = pem_key.as_rsa_key()?;
63 Ok(EncodingKey { family: AlgorithmFamily::Rsa, content: content.to_vec() })
64 }
65
66 #[cfg(feature = "use_pem")]
81 pub fn from_ec_pem(key: &[u8]) -> Result<Self> {
82 let pem_key = PemEncodedKey::new(key)?;
83 let content = pem_key.as_ec_private_key()?;
84 Ok(EncodingKey { family: AlgorithmFamily::Ec, content: content.to_vec() })
85 }
86
87 #[cfg(feature = "use_pem")]
91 pub fn from_ed_pem(key: &[u8]) -> Result<Self> {
92 let pem_key = PemEncodedKey::new(key)?;
93 let content = pem_key.as_ed_private_key()?;
94 Ok(EncodingKey { family: AlgorithmFamily::Ed, content: content.to_vec() })
95 }
96
97 pub fn from_rsa_der(der: &[u8]) -> Self {
99 EncodingKey { family: AlgorithmFamily::Rsa, content: der.to_vec() }
100 }
101
102 pub fn from_ec_der(der: &[u8]) -> Self {
104 EncodingKey { family: AlgorithmFamily::Ec, content: der.to_vec() }
105 }
106
107 pub fn from_ed_der(der: &[u8]) -> Self {
109 EncodingKey { family: AlgorithmFamily::Ed, content: der.to_vec() }
110 }
111
112 pub fn as_bytes(&self) -> &[u8] {
116 &self.content
117 }
118}
119
120impl Debug for EncodingKey {
121 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
122 f.debug_struct("EncodingKey")
123 .field("family", &self.family)
124 .field("content", &"[redacted]")
125 .finish()
126 }
127}
128
129pub fn encode<T: Serialize>(header: &Header, claims: &T, key: &EncodingKey) -> Result<String> {
152 if key.family != header.alg.family() {
153 return Err(new_error(ErrorKind::InvalidAlgorithm));
154 }
155
156 let signing_provider = (CryptoProvider::get_default().signer_factory)(&header.alg, key)?;
157
158 if signing_provider.algorithm() != header.alg {
159 return Err(new_error(ErrorKind::InvalidAlgorithm));
160 }
161
162 let encoded_header = b64_encode_part(&header)?;
163 let encoded_claims = b64_encode_part(claims)?;
164 let message = [encoded_header, encoded_claims].join(".");
165
166 let signature = b64_encode(signing_provider.try_sign(message.as_bytes())?);
167
168 Ok([message, signature].join("."))
169}