pub mod ecdsa {
pub use ecdsa::der;
pub use ecdsa::hazmat::{DigestPrimitive, SignPrimitive, VerifyPrimitive};
pub use ecdsa::{Error, Signature, SignatureSize, SigningKey, VerifyingKey};
#[cfg(feature = "secp256k1")]
pub use k256;
#[cfg(feature = "secp256k1")]
pub use k256::{
ecdsa::{
Signature as Secp256k1Signature, SigningKey as Secp256k1SigningKey, VerifyingKey as Secp256k1VerifyingKey,
},
schnorr, Secp256k1,
};
}
pub use elliptic_curve;
pub use signature::{Error, Keypair, SignatureEncoding, Signer, Verifier};
use crate::cms::content_info::CmsVersion;
use crate::cms::signed_data::{SignatureValue, SignerIdentifier, SignerInfo};
use crate::crypto::hash::Digest;
use crate::der::asn1::{ObjectIdentifier, OctetString};
use crate::der::oid::AssociatedOid;
use crate::error::{Result, TightBeamError};
use crate::oids::SIGNER_ECDSA_WITH_SHA3_256;
use crate::spki::{AlgorithmIdentifierOwned, EncodePublicKey};
use crate::x509::ext::pkix::SubjectKeyIdentifier;
pub trait SignatureAlgorithmIdentifier {
const ALGORITHM_OID: ObjectIdentifier;
}
pub trait Signatory<S>: Signer<S> + Keypair
where
S: SignatureEncoding,
{
type DigestAlgorithm: Digest + AssociatedOid;
fn to_signer_info(&self, data: impl AsRef<[u8]>) -> Result<SignerInfo> {
let mut hasher = Self::DigestAlgorithm::new();
hasher.update(&data);
hasher.finalize();
let signature: S = self.try_sign(data.as_ref())?;
let signature_bytes = signature.to_bytes();
let signature_value = SignatureValue::new(signature_bytes.as_ref())?;
let digest_alg = AlgorithmIdentifierOwned { oid: Self::DigestAlgorithm::OID, parameters: None };
let signature_algorithm = self.signature_algorithm();
let sid = self.signer_identifier()?;
Ok(SignerInfo {
version: CmsVersion::V1,
sid,
digest_alg,
signed_attrs: None,
signature_algorithm,
signature: signature_value,
unsigned_attrs: None,
})
}
fn signature_algorithm(&self) -> AlgorithmIdentifierOwned;
fn signer_identifier(&self) -> Result<SignerIdentifier>;
}
#[cfg(feature = "secp256k1")]
impl Signatory<ecdsa::Signature<ecdsa::Secp256k1>> for ecdsa::SigningKey<ecdsa::Secp256k1> {
type DigestAlgorithm = sha3::Sha3_256;
fn signature_algorithm(&self) -> AlgorithmIdentifierOwned {
AlgorithmIdentifierOwned { oid: SIGNER_ECDSA_WITH_SHA3_256, parameters: None }
}
fn signer_identifier(&self) -> Result<SignerIdentifier> {
let verifying_key = self.verifying_key();
let public_key_der = verifying_key
.to_public_key_der()
.map_err(|_| TightBeamError::SignatureEncodingError)?;
let mut hasher = Self::DigestAlgorithm::new();
hasher.update(public_key_der.as_bytes());
let skid_bytes = hasher.finalize();
let octet_string = OctetString::new(&skid_bytes[..20])?;
Ok(SignerIdentifier::SubjectKeyIdentifier(SubjectKeyIdentifier::from(octet_string)))
}
}
pub struct Sha3Signer<'a, S>(&'a S);
impl<'a, S> crate::spki::DynSignatureAlgorithmIdentifier for Sha3Signer<'a, S> {
fn signature_algorithm_identifier(&self) -> crate::spki::Result<crate::spki::AlgorithmIdentifierOwned> {
Ok(crate::spki::AlgorithmIdentifierOwned { oid: SIGNER_ECDSA_WITH_SHA3_256, parameters: None })
}
}
impl<'a, S> signature::Keypair for Sha3Signer<'a, S>
where
S: signature::Keypair,
{
type VerifyingKey = <S as signature::Keypair>::VerifyingKey;
fn verifying_key(&self) -> Self::VerifyingKey {
self.0.verifying_key()
}
}
impl<'a, S, Sig> signature::Signer<Sig> for Sha3Signer<'a, S>
where
S: signature::Signer<Sig>,
{
fn try_sign(&self, msg: &[u8]) -> core::result::Result<Sig, signature::Error> {
self.0.try_sign(msg)
}
}
impl<'a, S> From<&'a S> for Sha3Signer<'a, S> {
fn from(s: &'a S) -> Self {
Sha3Signer(s)
}
}
#[cfg(feature = "secp256k1")]
pub fn secp256k1_signer_identifier(verifying_key: &ecdsa::VerifyingKey<ecdsa::Secp256k1>) -> Result<SignerIdentifier> {
let public_key_der = verifying_key
.to_public_key_der()
.map_err(|_| TightBeamError::SignatureEncodingError)?;
let mut hasher = sha3::Sha3_256::new();
hasher.update(public_key_der.as_bytes());
let skid_bytes = hasher.finalize();
let octet_string = OctetString::new(&skid_bytes[..20]).map_err(TightBeamError::SerializationError)?;
Ok(SignerIdentifier::SubjectKeyIdentifier(SubjectKeyIdentifier::from(octet_string)))
}
pub trait SignatureVerifier {
fn verify_signature(&self, content: &[u8], signature: &[u8], signer_id: &SignerIdentifier) -> Result<()>;
}
#[cfg(all(feature = "signature", feature = "secp256k1"))]
pub struct EcdsaSignatureVerifier<V, S, D>
where
V: Verifier<S>,
S: SignatureEncoding,
D: Digest,
{
verifying_key: V,
expected_sid: Option<SignerIdentifier>,
_phantom: core::marker::PhantomData<(S, D)>,
}
#[cfg(all(feature = "signature", feature = "secp256k1"))]
impl<V, S, D> EcdsaSignatureVerifier<V, S, D>
where
V: Verifier<S>,
S: SignatureEncoding,
D: Digest,
{
pub fn from_signing_key<K>(signing_key: &K) -> Result<Self>
where
K: Signatory<S>,
K::VerifyingKey: Into<V>,
{
let verifying_key = signing_key.verifying_key().into();
let expected_sid = signing_key.signer_identifier()?;
Ok(Self {
verifying_key,
expected_sid: Some(expected_sid),
_phantom: core::marker::PhantomData,
})
}
pub fn from_verifying_key_with_sid(verifying_key: V, expected_sid: SignerIdentifier) -> Self {
Self {
verifying_key,
expected_sid: Some(expected_sid),
_phantom: core::marker::PhantomData,
}
}
}
#[cfg(all(feature = "signature", feature = "secp256k1"))]
impl<V, S, D> SignatureVerifier for EcdsaSignatureVerifier<V, S, D>
where
V: Verifier<S>,
S: SignatureEncoding,
D: Digest,
{
fn verify_signature(&self, content: &[u8], signature_bytes: &[u8], signer_id: &SignerIdentifier) -> Result<()> {
if let Some(ref expected_sid) = self.expected_sid {
if signer_id != expected_sid {
return Err(TightBeamError::SignatureEncodingError);
}
}
let mut hasher = D::new();
hasher.update(content);
let digest = hasher.finalize();
let signature = S::try_from(signature_bytes).map_err(|_| TightBeamError::SignatureEncodingError)?;
self.verifying_key
.verify(digest.as_slice(), &signature)
.map_err(|_| TightBeamError::SignatureEncodingError)?;
Ok(())
}
}
#[cfg(feature = "secp256k1")]
impl SignatureAlgorithmIdentifier for ecdsa::Secp256k1Signature {
const ALGORITHM_OID: ObjectIdentifier = SIGNER_ECDSA_WITH_SHA3_256;
}