jwt: added key rsa key generation, import/export, jwk as PS256

This commit is contained in:
Philippe Loctaux 2023-03-12 13:59:14 +01:00
parent e1ec84f7c6
commit 44506422e9
14 changed files with 334 additions and 1 deletions

View file

@ -0,0 +1,66 @@
use crate::Error;
use id::KeyID;
use jwt_compact::alg::{RsaPrivateKey, StrongKey};
use rsa::pkcs8::der::zeroize::Zeroizing;
use rsa::pkcs8::{DecodePrivateKey, EncodePrivateKey};
pub struct PrivateKey {
id: KeyID,
key: RsaPrivateKey,
}
impl PrivateKey {
pub fn new(id: &KeyID, key: StrongKey<RsaPrivateKey>) -> Self {
Self {
id: id.clone(),
key: key.into_inner(),
}
}
pub fn to_der(&self) -> Result<Zeroizing<Vec<u8>>, Error> {
Ok(self.key.to_pkcs8_der()?.to_bytes())
}
pub fn from_der(der: &[u8], id: &KeyID) -> Result<Self, Error> {
Ok(Self {
id: id.clone(),
key: RsaPrivateKey::from_pkcs8_der(der)?,
})
}
}
#[cfg(test)]
mod tests {
use crate::PrivateKey;
use id::KeyID;
#[test]
fn generate() {
let key_id = KeyID::default();
let keys = crate::generate(&key_id);
assert!(keys.is_ok());
let private_key = keys.unwrap().0;
assert_eq!(private_key.id, key_id);
}
#[test]
fn import_export() {
let key_id = KeyID::default();
// Import premade key
let premade_der = include_bytes!("../../tests/private_key.der");
let private_key = PrivateKey::from_der(premade_der, &key_id);
// Make sure import is ok
assert!(private_key.is_ok());
let private_key = private_key.unwrap();
// Export private key
let exported_der = private_key.to_der();
assert!(exported_der.is_ok());
let exported_der = exported_der.unwrap();
// Make sure output matches
assert_eq!(premade_der.as_slice(), exported_der.as_slice());
}
}

View file

@ -0,0 +1,92 @@
use crate::jwk::JsonWebKey;
use crate::Error;
use id::KeyID;
use jwt_compact::alg::{Rsa, RsaPublicKey, StrongKey};
use jwt_compact::jwk::JsonWebKey as JsonWebKeyBase;
use jwt_compact::Algorithm;
use rsa::pkcs1::{DecodeRsaPublicKey, EncodeRsaPublicKey};
pub struct PublicKey {
id: KeyID,
key: RsaPublicKey,
}
impl PublicKey {
pub fn new(id: &KeyID, key: StrongKey<RsaPublicKey>) -> Self {
Self {
id: id.clone(),
key: key.into_inner(),
}
}
pub fn to_der(&self) -> Result<Vec<u8>, Error> {
Ok(self.key.to_pkcs1_der()?.to_vec())
}
pub fn from_der(der: &[u8], id: &KeyID) -> Result<Self, Error> {
Ok(Self {
id: id.clone(),
key: RsaPublicKey::from_pkcs1_der(der)?,
})
}
pub fn jwk(&self) -> JsonWebKey {
JsonWebKey {
base: JsonWebKeyBase::from(&self.key),
key_id: self.id.as_ref(),
algorithm: Rsa::ps256().name(),
}
}
}
#[cfg(test)]
mod tests {
use crate::PublicKey;
use id::KeyID;
use std::str::FromStr;
#[test]
fn generate() {
let key_id = KeyID::default();
let keys = crate::generate(&key_id);
assert!(keys.is_ok());
let public_key = keys.unwrap().1;
assert_eq!(public_key.id, key_id);
}
#[test]
fn import_export() {
let key_id = KeyID::default();
// Import premade key
let premade_der = include_bytes!("../../tests/public_key.der");
let public_key = PublicKey::from_der(premade_der, &key_id);
// Make sure import is ok
assert!(public_key.is_ok());
let public_key = public_key.unwrap();
// Export public key
let exported_der = public_key.to_der();
assert!(exported_der.is_ok());
let exported_der = exported_der.unwrap();
// Make sure output matches
assert_eq!(premade_der.as_slice(), exported_der.as_slice());
}
#[test]
fn jwk() {
let key_id = KeyID::from_str("SgTG8ulMHAp5UsGWuCclw36zWsdEo5").unwrap();
// Import premade key
let premade_der = include_bytes!("../../tests/public_key.der");
let public_key = PublicKey::from_der(premade_der, &key_id).unwrap();
let generated_jwk = serde_json::to_string(&public_key.jwk());
assert!(generated_jwk.is_ok());
let jwk = r#"{"kty":"RSA","n":"3os0j_kNfdTHJVQ-eMYXyRBWIqsrJDdELxLAh3_WlOZtsBwiGVNnpHQm9cRB63Un9UJpYGbWz38emglXc8bHPrUArDl-K_5ioDlbh7hAaz3rZ6b8LDIPUO-jYICdxBdv1THXSWbTEistZF1TYsXg7G4xrxiFKnZLBNaSgJrKOAY8AUNWuby-vZKr5X9e3SG7kvPsUITyqSmDz4ZTCj4QScx4O9gyqz1_UEBxTRSKcpS82YzAo2Byo5avRWesiGoaxs8lNv0QJ22IY1KVoROv3hHFeFEcg3D4NTfFG2Cd8d1OMXfILhtFnQZbt5ZxIG9SCOfirn32-9OtoLemKlgSq0gbLf6t1OK12LK6mIJ78pphlnhHdvHeJ75PV6c2lS2Wwd75NYBJzhIojG4U4Lbpe7T_NDFaxExry_7V5oxX8tbb-OzJnuPOQRR0H5uOBjdVo7i5vjnDKOTDpro3XPQjBbIBkABhDdU2FcXkEbl8_ByyYZZni7ekzGrVSJB_vxvv","e":"AQAB","kid":"SgTG8ulMHAp5UsGWuCclw36zWsdEo5","alg":"PS256"}"#;
let generated_jwk = generated_jwk.unwrap();
assert_eq!(jwk, generated_jwk);
}
}