use super::*;
use crate::{jwk::Jwk, PublicKeyToJwk, VerificationKey, URL_SAFE_TRAILING_BITS};
use aws_lc_rs::rsa::{PublicKeyComponents, RsaParameters};
use aws_lc_rs::signature;
use base64::Engine as _;
#[derive(Debug, Clone)]
pub struct RsaPublicKey {
components: PublicKeyComponents<Vec<u8>>,
pub algorithm: Option<RsaAlgorithm>,
}
impl RsaPublicKey {
pub fn from_components(n: &[u8], e: &[u8], algorithm: Option<RsaAlgorithm>) -> Result<Self> {
Ok(Self {
components: PublicKeyComponents {
n: n.to_vec(),
e: e.to_vec(),
},
algorithm,
})
}
}
impl PublicKeyToJwk for RsaPublicKey {
fn public_key_to_jwk(&self) -> Result<Jwk> {
Ok(Jwk {
kty: "RSA".into(),
alg: self.algorithm.map(|alg| alg.name().to_string()),
use_: Some("sig".into()),
n: Some(URL_SAFE_TRAILING_BITS.encode(&self.components.n)),
e: Some(URL_SAFE_TRAILING_BITS.encode(&self.components.e)),
..Jwk::default()
})
}
}
fn rsa_params(alg: RsaAlgorithm) -> &'static RsaParameters {
use RsaAlgorithm::*;
match alg {
RS256 => &signature::RSA_PKCS1_2048_8192_SHA256,
RS384 => &signature::RSA_PKCS1_2048_8192_SHA384,
RS512 => &signature::RSA_PKCS1_2048_8192_SHA512,
PS256 => &signature::RSA_PSS_2048_8192_SHA256,
PS384 => &signature::RSA_PSS_2048_8192_SHA384,
PS512 => &signature::RSA_PSS_2048_8192_SHA512,
}
}
impl VerificationKey for RsaPublicKey {
fn verify(&self, v: &[u8], sig: &[u8], alg: &str) -> Result<()> {
let alg = if let Some(self_alg) = self.algorithm {
if self_alg.name() != alg {
return Err(Error::VerificationError);
}
self_alg
} else {
RsaAlgorithm::from_name(alg)?
};
self.components
.verify(rsa_params(alg), v, sig)
.map_err(|_| Error::VerificationError)
}
}