ab_core_primitives/
ed25519.rs

1//! Primitives related to Ed25519
2
3use crate::hashes::Blake3Hash;
4use ab_blake3::single_block_hash;
5use ab_io_type::trivial_type::TrivialType;
6use core::fmt;
7use derive_more::{Deref, From, Into};
8use ed25519_zebra::{Error, Signature, VerificationKey};
9#[cfg(feature = "scale-codec")]
10use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
11#[cfg(feature = "scale-codec")]
12use scale_info::TypeInfo;
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Deserializer, Serialize, Serializer};
15#[cfg(feature = "serde")]
16use serde_big_array::BigArray;
17
18/// Ed25519 public key
19#[derive(
20    Default, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Deref, From, Into, TrivialType,
21)]
22#[cfg_attr(
23    feature = "scale-codec",
24    derive(Encode, Decode, TypeInfo, MaxEncodedLen)
25)]
26#[repr(C)]
27pub struct Ed25519PublicKey([u8; Ed25519PublicKey::SIZE]);
28
29impl From<VerificationKey> for Ed25519PublicKey {
30    #[inline(always)]
31    fn from(verification_key: VerificationKey) -> Self {
32        Ed25519PublicKey(verification_key.into())
33    }
34}
35
36impl fmt::Debug for Ed25519PublicKey {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        for byte in self.0 {
39            write!(f, "{byte:02x}")?;
40        }
41        Ok(())
42    }
43}
44
45#[cfg(feature = "serde")]
46#[derive(Serialize, Deserialize)]
47#[serde(transparent)]
48struct Ed25519PublicKeyBinary([u8; Ed25519PublicKey::SIZE]);
49
50#[cfg(feature = "serde")]
51#[derive(Serialize, Deserialize)]
52#[serde(transparent)]
53struct Ed25519PublicKeyHex(#[serde(with = "hex")] [u8; Ed25519PublicKey::SIZE]);
54
55#[cfg(feature = "serde")]
56impl Serialize for Ed25519PublicKey {
57    #[inline]
58    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59    where
60        S: Serializer,
61    {
62        if serializer.is_human_readable() {
63            Ed25519PublicKeyHex(self.0).serialize(serializer)
64        } else {
65            Ed25519PublicKeyBinary(self.0).serialize(serializer)
66        }
67    }
68}
69
70#[cfg(feature = "serde")]
71impl<'de> Deserialize<'de> for Ed25519PublicKey {
72    #[inline]
73    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
74    where
75        D: Deserializer<'de>,
76    {
77        Ok(Self(if deserializer.is_human_readable() {
78            Ed25519PublicKeyHex::deserialize(deserializer)?.0
79        } else {
80            Ed25519PublicKeyBinary::deserialize(deserializer)?.0
81        }))
82    }
83}
84
85impl fmt::Display for Ed25519PublicKey {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        for byte in self.0 {
88            write!(f, "{byte:02x}")?;
89        }
90        Ok(())
91    }
92}
93
94impl AsRef<[u8]> for Ed25519PublicKey {
95    #[inline]
96    fn as_ref(&self) -> &[u8] {
97        &self.0
98    }
99}
100
101impl Ed25519PublicKey {
102    /// Public key size in bytes
103    pub const SIZE: usize = 32;
104
105    /// Public key hash.
106    pub fn hash(&self) -> Blake3Hash {
107        Blake3Hash::new(
108            single_block_hash(&self.0).expect("Less than a single block worth of bytes; qed"),
109        )
110    }
111
112    /// Verify Ed25519 signature
113    #[inline]
114    pub fn verify(&self, signature: &Ed25519Signature, msg: &[u8]) -> Result<(), Error> {
115        VerificationKey::try_from(self.0)?.verify(&Signature::from_bytes(signature), msg)
116    }
117}
118
119/// Ed25519 signature
120#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Deref, From, Into, TrivialType)]
121#[cfg_attr(
122    feature = "scale-codec",
123    derive(Encode, Decode, TypeInfo, MaxEncodedLen)
124)]
125#[repr(C)]
126pub struct Ed25519Signature([u8; Ed25519Signature::SIZE]);
127
128impl From<Signature> for Ed25519Signature {
129    #[inline(always)]
130    fn from(signature: Signature) -> Self {
131        Ed25519Signature::from(signature.to_bytes())
132    }
133}
134
135impl Default for Ed25519Signature {
136    fn default() -> Self {
137        Self([0; Self::SIZE])
138    }
139}
140
141impl fmt::Debug for Ed25519Signature {
142    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143        for byte in self.0 {
144            write!(f, "{byte:02x}")?;
145        }
146        Ok(())
147    }
148}
149
150#[cfg(feature = "serde")]
151#[derive(Serialize, Deserialize)]
152#[serde(transparent)]
153struct Ed25519SignatureBinary(#[serde(with = "BigArray")] [u8; Ed25519Signature::SIZE]);
154
155#[cfg(feature = "serde")]
156#[derive(Serialize, Deserialize)]
157#[serde(transparent)]
158struct Ed25519SignatureHex(#[serde(with = "hex")] [u8; Ed25519Signature::SIZE]);
159
160#[cfg(feature = "serde")]
161impl Serialize for Ed25519Signature {
162    #[inline]
163    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
164    where
165        S: Serializer,
166    {
167        if serializer.is_human_readable() {
168            Ed25519SignatureHex(self.0).serialize(serializer)
169        } else {
170            Ed25519SignatureBinary(self.0).serialize(serializer)
171        }
172    }
173}
174
175#[cfg(feature = "serde")]
176impl<'de> Deserialize<'de> for Ed25519Signature {
177    #[inline]
178    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
179    where
180        D: Deserializer<'de>,
181    {
182        Ok(Self(if deserializer.is_human_readable() {
183            Ed25519SignatureHex::deserialize(deserializer)?.0
184        } else {
185            Ed25519SignatureBinary::deserialize(deserializer)?.0
186        }))
187    }
188}
189
190impl fmt::Display for Ed25519Signature {
191    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192        for byte in self.0 {
193            write!(f, "{byte:02x}")?;
194        }
195        Ok(())
196    }
197}
198
199impl AsRef<[u8]> for Ed25519Signature {
200    #[inline]
201    fn as_ref(&self) -> &[u8] {
202        &self.0
203    }
204}
205
206impl Ed25519Signature {
207    /// Signature size in bytes
208    pub const SIZE: usize = 64;
209}