use crate::{certificate::Certificate, digest::DigestAlgorithm, error::AdesError};
pub trait Signer {
type Error: std::error::Error + Send + Sync + 'static;
fn sign_digest(&self, digest: &[u8]) -> Result<Vec<u8>, Self::Error>;
fn certificate(&self) -> &Certificate;
fn digest_algorithm(&self) -> DigestAlgorithm;
}
#[cfg(feature = "soft")]
enum SoftKey {
Rsa(Box<rsa::RsaPrivateKey>),
Ec(p256::ecdsa::SigningKey),
}
#[cfg(feature = "soft")]
pub struct SoftSigner {
key: SoftKey,
certificate: Certificate,
digest: DigestAlgorithm,
}
#[cfg(feature = "soft")]
impl SoftSigner {
pub fn generate(bits: usize) -> Result<Self, AdesError> {
use der::{Decode, Encode};
use rand_core::OsRng;
use rsa::pkcs1v15::SigningKey;
use sha2::Sha256;
use signature::Keypair;
use spki::{EncodePublicKey, SubjectPublicKeyInfoOwned};
use x509_cert::{
builder::{Builder, CertificateBuilder, Profile},
name::RdnSequence,
serial_number::SerialNumber,
time::Validity,
};
let private_key = rsa::RsaPrivateKey::new(&mut OsRng, bits).map_err(AdesError::Rsa)?;
let signing_key = SigningKey::<Sha256>::new(private_key.clone());
let verifying_key = signing_key.verifying_key();
let pub_key_doc = verifying_key
.to_public_key_der()
.map_err(|e| AdesError::Signer(Box::new(e)))?;
let spki = SubjectPublicKeyInfoOwned::from_der(pub_key_doc.as_bytes())?;
let validity = Validity::from_now(std::time::Duration::from_secs(60 * 60 * 24 * 365 * 10))?;
let subject = RdnSequence::default();
let serial = SerialNumber::from(1u32);
let builder =
CertificateBuilder::new(Profile::Root, serial, validity, subject, spki, &signing_key)?;
let cert = builder.build::<rsa::pkcs1v15::Signature>()?;
let cert_der = cert.to_der()?;
let certificate = Certificate::from_der(&cert_der)?;
Ok(Self {
key: SoftKey::Rsa(Box::new(private_key)),
certificate,
digest: DigestAlgorithm::Sha256,
})
}
pub fn from_parts(
private_key: rsa::RsaPrivateKey,
cert_der: &[u8],
digest: DigestAlgorithm,
) -> Result<Self, AdesError> {
let certificate = Certificate::from_der(cert_der)?;
Ok(Self {
key: SoftKey::Rsa(Box::new(private_key)),
certificate,
digest,
})
}
pub fn generate_ec() -> Result<Self, AdesError> {
use der::{Decode, Encode};
use p256::ecdsa::{DerSignature, SigningKey};
use rand_core::OsRng;
use spki::{EncodePublicKey, SubjectPublicKeyInfoOwned};
use x509_cert::{
builder::{Builder, CertificateBuilder, Profile},
name::RdnSequence,
serial_number::SerialNumber,
time::Validity,
};
let signing_key = SigningKey::random(&mut OsRng);
let verifying_key = signing_key.verifying_key();
let pub_key_doc = verifying_key
.to_public_key_der()
.map_err(|e| AdesError::Signer(Box::new(e)))?;
let spki = SubjectPublicKeyInfoOwned::from_der(pub_key_doc.as_bytes())?;
let validity = Validity::from_now(std::time::Duration::from_secs(60 * 60 * 24 * 365 * 10))?;
let subject = RdnSequence::default();
let serial = SerialNumber::from(1u32);
let builder =
CertificateBuilder::new(Profile::Root, serial, validity, subject, spki, &signing_key)?;
let cert = builder.build::<DerSignature>()?;
let cert_der = cert.to_der()?;
let certificate = Certificate::from_der(&cert_der)?;
Ok(Self {
key: SoftKey::Ec(signing_key),
certificate,
digest: DigestAlgorithm::Sha256,
})
}
pub fn from_ec_parts(
signing_key: p256::ecdsa::SigningKey,
cert_der: &[u8],
digest: DigestAlgorithm,
) -> Result<Self, AdesError> {
let certificate = Certificate::from_der(cert_der)?;
Ok(Self {
key: SoftKey::Ec(signing_key),
certificate,
digest,
})
}
}
#[cfg(feature = "soft")]
impl Signer for SoftSigner {
type Error = AdesError;
fn sign_digest(&self, digest: &[u8]) -> Result<Vec<u8>, Self::Error> {
match &self.key {
SoftKey::Rsa(private_key) => {
use rsa::pkcs1v15::SigningKey;
use rsa::signature::hazmat::PrehashSigner;
use rsa::signature::SignatureEncoding;
use sha2::Sha256;
let signing_key = SigningKey::<Sha256>::new((**private_key).clone());
let signature: rsa::pkcs1v15::Signature = signing_key.sign_prehash(digest)?;
Ok(signature.to_vec())
}
SoftKey::Ec(signing_key) => {
use p256::ecdsa::signature::hazmat::PrehashSigner;
use p256::ecdsa::signature::SignatureEncoding;
use p256::ecdsa::DerSignature;
let signature: DerSignature = signing_key.sign_prehash(digest)?;
Ok(signature.to_vec())
}
}
}
fn certificate(&self) -> &Certificate {
&self.certificate
}
fn digest_algorithm(&self) -> DigestAlgorithm {
self.digest
}
}