Skip to content

Commit a701547

Browse files
committed
feat(encoder): Convert to dynamic dispatch
1 parent 502faa4 commit a701547

File tree

5 files changed

+180
-160
lines changed

5 files changed

+180
-160
lines changed

src/builder.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
use serde::Serialize;
66

77
use crate::{
8-
crypto::JwtSigner,
8+
crypto::{
9+
hmac::{HmacSecret, Hs256, Hs384},
10+
JwtSigner,
11+
},
912
errors::{new_error, Result},
1013
serialization::{b64_encode, b64_encode_part},
1114
Header,
@@ -14,14 +17,19 @@ use crate::{
1417
/// # Todo
1518
///
1619
/// - Documentation
17-
pub struct JwtEncoder<C: JwtSigner> {
18-
signing_provider: C,
20+
pub struct JwtEncoder {
21+
signing_provider: Box<dyn JwtSigner>,
1922
header: Header,
2023
}
2124

22-
impl<C: JwtSigner> JwtEncoder<C> {
25+
impl JwtEncoder {
26+
/// Todo
27+
pub fn from_signer<S: JwtSigner + 'static>(signing_provider: S) -> Self {
28+
Self::from_boxed_signer(Box::new(signing_provider))
29+
}
30+
2331
/// Create a new [`JwtEncoder`] with any crypto provider that implements the [`CryptoProvider`] trait.
24-
pub fn new(signing_provider: C) -> Self {
32+
pub fn from_boxed_signer(signing_provider: Box<dyn JwtSigner>) -> Self {
2533
// Determine a default header
2634
let mut header = Header::new(signing_provider.algorithm());
2735
header.typ = Some("JWT".to_owned());
@@ -60,11 +68,24 @@ impl<C: JwtSigner> JwtEncoder<C> {
6068

6169
Ok([message, signature].join("."))
6270
}
71+
72+
/// Create new [`JwtEncoder`] with the `HS256` algorithm.
73+
pub fn hs_256(secret: HmacSecret) -> Result<JwtEncoder> {
74+
let signing_provider = Box::new(Hs256::new(secret)?);
75+
76+
Ok(JwtEncoder::from_boxed_signer(signing_provider))
77+
}
78+
79+
/// Create new [`JwtEncoder`] with the `HS384` algorithm.
80+
pub fn hs_384(secret: HmacSecret) -> Result<JwtEncoder> {
81+
let signing_provider = Box::new(Hs384::new(secret)?);
82+
83+
Ok(JwtEncoder::from_boxed_signer(signing_provider))
84+
}
6385
}
6486

6587
#[cfg(test)]
6688
mod builder_tests {
67-
use crate::crypto::hmac::HmacSha256Trait;
6889

6990
use super::*;
7091

@@ -78,10 +99,10 @@ mod builder_tests {
7899
fn test_builder() {
79100
// Arrange
80101
let claims = Claims { sub: "123345".to_owned(), age: 25 };
81-
let signer = HmacSha256Trait::new("k3XTGsWiuO0stzhwPkuF2R6FdFY2crfyAVDjSBX34bW41ektItjp340PNXz1UvLkaq4CcT6ZMl7GXzfTvCvpkFXJbMni1wj40g423FbUxI7ZclVyzIrVFywrB5trt94Rv9AkTpShXzpnEWKGhZdD0MIOrQlg".as_ref()).unwrap();
102+
let secret = HmacSecret::from_secret("test".as_ref());
82103

83104
// Act
84-
let jwt = JwtEncoder::new(signer).encode(&claims).unwrap();
105+
let jwt = JwtEncoder::hs_256(secret).unwrap().encode(&claims).unwrap();
85106

86107
dbg!(&jwt);
87108

src/crypto/hmac.rs

Lines changed: 64 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,113 @@
1+
use base64::{engine::general_purpose::STANDARD, Engine};
12
use hmac::{Hmac, Mac};
23
use sha2::{Sha256, Sha384, Sha512};
3-
use signature::Signer;
4+
use signature::{Signer, Verifier};
45

56
use crate::errors::Result;
6-
use crate::serialization::{b64_decode, b64_encode};
77
use crate::Algorithm;
88

9-
use super::JwtSigner;
9+
use super::{JwtSigner, JwtVerifier};
1010

1111
type HmacSha256 = Hmac<Sha256>;
1212
type HmacSha384 = Hmac<Sha384>;
1313
type HmacSha512 = Hmac<Sha512>;
1414

15-
pub(crate) struct HmacSha256Trait(HmacSha256);
15+
pub(crate) struct HmacSecret(Vec<u8>);
1616

17-
impl HmacSha256Trait {
18-
pub(crate) fn new(key: &[u8]) -> Result<Self> {
19-
let inner = HmacSha256::new_from_slice(key)
17+
impl HmacSecret {
18+
/// If you're using an HMAC secret that is not base64, use that.
19+
pub fn from_secret(secret: &[u8]) -> Self {
20+
Self(secret.to_vec())
21+
}
22+
23+
/// If you have a base64 HMAC secret, use that.
24+
pub fn from_base64_secret(secret: &str) -> Result<Self> {
25+
Ok(Self(STANDARD.decode(secret)?))
26+
}
27+
}
28+
29+
pub struct Hs256(HmacSha256);
30+
31+
impl Hs256 {
32+
pub(crate) fn new(secret: HmacSecret) -> Result<Self> {
33+
let inner = HmacSha256::new_from_slice(&secret.0)
2034
.map_err(|_e| crate::errors::ErrorKind::InvalidKeyFormat)?;
2135

2236
Ok(Self(inner))
2337
}
2438
}
2539

26-
impl Signer<Vec<u8>> for HmacSha256Trait {
40+
impl Signer<Vec<u8>> for Hs256 {
2741
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, signature::Error> {
2842
let mut signer = self.0.clone();
43+
signer.reset();
44+
signer.update(msg);
2945

30-
Ok(signer.sign(msg))
46+
Ok(signer.finalize().into_bytes().to_vec())
3147
}
3248
}
3349

34-
impl JwtSigner for HmacSha256Trait {
50+
impl JwtSigner for Hs256 {
3551
fn algorithm(&self) -> Algorithm {
3652
Algorithm::HS256
3753
}
3854
}
3955

40-
pub(crate) fn sign_hmac(alg: Algorithm, key: &[u8], message: &[u8]) -> Result<String> {
41-
let mut hmac = create_hmac(alg, key)?;
42-
let digest = hmac.sign(message);
43-
Ok(b64_encode(digest))
44-
}
56+
impl Verifier<Vec<u8>> for Hs256 {
57+
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), signature::Error> {
58+
let mut verifier = self.0.clone();
59+
verifier.reset();
60+
verifier.update(msg);
4561

46-
pub(crate) fn hmac_verify(
47-
alg: Algorithm,
48-
signature: &str,
49-
key: &[u8],
50-
message: &[u8],
51-
) -> Result<bool> {
52-
let mut hmac = create_hmac(alg, key)?;
53-
let signature = b64_decode(signature)?;
54-
Ok(hmac.verify(&signature, message))
62+
verifier.verify_slice(signature).map_err(|e| signature::Error::from_source(e))
63+
}
5564
}
5665

57-
fn create_hmac(alg: Algorithm, key: &[u8]) -> Result<Box<dyn HmacAlgorithm>> {
58-
let hmac: Box<dyn HmacAlgorithm> = match alg {
59-
Algorithm::HS256 => {
60-
let sha256 = HmacSha256::new_from_slice(key)
61-
.map_err(|_e| crate::errors::ErrorKind::InvalidKeyFormat)?;
62-
Box::new(sha256)
63-
}
64-
Algorithm::HS384 => {
65-
let sha384 = HmacSha384::new_from_slice(key)
66-
.map_err(|_e| crate::errors::ErrorKind::InvalidKeyFormat)?;
67-
Box::new(sha384)
68-
}
69-
Algorithm::HS512 => {
70-
let sha512 = HmacSha512::new_from_slice(key)
71-
.map_err(|_e| crate::errors::ErrorKind::InvalidKeyFormat)?;
72-
Box::new(sha512)
73-
}
74-
_ => {
75-
return Err(crate::errors::new_error(crate::errors::ErrorKind::InvalidAlgorithm));
76-
}
77-
};
78-
Ok(hmac)
66+
impl JwtVerifier for Hs256 {
67+
fn algorithm(&self) -> Algorithm {
68+
Algorithm::HS256
69+
}
7970
}
8071

81-
trait HmacAlgorithm {
82-
fn sign(&mut self, message: &[u8]) -> Vec<u8>;
83-
fn verify(&mut self, signature: &[u8], message: &[u8]) -> bool;
84-
}
72+
pub(crate) struct Hs384(HmacSha384);
8573

86-
impl HmacAlgorithm for Box<dyn HmacAlgorithm + '_> {
87-
fn sign(&mut self, message: &[u8]) -> Vec<u8> {
88-
(**self).sign(message)
89-
}
74+
impl Hs384 {
75+
pub(crate) fn new(secret: HmacSecret) -> Result<Self> {
76+
let inner = HmacSha384::new_from_slice(&secret.0)
77+
.map_err(|_e| crate::errors::ErrorKind::InvalidKeyFormat)?;
9078

91-
fn verify(&mut self, signature: &[u8], message: &[u8]) -> bool {
92-
(**self).verify(signature, message)
79+
Ok(Self(inner))
9380
}
9481
}
9582

96-
impl HmacAlgorithm for HmacSha256 {
97-
fn sign(&mut self, message: &[u8]) -> Vec<u8> {
98-
self.reset();
99-
self.update(message);
100-
self.clone().finalize().into_bytes().to_vec()
101-
}
102-
fn verify(&mut self, signature: &[u8], message: &[u8]) -> bool {
103-
self.reset();
104-
self.update(message);
105-
self.clone().verify_slice(signature).is_ok()
83+
impl Signer<Vec<u8>> for Hs384 {
84+
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, signature::Error> {
85+
let mut signer = self.0.clone();
86+
signer.reset();
87+
signer.update(msg);
88+
89+
Ok(signer.finalize().into_bytes().to_vec())
10690
}
10791
}
10892

109-
impl HmacAlgorithm for HmacSha384 {
110-
fn sign(&mut self, message: &[u8]) -> Vec<u8> {
111-
self.reset();
112-
self.update(message);
113-
self.clone().finalize().into_bytes().to_vec()
114-
}
115-
fn verify(&mut self, signature: &[u8], message: &[u8]) -> bool {
116-
self.reset();
117-
self.update(message);
118-
self.clone().verify_slice(signature).is_ok()
93+
impl JwtSigner for Hs384 {
94+
fn algorithm(&self) -> Algorithm {
95+
Algorithm::HS384
11996
}
12097
}
12198

122-
impl HmacAlgorithm for HmacSha512 {
123-
fn sign(&mut self, message: &[u8]) -> Vec<u8> {
124-
self.reset();
125-
self.update(message);
126-
self.clone().finalize().into_bytes().to_vec()
99+
impl Verifier<Vec<u8>> for Hs384 {
100+
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), signature::Error> {
101+
let mut verifier = self.0.clone();
102+
verifier.reset();
103+
verifier.update(msg);
104+
105+
verifier.verify_slice(signature).map_err(|e| signature::Error::from_source(e))
127106
}
107+
}
128108

129-
fn verify(&mut self, signature: &[u8], message: &[u8]) -> bool {
130-
self.reset();
131-
self.update(message);
132-
self.clone().verify_slice(signature).is_ok()
109+
impl JwtVerifier for Hs384 {
110+
fn algorithm(&self) -> Algorithm {
111+
Algorithm::HS384
133112
}
134113
}

0 commit comments

Comments
 (0)