use crate::*;
#[derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum SignatureShare<C: BlsSignatureImpl> {
Basic(<C as Pairing>::SignatureShare),
MessageAugmentation(<C as Pairing>::SignatureShare),
ProofOfPossession(<C as Pairing>::SignatureShare),
}
impl<C: BlsSignatureImpl> Default for SignatureShare<C> {
fn default() -> Self {
Self::ProofOfPossession(<C as Pairing>::SignatureShare::default())
}
}
impl_signature_enum_traits!(
SignatureShare,
<C as Pairing>::SignatureShare,
"SignatureShare::conditional_select: mismatched variants"
);
impl_from_derivatives_generic!(SignatureShare);
impl<C: BlsSignatureImpl> TryFrom<&SignatureShare<C>> for Vec<u8> {
type Error = BlsError;
fn try_from(s: &SignatureShare<C>) -> BlsResult<Self> {
match s {
SignatureShare::Basic(s) => serde_bare::to_vec(&(SignatureSchemes::Basic, s)),
SignatureShare::MessageAugmentation(s) => {
serde_bare::to_vec(&(SignatureSchemes::MessageAugmentation, s))
}
SignatureShare::ProofOfPossession(s) => {
serde_bare::to_vec(&(SignatureSchemes::ProofOfPossession, s))
}
}
.map_err(|e| BlsError::SerializationError(e.to_string()))
}
}
impl<C: BlsSignatureImpl> TryFrom<&[u8]> for SignatureShare<C> {
type Error = BlsError;
fn try_from(bytes: &[u8]) -> BlsResult<Self> {
let (scheme, s): (SignatureSchemes, <C as Pairing>::SignatureShare) =
serde_bare::from_slice(bytes)
.map_err(|_| BlsError::InvalidInputs("invalid byte sequence".to_string()))?;
match scheme {
SignatureSchemes::Basic => Ok(Self::Basic(s)),
SignatureSchemes::MessageAugmentation => Ok(Self::MessageAugmentation(s)),
SignatureSchemes::ProofOfPossession => Ok(Self::ProofOfPossession(s)),
}
}
}
impl<C: BlsSignatureImpl> SignatureShare<C> {
pub fn verify<B: AsRef<[u8]>>(&self, pks: &PublicKeyShare<C>, msg: B) -> BlsResult<()> {
pks.verify(self, msg)
}
pub fn same_scheme(&self, other: &Self) -> bool {
matches!(
(self, other),
(Self::Basic(_), Self::Basic(_))
| (Self::MessageAugmentation(_), Self::MessageAugmentation(_))
| (Self::ProofOfPossession(_), Self::ProofOfPossession(_))
)
}
pub fn as_raw_value(&self) -> &<C as Pairing>::SignatureShare {
match self {
Self::Basic(s) => s,
Self::MessageAugmentation(s) => s,
Self::ProofOfPossession(s) => s,
}
}
pub fn from_v1_inner_bytes(raw_bytes: &[u8]) -> BlsResult<Self> {
let mut repr = <C::Signature as GroupEncoding>::Repr::default();
if repr.as_ref().len() != raw_bytes.len() - 2 {
return Err(BlsError::InvalidInputs("invalid byte sequence".to_string()));
}
let identifier = IdentifierPrimeField(<<C as Pairing>::Signature as Group>::Scalar::from(
raw_bytes[1] as u64,
));
repr.as_mut().copy_from_slice(&raw_bytes[2..]);
let value = Option::<C::Signature>::from(C::Signature::from_bytes(&repr))
.ok_or(BlsError::InvalidSignature)?;
let inner = <C as Pairing>::SignatureShare::with_identifier_and_value(
identifier,
ValueGroup(value),
);
match raw_bytes[0] {
0 => Ok(Self::Basic(inner)),
1 => Ok(Self::MessageAugmentation(inner)),
2 => Ok(Self::ProofOfPossession(inner)),
_ => Err(BlsError::InvalidInputs("invalid byte sequence".to_string())),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bytes() {
let s = SignatureShare::<Bls12381G2Impl>::default();
let bytes = Vec::<u8>::try_from(&s).unwrap();
let s2 = SignatureShare::<Bls12381G2Impl>::try_from(&bytes).unwrap();
assert_eq!(s, s2);
let mut bytes = [0u8; 98];
bytes[0] = 2;
bytes[2] = 192; let s2 = SignatureShare::from_v1_inner_bytes(&bytes).unwrap();
assert_eq!(s, s2);
let s = SignatureShare::<Bls12381G1Impl>::default();
let bytes = Vec::<u8>::try_from(&s).unwrap();
let s2 = SignatureShare::<Bls12381G1Impl>::try_from(&bytes).unwrap();
assert_eq!(s, s2);
let mut bytes = [0u8; 50];
bytes[0] = 2;
bytes[2] = 192; let s2 = SignatureShare::from_v1_inner_bytes(&bytes).unwrap();
assert_eq!(s, s2);
}
}