ecvrf-rs 1.0.0

Elliptic Curve VRF implemented in Rust
Documentation
use core::fmt;

use schemars::{
    gen::SchemaGenerator,
    schema::{InstanceType, Schema, SchemaObject},
    JsonSchema,
};
use serde::{
    de::{Error, IgnoredAny, MapAccess, SeqAccess, Visitor},
    ser::SerializeStruct,
    Deserialize, Deserializer, Serialize, Serializer,
};

use crate::{Proof, PublicKey, SecretKey};
use std::{
    fmt::{Formatter, Write},
    num::ParseIntError,
};

impl AsRef<[u8]> for SecretKey {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

/// Decodes a hex-encoded string into a byte array.
///
/// # Errors
///
/// This function will return an error if the string is not hex-encoded.
pub fn decode_hex(s: &str) -> Result<Vec<u8>, ParseIntError> {
    (0..s.len())
        .step_by(2)
        .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
        .collect()
}

/// Encodes a byte array into a hex-encoded string.
///
/// # Panics
///
/// Panics if the call to [`write!`] returns an error.
#[must_use]
pub fn encode_hex(bytes: &[u8]) -> String {
    let mut s = String::with_capacity(bytes.len() * 2);
    for &b in bytes {
        write!(&mut s, "{:02x}", b).unwrap();
    }
    s
}

impl fmt::Display for SecretKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", encode_hex(&self.bytes))?;
        Ok(())
    }
}

impl fmt::Display for PublicKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", encode_hex(self.point.as_bytes()))?;
        Ok(())
    }
}

impl Serialize for PublicKey {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&encode_hex(self.point.as_bytes()))
    }
}

impl Serialize for SecretKey {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&encode_hex(self.as_bytes()))
    }
}

impl Serialize for Proof {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("Proof", 3)?;
        state.serialize_field("signer", &self.signer)?;
        state.serialize_field("message", &encode_hex(&self.message_bytes))?;
        state.serialize_field("proof", &encode_hex(&self.proof_bytes))?;
        state.end()
    }
}

impl<'de> Deserialize<'de> for PublicKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct PublicKeyVisitor;

        impl<'de> Visitor<'de> for PublicKeyVisitor {
            type Value = PublicKey;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("PublicKey bytes")
            }

            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
            where
                E: Error,
            {
                Ok(PublicKey::from_bytes(
                    decode_hex(v)
                        .map_err(|_| E::custom("Error decoding PublicKey bytes"))?
                        .as_slice(),
                ))
            }
        }

        deserializer.deserialize_str(PublicKeyVisitor)
    }
}

impl<'de> Deserialize<'de> for SecretKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct SecretKeyVisitor;

        impl<'de> Visitor<'de> for SecretKeyVisitor {
            type Value = SecretKey;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("SecretKey bytes")
            }

            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
            where
                E: Error,
            {
                Ok(SecretKey::from_slice(
                    decode_hex(v)
                        .map_err(|_| E::custom("Error decoding Secretkey bytes"))?
                        .as_slice(),
                ))
            }
        }

        deserializer.deserialize_str(SecretKeyVisitor)
    }
}

impl<'de> Deserialize<'de> for Proof {
    #[allow(clippy::too_many_lines)]
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        enum Field {
            Signer,
            Message,
            Proof,
            Ignore,
        }

        struct FieldVisitor;

        impl<'de> Visitor<'de> for FieldVisitor {
            type Value = Field;

            fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
                formatter.write_str("field identifier")
            }

            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
            where
                E: Error,
            {
                match v {
                    0u64 => Ok(Field::Signer),
                    1u64 => Ok(Field::Message),
                    2u64 => Ok(Field::Proof),
                    _ => Ok(Field::Ignore),
                }
            }

            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
            where
                E: Error,
            {
                match v {
                    "signer" => Ok(Field::Signer),
                    "message" => Ok(Field::Message),
                    "proof" => Ok(Field::Proof),
                    _ => Ok(Field::Ignore),
                }
            }

            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
            where
                E: Error,
            {
                match v {
                    b"signer" => Ok(Field::Signer),
                    b"message" => Ok(Field::Message),
                    b"proof" => Ok(Field::Proof),
                    _ => Ok(Field::Ignore),
                }
            }
        }

        impl<'de> Deserialize<'de> for Field {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: Deserializer<'de>,
            {
                deserializer.deserialize_identifier(FieldVisitor)
            }
        }

        struct ProofVisitor;

        impl<'de> Visitor<'de> for ProofVisitor {
            type Value = Proof;

            fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
                formatter.write_str("struct Proof")
            }

            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
            where
                A: SeqAccess<'de>,
            {
                let signer = seq
                    .next_element::<PublicKey>()?
                    .ok_or_else(|| A::Error::invalid_length(0, &"struct Proof with 3 elements"))?;
                let message = seq
                    .next_element::<String>()?
                    .ok_or_else(|| A::Error::invalid_length(1, &"struct Proof with 3 elements"))?;
                let proof = seq
                    .next_element::<String>()?
                    .ok_or_else(|| A::Error::invalid_length(2, &"struct Proof with 3 elements"))?;
                Ok(Proof {
                    signer,
                    message_bytes: decode_hex(message.as_str())
                        .map_err(|_| A::Error::custom("Error decoding message"))?,
                    proof_bytes: decode_hex(proof.as_str())
                        .map_err(|_| A::Error::custom("Error decoding proof"))?,
                })
            }

            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
            where
                A: MapAccess<'de>,
            {
                let mut signer = None;
                let mut message = None;
                let mut proof = None;
                while let Some(key) = map.next_key::<Field>()? {
                    match key {
                        Field::Signer => {
                            if signer.is_some() {
                                return Err(A::Error::duplicate_field("signer"));
                            }
                            signer = Some(map.next_value::<PublicKey>()?);
                        }
                        Field::Message => {
                            if message.is_some() {
                                return Err(A::Error::duplicate_field("message"));
                            }
                            message = Some(map.next_value::<String>()?);
                        }
                        Field::Proof => {
                            if proof.is_some() {
                                return Err(A::Error::duplicate_field("proof"));
                            }
                            proof = Some(map.next_value::<String>()?);
                        }
                        Field::Ignore => {
                            let _ = map.next_value::<IgnoredAny>()?;
                        }
                    }
                }
                let signer = signer.ok_or_else(|| A::Error::missing_field("signer"))?;
                let message = message.ok_or_else(|| A::Error::missing_field("message"))?;
                let proof = proof.ok_or_else(|| A::Error::missing_field("proof"))?;
                Ok(Proof {
                    signer,
                    message_bytes: decode_hex(message.as_str())
                        .map_err(|_| A::Error::custom("Error decoding message"))?,
                    proof_bytes: decode_hex(proof.as_str())
                        .map_err(|_| A::Error::custom("Error decoding proof"))?,
                })
            }
        }

        const FIELDS: &[&str] = &["signer", "message", "proof"];
        deserializer.deserialize_struct("Proof", FIELDS, ProofVisitor)
    }
}

impl JsonSchema for SecretKey {
    fn schema_name() -> String {
        "SecretKey".to_owned()
    }
    fn json_schema(_: &mut SchemaGenerator) -> Schema {
        let mut schema_object = SchemaObject {
            instance_type: Some(InstanceType::String.into()),
            ..Default::default()
        };
        let string_validation = schema_object.string();
        string_validation.min_length = Some(64u32);
        string_validation.max_length = Some(64u32);
        Schema::Object(schema_object)
    }
}

impl JsonSchema for PublicKey {
    fn schema_name() -> String {
        "PublicKey".to_owned()
    }
    fn json_schema(_: &mut SchemaGenerator) -> Schema {
        let mut schema_object = SchemaObject {
            instance_type: Some(InstanceType::String.into()),
            ..Default::default()
        };
        let string_validation = schema_object.string();
        string_validation.min_length = Some(64u32);
        string_validation.max_length = Some(64u32);
        Schema::Object(schema_object)
    }
}

impl JsonSchema for Proof {
    fn schema_name() -> String {
        "Proof".to_owned()
    }

    fn json_schema(gen: &mut SchemaGenerator) -> Schema {
        let mut schema_object = SchemaObject {
            instance_type: Some(InstanceType::Object.into()),
            ..Default::default()
        };
        let object_validation = schema_object.object();
        {
            // signer
            object_validation
                .properties
                .insert("signer".to_owned(), gen.subschema_for::<PublicKey>());
            object_validation.required.insert("signer".to_owned());
        }
        {
            // message
            object_validation
                .properties
                .insert("message".to_owned(), gen.subschema_for::<String>());
            object_validation.required.insert("message".to_owned());
        }

        {
            // proof
            object_validation
                .properties
                .insert("proof".to_owned(), gen.subschema_for::<String>());
            object_validation.required.insert("proof".to_owned());
        }
        Schema::Object(schema_object)
    }
}