use crate::{convert::ScalarPair, curve::Curve};
use core::{
convert::{TryFrom, TryInto},
fmt::{self, Debug},
ops::Add,
};
use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
use signature::Error;
pub type MaxOverhead = generic_array::typenum::U9;
pub type MaxSize<ScalarSize> = <<ScalarSize as Add>::Output as Add<MaxOverhead>>::Output;
pub struct Asn1Signature<C: Curve>
where
MaxSize<C::ScalarSize>: ArrayLength<u8>,
<C::ScalarSize as Add>::Output: ArrayLength<u8> + Add<MaxOverhead>,
{
pub(crate) bytes: GenericArray<u8, MaxSize<C::ScalarSize>>,
pub(crate) length: usize,
}
impl<C: Curve> signature::Signature for Asn1Signature<C>
where
MaxSize<C::ScalarSize>: ArrayLength<u8>,
<C::ScalarSize as Add>::Output: ArrayLength<u8> + Add<MaxOverhead>,
{
fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
bytes.try_into()
}
}
impl<C: Curve> AsRef<[u8]> for Asn1Signature<C>
where
MaxSize<C::ScalarSize>: ArrayLength<u8>,
<C::ScalarSize as Add>::Output: ArrayLength<u8> + Add<MaxOverhead>,
{
fn as_ref(&self) -> &[u8] {
&self.bytes.as_slice()[..self.length]
}
}
impl<C: Curve> Debug for Asn1Signature<C>
where
MaxSize<C::ScalarSize>: ArrayLength<u8>,
<C::ScalarSize as Add>::Output: ArrayLength<u8> + Add<MaxOverhead>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Asn1Signature<{:?}> {{ bytes: {:?}) }}",
C::default(),
self.as_ref()
)
}
}
impl<'a, C: Curve> TryFrom<&'a [u8]> for Asn1Signature<C>
where
MaxSize<C::ScalarSize>: ArrayLength<u8>,
<C::ScalarSize as Add>::Output: ArrayLength<u8> + Add<MaxOverhead>,
{
type Error = Error;
fn try_from(slice: &'a [u8]) -> Result<Self, Error> {
let length = slice.len();
if <MaxSize<C::ScalarSize>>::to_usize() < length {
return Err(Error::new());
}
let mut bytes = GenericArray::default();
bytes.as_mut_slice()[..length].copy_from_slice(slice);
let result = Self { bytes, length };
ScalarPair::from_asn1_signature(&result).ok_or_else(Error::new)?;
Ok(result)
}
}