Skip to main content

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