use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::{Bytes, serde_as};
use super::super::{
RebasedError,
crypto::{Ed25519KeyPair, Ed25519PublicKey, Ed25519Signature, Signer},
encoding::{Base64, EncodeDecodeBase64, Encoding},
hash::{Blake2b256, HashFunction},
serde::Readable,
traits::ToFromBytes,
};
use super::IntentMessage;
#[derive(Clone, Copy, Deserialize, Serialize, Debug, PartialEq, Eq)]
pub enum SignatureScheme {
ED25519,
}
impl SignatureScheme {
pub fn flag(&self) -> u8 {
match self {
SignatureScheme::ED25519 => 0x00,
}
}
pub fn update_hasher_with_flag(&self, hasher: &mut Blake2b256) {
#[allow(unreachable_patterns)]
match self {
SignatureScheme::ED25519 => (),
_ => hasher.update([self.flag()]),
};
}
pub fn from_flag(flag: &str) -> Result<SignatureScheme, RebasedError> {
let byte_int = flag
.parse::<u8>()
.map_err(|_| RebasedError::KeyConversion("Invalid key scheme".to_string()))?;
Self::from_flag_byte(&byte_int)
}
pub fn from_flag_byte(byte_int: &u8) -> Result<SignatureScheme, RebasedError> {
match byte_int {
0x00 => Ok(SignatureScheme::ED25519),
_ => Err(RebasedError::KeyConversion("Invalid key scheme".to_string())),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Signature {
Ed25519IotaSignature(Ed25519IotaSignature),
}
impl Serialize for Signature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let bytes = self.as_ref();
if serializer.is_human_readable() {
let s = Base64::encode(bytes);
serializer.serialize_str(&s)
} else {
serializer.serialize_bytes(bytes)
}
}
}
impl<'de> Deserialize<'de> for Signature {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;
let bytes = if deserializer.is_human_readable() {
let s = String::deserialize(deserializer)?;
Base64::decode(&s).map_err(|e| Error::custom(e.to_string()))?
} else {
let data: Vec<u8> = Vec::deserialize(deserializer)?;
data
};
Self::from_bytes(&bytes).map_err(|e| Error::custom(e.to_string()))
}
}
impl Signature {
pub fn new_hashed(hashed_msg: &[u8], secret: &dyn Signer<Signature>) -> Self {
Signer::sign(secret, hashed_msg)
}
pub fn new_secure<T>(value: &IntentMessage<T>, secret: &dyn Signer<Signature>) -> Result<Self, RebasedError>
where
T: Serialize,
{
let mut hasher = Blake2b256::default();
hasher.update(bcs::to_bytes(&value)?);
Ok(Signer::sign(secret, &hasher.finalize().digest))
}
}
impl AsRef<[u8]> for Signature {
fn as_ref(&self) -> &[u8] {
match self {
Signature::Ed25519IotaSignature(sig) => sig.as_ref(),
}
}
}
impl AsMut<[u8]> for Signature {
fn as_mut(&mut self) -> &mut [u8] {
match self {
Signature::Ed25519IotaSignature(sig) => sig.as_mut(),
}
}
}
impl ToFromBytes for Signature {
fn from_bytes(bytes: &[u8]) -> Result<Self, RebasedError> {
match bytes.first() {
Some(x) => {
if x == &Ed25519IotaSignature::SCHEME.flag() {
Ok(Signature::Ed25519IotaSignature(
<Ed25519IotaSignature as ToFromBytes>::from_bytes(bytes)?,
))
} else {
Err(RebasedError::InvalidInput)
}
}
_ => Err(RebasedError::InvalidInput),
}
}
}
#[serde_as]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct Ed25519IotaSignature(
#[serde_as(as = "Readable<Base64, Bytes>")] [u8; Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1],
);
impl Ed25519IotaSignature {
const SCHEME: SignatureScheme = SignatureScheme::ED25519;
}
impl AsRef<[u8]> for Ed25519IotaSignature {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for Ed25519IotaSignature {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl Ed25519IotaSignature {
const LENGTH: usize = Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1;
}
impl ToFromBytes for Ed25519IotaSignature {
fn from_bytes(bytes: &[u8]) -> Result<Self, RebasedError> {
if bytes.len() != Self::LENGTH {
return Err(RebasedError::InputLengthWrong(Self::LENGTH));
}
let mut sig_bytes = [0; Self::LENGTH];
sig_bytes.copy_from_slice(bytes);
Ok(Self(sig_bytes))
}
}
impl Signer<Signature> for Ed25519KeyPair {
fn sign(&self, msg: &[u8]) -> Signature {
let sig: Ed25519Signature = <Self as Signer<Ed25519Signature>>::sign(self, msg);
let mut signature_bytes: Vec<u8> = Vec::new();
signature_bytes.extend_from_slice(&[Ed25519IotaSignature::SCHEME.flag()]);
signature_bytes.extend_from_slice(sig.as_ref());
signature_bytes.extend_from_slice(self.public().as_ref());
#[allow(
clippy::expect_used,
reason = "the required length is constant, thus this is acceptable"
)]
let sign = Ed25519IotaSignature::from_bytes(&signature_bytes[..])
.expect("Serialized signature did not have expected size");
Signature::Ed25519IotaSignature(sign)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GenericSignature {
Signature(Signature),
}
impl From<Signature> for GenericSignature {
fn from(value: Signature) -> Self {
Self::Signature(value)
}
}
impl ToFromBytes for GenericSignature {
fn from_bytes(bytes: &[u8]) -> Result<Self, RebasedError> {
match SignatureScheme::from_flag_byte(bytes.first().ok_or(RebasedError::InputTooShort(0))?) {
Ok(x) => match x {
SignatureScheme::ED25519 => {
Ok(GenericSignature::Signature(
Signature::from_bytes(bytes).map_err(|_| RebasedError::InvalidSignature)?,
))
} },
Err(_) => Err(RebasedError::InvalidInput),
}
}
}
impl AsRef<[u8]> for GenericSignature {
fn as_ref(&self) -> &[u8] {
match self {
GenericSignature::Signature(s) => s.as_ref(),
}
}
}
impl ::serde::Serialize for GenericSignature {
fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
if serializer.is_human_readable() {
#[derive(serde::Serialize)]
struct GenericSignature(String);
GenericSignature(self.encode_base64()).serialize(serializer)
} else {
#[derive(serde::Serialize)]
struct GenericSignature<'a>(&'a [u8]);
GenericSignature(self.as_ref()).serialize(serializer)
}
}
}
impl<'de> ::serde::Deserialize<'de> for GenericSignature {
fn deserialize<D: ::serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::Error;
if deserializer.is_human_readable() {
#[derive(serde::Deserialize)]
struct GenericSignature(String);
let s = GenericSignature::deserialize(deserializer)?;
Self::decode_base64(&s.0).map_err(::serde::de::Error::custom)
} else {
#[derive(serde::Deserialize)]
struct GenericSignature(Vec<u8>);
let data = GenericSignature::deserialize(deserializer)?;
Self::from_bytes(&data.0).map_err(|e| Error::custom(e.to_string()))
}
}
}