use rsa::signature::{RandomizedSigner, SignatureEncoding, Signer, Verifier};
use crate::error::{Error, Result};
use crate::signature::{Encoding, Signature};
mod sealed {
pub trait Sealed {}
}
pub trait SignatureScheme: sealed::Sealed {
type SigningKey: Clone;
type VerifyingKey: Clone;
fn parse_private_pem(pem: &str) -> Result<Self::SigningKey>;
fn parse_public_pem(pem: &str) -> Result<Self::VerifyingKey>;
fn sign(key: &Self::SigningKey, payload: &[u8]) -> Signature;
fn verify(key: &Self::VerifyingKey, payload: &[u8], sig_bytes: &[u8]) -> Result<()>;
}
fn map_priv<E: core::fmt::Display>(e: E) -> Error {
Error::InvalidSecretKey(e.to_string())
}
fn map_pub<E: core::fmt::Display>(e: E) -> Error {
Error::InvalidPublicKey(e.to_string())
}
fn map_sig_decode<E: core::fmt::Display>(e: E) -> Error {
Error::SignatureDecode { encoding: Encoding::Base64, reason: e.to_string() }
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Pkcs1v15Sha256;
impl sealed::Sealed for Pkcs1v15Sha256 {}
impl SignatureScheme for Pkcs1v15Sha256 {
type SigningKey = rsa::pkcs1v15::SigningKey<sha2::Sha256>;
type VerifyingKey = rsa::pkcs1v15::VerifyingKey<sha2::Sha256>;
fn parse_private_pem(pem: &str) -> Result<Self::SigningKey> {
use rsa::pkcs8::DecodePrivateKey;
Self::SigningKey::from_pkcs8_pem(pem).map_err(map_priv)
}
fn parse_public_pem(pem: &str) -> Result<Self::VerifyingKey> {
use rsa::pkcs8::DecodePublicKey;
Self::VerifyingKey::from_public_key_pem(pem).map_err(map_pub)
}
fn sign(key: &Self::SigningKey, payload: &[u8]) -> Signature {
let sig = Signer::sign(key, payload);
Signature::from_bytes(sig.to_bytes().into_vec())
}
fn verify(key: &Self::VerifyingKey, payload: &[u8], sig_bytes: &[u8]) -> Result<()> {
let sig = rsa::pkcs1v15::Signature::try_from(sig_bytes).map_err(map_sig_decode)?;
Verifier::verify(key, payload, &sig).map_err(|_| Error::AsymmetricVerifyFailed)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Pkcs1v15Sha512;
impl sealed::Sealed for Pkcs1v15Sha512 {}
impl SignatureScheme for Pkcs1v15Sha512 {
type SigningKey = rsa::pkcs1v15::SigningKey<sha2::Sha512>;
type VerifyingKey = rsa::pkcs1v15::VerifyingKey<sha2::Sha512>;
fn parse_private_pem(pem: &str) -> Result<Self::SigningKey> {
use rsa::pkcs8::DecodePrivateKey;
Self::SigningKey::from_pkcs8_pem(pem).map_err(map_priv)
}
fn parse_public_pem(pem: &str) -> Result<Self::VerifyingKey> {
use rsa::pkcs8::DecodePublicKey;
Self::VerifyingKey::from_public_key_pem(pem).map_err(map_pub)
}
fn sign(key: &Self::SigningKey, payload: &[u8]) -> Signature {
let sig = Signer::sign(key, payload);
Signature::from_bytes(sig.to_bytes().into_vec())
}
fn verify(key: &Self::VerifyingKey, payload: &[u8], sig_bytes: &[u8]) -> Result<()> {
let sig = rsa::pkcs1v15::Signature::try_from(sig_bytes).map_err(map_sig_decode)?;
Verifier::verify(key, payload, &sig).map_err(|_| Error::AsymmetricVerifyFailed)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct PssSha256;
impl sealed::Sealed for PssSha256 {}
impl SignatureScheme for PssSha256 {
type SigningKey = rsa::pss::SigningKey<sha2::Sha256>;
type VerifyingKey = rsa::pss::VerifyingKey<sha2::Sha256>;
fn parse_private_pem(pem: &str) -> Result<Self::SigningKey> {
use rsa::pkcs8::DecodePrivateKey;
let raw = rsa::RsaPrivateKey::from_pkcs8_pem(pem).map_err(map_priv)?;
Ok(rsa::pss::SigningKey::<sha2::Sha256>::new(raw))
}
fn parse_public_pem(pem: &str) -> Result<Self::VerifyingKey> {
use rsa::pkcs8::DecodePublicKey;
let raw = rsa::RsaPublicKey::from_public_key_pem(pem).map_err(map_pub)?;
Ok(rsa::pss::VerifyingKey::<sha2::Sha256>::new(raw))
}
fn sign(key: &Self::SigningKey, payload: &[u8]) -> Signature {
let mut rng = rand_core::OsRng;
let sig = RandomizedSigner::sign_with_rng(key, &mut rng, payload);
Signature::from_bytes(sig.to_bytes().into_vec())
}
fn verify(key: &Self::VerifyingKey, payload: &[u8], sig_bytes: &[u8]) -> Result<()> {
let sig = rsa::pss::Signature::try_from(sig_bytes).map_err(map_sig_decode)?;
Verifier::verify(key, payload, &sig).map_err(|_| Error::AsymmetricVerifyFailed)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct PssSha512;
impl sealed::Sealed for PssSha512 {}
impl SignatureScheme for PssSha512 {
type SigningKey = rsa::pss::SigningKey<sha2::Sha512>;
type VerifyingKey = rsa::pss::VerifyingKey<sha2::Sha512>;
fn parse_private_pem(pem: &str) -> Result<Self::SigningKey> {
use rsa::pkcs8::DecodePrivateKey;
let raw = rsa::RsaPrivateKey::from_pkcs8_pem(pem).map_err(map_priv)?;
Ok(rsa::pss::SigningKey::<sha2::Sha512>::new(raw))
}
fn parse_public_pem(pem: &str) -> Result<Self::VerifyingKey> {
use rsa::pkcs8::DecodePublicKey;
let raw = rsa::RsaPublicKey::from_public_key_pem(pem).map_err(map_pub)?;
Ok(rsa::pss::VerifyingKey::<sha2::Sha512>::new(raw))
}
fn sign(key: &Self::SigningKey, payload: &[u8]) -> Signature {
let mut rng = rand_core::OsRng;
let sig = RandomizedSigner::sign_with_rng(key, &mut rng, payload);
Signature::from_bytes(sig.to_bytes().into_vec())
}
fn verify(key: &Self::VerifyingKey, payload: &[u8], sig_bytes: &[u8]) -> Result<()> {
let sig = rsa::pss::Signature::try_from(sig_bytes).map_err(map_sig_decode)?;
Verifier::verify(key, payload, &sig).map_err(|_| Error::AsymmetricVerifyFailed)
}
}