use crate::{object, Client};
use signatory::{
digest::Digest,
ecdsa::{
curve::{NistP256, NistP384, WeierstrassCurve},
Asn1Signature, FixedSignature, PublicKey,
},
generic_array::typenum::{U32, U48},
DigestSigner, Error, PublicKeyed, Signature,
};
#[cfg(feature = "secp256k1")]
use signatory::{ecdsa::curve::Secp256k1, generic_array::GenericArray};
use signature_derive::Signer;
use std::marker::PhantomData;
#[derive(Signer)]
pub struct Signer<C>
where
C: WeierstrassCurve,
{
client: Client,
signing_key_id: object::Id,
curve: PhantomData<C>,
}
impl<C> Signer<C>
where
C: WeierstrassCurve,
{
pub fn create(client: Client, signing_key_id: object::Id) -> Result<Self, Error> {
let signer = Self {
client,
signing_key_id,
curve: PhantomData,
};
signer.public_key()?;
Ok(signer)
}
}
impl<C> PublicKeyed<PublicKey<C>> for Signer<C>
where
C: WeierstrassCurve,
{
fn public_key(&self) -> Result<PublicKey<C>, Error> {
let public_key = self.client.get_public_key(self.signing_key_id)?;
public_key.ecdsa().ok_or_else(Error::new)
}
}
impl<D> DigestSigner<D, Asn1Signature<NistP256>> for Signer<NistP256>
where
D: Digest<OutputSize = U32> + Default,
{
fn try_sign_digest(&self, digest: D) -> Result<Asn1Signature<NistP256>, Error> {
self.sign_nistp256_asn1(digest)
}
}
impl<D> DigestSigner<D, FixedSignature<NistP256>> for Signer<NistP256>
where
D: Digest<OutputSize = U32> + Default,
{
fn try_sign_digest(&self, digest: D) -> Result<FixedSignature<NistP256>, Error> {
Ok(FixedSignature::from(&self.sign_nistp256_asn1(digest)?))
}
}
impl<D> DigestSigner<D, Asn1Signature<NistP384>> for Signer<NistP384>
where
D: Digest<OutputSize = U48> + Default,
{
fn try_sign_digest(&self, digest: D) -> Result<Asn1Signature<NistP384>, Error> {
self.sign_nistp384_asn1(digest)
}
}
impl<D> DigestSigner<D, FixedSignature<NistP384>> for Signer<NistP384>
where
D: Digest<OutputSize = U48> + Default,
{
fn try_sign_digest(&self, digest: D) -> Result<FixedSignature<NistP384>, Error> {
Ok(FixedSignature::from(&self.sign_nistp384_asn1(digest)?))
}
}
#[cfg(feature = "secp256k1")]
impl<D> DigestSigner<D, Asn1Signature<Secp256k1>> for Signer<Secp256k1>
where
D: Digest<OutputSize = U32> + Default,
{
fn try_sign_digest(&self, digest: D) -> Result<Asn1Signature<Secp256k1>, Error> {
let asn1_sig = self.sign_secp256k1(digest)?.serialize_der();
Ok(Asn1Signature::from_bytes(&asn1_sig).unwrap())
}
}
#[cfg(feature = "secp256k1")]
impl<D> DigestSigner<D, FixedSignature<Secp256k1>> for Signer<Secp256k1>
where
D: Digest<OutputSize = U32> + Default,
{
fn try_sign_digest(&self, digest: D) -> Result<FixedSignature<Secp256k1>, Error> {
let fixed_sig =
GenericArray::clone_from_slice(&self.sign_secp256k1(digest)?.serialize_compact());
Ok(FixedSignature::from(fixed_sig))
}
}
impl Signer<NistP256> {
fn sign_nistp256_asn1<D>(&self, digest: D) -> Result<Asn1Signature<NistP256>, Error>
where
D: Digest<OutputSize = U32> + Default,
{
Asn1Signature::from_bytes(
self.client
.sign_ecdsa(self.signing_key_id, digest.result().as_slice())?,
)
}
}
impl Signer<NistP384> {
fn sign_nistp384_asn1<D>(&self, digest: D) -> Result<Asn1Signature<NistP384>, Error>
where
D: Digest<OutputSize = U48> + Default,
{
Asn1Signature::from_bytes(
self.client
.sign_ecdsa(self.signing_key_id, digest.result().as_slice())?,
)
}
}
#[cfg(feature = "secp256k1")]
impl Signer<Secp256k1> {
fn sign_secp256k1<D>(&self, digest: D) -> Result<secp256k1::Signature, Error>
where
D: Digest<OutputSize = U32> + Default,
{
let raw_sig = self
.client
.sign_ecdsa(self.signing_key_id, digest.result().as_slice())?;
let mut sig = secp256k1::Signature::from_der_lax(raw_sig.as_ref()).unwrap();
sig.normalize_s();
Ok(sig)
}
}