Skip to main content

asjeeves_encryption/
web_key.rs

1use std::borrow::Cow;
2use std::fmt;
3use std::sync::Arc;
4
5use json_web_key::prelude::*;
6use json_web_tolkien::jws::Jws;
7use json_web_tolkien::jwt::Jwt;
8use json_web_tolkien::prelude::Algorithm;
9use rand_core::{CryptoRng, RngCore};
10use rsa::pkcs1v15::{Signature, SigningKey, VerifyingKey};
11use rsa::pkcs8::{DecodePrivateKey, EncodePrivateKey, SecretDocument};
12use rsa::sha2::Sha256;
13use rsa::signature::{SignatureEncoding, SignerMut, Verifier};
14use rsa::traits::PublicKeyParts;
15use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
16use serde::{Deserialize, Serialize};
17use tracing::instrument;
18use uuid::Uuid;
19use zeroize::Zeroizing;
20
21use crate::error::Error;
22use crate::prelude::Sensitive;
23
24pub type WebKey = PrivateKey;
25
26#[derive(Clone, PartialEq)]
27pub struct PrivateKey {
28    inner: Arc<RsaPrivateKey>,
29    id: Arc<str>,
30}
31
32impl PrivateKey {
33    #[instrument(skip(ciphertext))]
34    pub fn decrypt_bytes(&self, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
35        let dec_bytes: Vec<u8> = self
36            .inner
37            .decrypt(Pkcs1v15Encrypt, ciphertext)
38            .map_err(|source| Error::DecryptionError { source })?;
39
40        Ok(dec_bytes)
41    }
42
43    #[instrument]
44    pub fn encrypt_bytes<R>(
45        &self,
46        bytes: Sensitive<Box<[u8]>>,
47        rng: &mut R,
48    ) -> Result<Vec<u8>, Error>
49    where
50        R: CryptoRng + RngCore + fmt::Debug,
51    {
52        let enc_bytes: Vec<u8> = self
53            .pubkey()
54            .encrypt(rng, Pkcs1v15Encrypt, &bytes)
55            .map_err(|source| Error::EncryptionError { source })?;
56
57        Ok(enc_bytes)
58    }
59
60    pub fn id(&self) -> &str {
61        self.id.as_ref()
62    }
63
64    #[instrument]
65    pub fn sign_claims<C>(&self, claims: C) -> Result<Jws, Error>
66    where
67        C: fmt::Debug + for<'de> Deserialize<'de> + Serialize,
68    {
69        #[derive(Clone, Debug, Deserialize, Serialize)]
70        struct Header {
71            alg: Algorithm,
72            kid: Box<str>,
73            typ: Box<str>,
74        }
75
76        let header = Header {
77            alg: Algorithm::RS256,
78            kid: self.id.as_ref().into(),
79            typ: "JWT".into(),
80        };
81
82        let debug_info = serde_json::to_string(&claims).unwrap();
83
84        tracing::info!("unencoded token {}", debug_info);
85
86        let token = Jwt::new(claims, header);
87
88        self.sign_json_web_token(token)
89    }
90
91    #[instrument(skip(token))]
92    pub fn sign_json_web_token<C, H>(&self, token: Jwt<C, H>) -> Result<Jws, Error>
93    where
94        C: fmt::Debug + Serialize,
95        H: fmt::Debug + Serialize,
96    {
97        let mut signing_key: SigningKey<Sha256> = SigningKey::new((*self.inner).clone());
98
99        // move this to json_web_tolkien.
100        let encoded_token: String = token
101            .to_string()
102            .map_err(|source| Error::JwtSerializationError { source })?;
103
104        tracing::info!("encoded token {}", encoded_token);
105
106        let signature: Box<[u8]> = {
107            let msg: &[u8] = encoded_token.as_bytes();
108
109            let signature: Signature = signing_key.sign(msg);
110
111            signature.to_bytes()
112        };
113
114        let jws = Jws::new(encoded_token.as_str(), signature.as_ref());
115
116        Ok(jws)
117    }
118
119    #[instrument]
120    pub fn generate<R>(rng: &mut R) -> Result<Self, Error>
121    where
122        R: CryptoRng + RngCore + fmt::Debug,
123    {
124        const BITS: usize = 2048;
125
126        let inner: Arc<RsaPrivateKey> = {
127            let inner =
128                RsaPrivateKey::new(rng, BITS).map_err(|source| Error::KeyGenError { source })?;
129
130            Arc::new(inner)
131        };
132
133        let id: Arc<str> = {
134            let id = Uuid::now_v7();
135            let id = id.to_string();
136            let id = id.as_str();
137
138            id.into()
139        };
140
141        let key = Self { id, inner };
142
143        Ok(key)
144    }
145
146    #[instrument]
147    pub fn to_json_web_key(&self) -> JsonWebKey {
148        let key_id: Box<str> = (*self.id.clone()).into();
149        let pubkey = self.pubkey();
150
151        let exponent: Box<[u8]> = pubkey.e().to_bytes_be().into();
152        let modulus: Box<[u8]> = pubkey.n().to_bytes_be().into();
153
154        let rwk = RsaWebKey {
155            exponent,
156            key_id,
157            modulus,
158            ..RsaWebKey::default()
159        };
160
161        JsonWebKey::RS256(rwk)
162    }
163
164    #[instrument]
165    pub fn to_json(&self) -> Result<serde_json::Value, Error> {
166        let jwk: JsonWebKey = self.to_json_web_key();
167
168        let json_val: serde_json::Value = serde_json::to_value(jwk)?;
169
170        Ok(json_val)
171    }
172
173    #[instrument(skip(jws))]
174    pub fn verify_json_web_signature(&self, jws: &Jws) -> Result<(), Error> {
175        let key: VerifyingKey<Sha256> = VerifyingKey::new(self.pubkey());
176
177        let signature: Signature = {
178            let sig: Cow<[u8]> = jws.signature();
179            Signature::try_from(sig.as_ref())?
180        };
181
182        let msg: Cow<str> = jws.encoded_token();
183
184        key.verify(msg.as_bytes(), &signature)?;
185
186        Ok(())
187    }
188
189    pub(crate) fn from_bytes(bytes: Zeroizing<Vec<u8>>, id: Arc<str>) -> Result<Self, Error> {
190        let inner: Arc<RsaPrivateKey> = {
191            let inner = RsaPrivateKey::from_pkcs8_der(&bytes)?;
192
193            Arc::new(inner)
194        };
195
196        let key = Self { id, inner };
197
198        Ok(key)
199    }
200
201    pub(crate) fn to_bytes(&self) -> Result<Zeroizing<Vec<u8>>, Error> {
202        let doc: SecretDocument = self.inner.to_pkcs8_der()?;
203
204        let bytes: Zeroizing<Vec<u8>> = doc.to_bytes();
205
206        Ok(bytes)
207    }
208
209    fn pubkey(&self) -> RsaPublicKey {
210        RsaPublicKey::from(self.inner.as_ref())
211    }
212}
213
214impl fmt::Debug for PrivateKey {
215    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216        f.debug_struct("PrivateKey")
217            .field("id", &self.id)
218            .finish_non_exhaustive()
219    }
220}
221
222#[cfg(test)]
223mod tests {
224    use super::*;
225    use crate::seed::Seed;
226
227    #[test]
228    fn test_generate() {
229        let seed = Seed::from(1);
230        let mut rng = seed.rng();
231
232        assert!(WebKey::generate(&mut rng).is_ok())
233    }
234}