p2panda_core/
identity.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3//! Ed25519 key pairs and signatures.
4//!
5//! The `PrivateKey` is used for creating digital signatures and the `PublicKey` is used for
6//! verifying that a signature was indeed created by it's private counterpart. The private part of
7//! a key pair is typically kept securely on one device and never transported, whereas the public
8//! part acts as a peer's unique identifier and can be shared freely.
9//!
10//! ## Example
11//!
12//! ```
13//! use p2panda_core::identity::PrivateKey;
14//!
15//! let private_key = PrivateKey::new();
16//! let public_key = private_key.public_key();
17//!
18//! let bytes: &[u8] = b"A very important message.";
19//! let signature = private_key.sign(bytes);
20//!
21//! assert!(public_key.verify(bytes, &signature))
22//! ```
23use std::fmt;
24use std::str::FromStr;
25
26#[cfg(feature = "arbitrary")]
27use arbitrary::Arbitrary;
28use ed25519_dalek::Signer;
29use rand::rngs::OsRng;
30use thiserror::Error;
31
32/// The length of an Ed25519 `Signature`, in bytes.
33pub const SIGNATURE_LEN: usize = ed25519_dalek::SIGNATURE_LENGTH;
34
35/// The length of an Ed25519 `PrivateKey`, in bytes.
36pub const PRIVATE_KEY_LEN: usize = ed25519_dalek::SECRET_KEY_LENGTH;
37
38/// The length of an Ed25519 `PublicKey`, in bytes.
39pub const PUBLIC_KEY_LEN: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
40
41/// Private Ed25519 key used for digital signatures.
42#[derive(Clone)]
43pub struct PrivateKey(ed25519_dalek::SigningKey);
44
45impl Default for PrivateKey {
46    fn default() -> Self {
47        Self::new()
48    }
49}
50
51impl PrivateKey {
52    /// Generates a new private key using the system's random number generator (CSPRNG) as a seed.
53    pub fn new() -> Self {
54        let mut csprng: OsRng = OsRng;
55        let private_key = ed25519_dalek::SigningKey::generate(&mut csprng);
56        Self(private_key)
57    }
58
59    /// Create a `PrivateKey` from its raw bytes representation.
60    pub fn from_bytes(bytes: &[u8; PRIVATE_KEY_LEN]) -> Self {
61        Self(ed25519_dalek::SigningKey::from_bytes(bytes))
62    }
63
64    /// Bytes of the private key.
65    pub fn as_bytes(&self) -> &[u8; PRIVATE_KEY_LEN] {
66        self.0.as_bytes()
67    }
68
69    /// Convert the private key to a hex string.
70    pub fn to_hex(&self) -> String {
71        hex::encode(self.0.as_bytes())
72    }
73
74    /// Returns public key using this private counterpart.
75    pub fn public_key(&self) -> PublicKey {
76        self.0.verifying_key().into()
77    }
78
79    /// Sign the provided bytestring using this private key returning a digital signature.
80    pub fn sign(&self, bytes: &[u8]) -> Signature {
81        self.0.sign(bytes).into()
82    }
83}
84
85impl fmt::Display for PrivateKey {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        write!(f, "{}", self.to_hex())
88    }
89}
90
91impl fmt::Debug for PrivateKey {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        f.debug_tuple("PrivateKey")
94            .field(self.0.as_bytes())
95            .finish()
96    }
97}
98
99impl From<[u8; PRIVATE_KEY_LEN]> for PrivateKey {
100    fn from(value: [u8; PRIVATE_KEY_LEN]) -> Self {
101        Self::from_bytes(&value)
102    }
103}
104
105impl From<PrivateKey> for [u8; PRIVATE_KEY_LEN] {
106    fn from(value: PrivateKey) -> Self {
107        *value.as_bytes()
108    }
109}
110
111impl From<&[u8; PRIVATE_KEY_LEN]> for PrivateKey {
112    fn from(value: &[u8; PRIVATE_KEY_LEN]) -> Self {
113        Self::from_bytes(value)
114    }
115}
116
117impl TryFrom<&[u8]> for PrivateKey {
118    type Error = IdentityError;
119
120    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
121        let value_len = value.len();
122
123        let checked_value: [u8; PRIVATE_KEY_LEN] = value
124            .try_into()
125            .map_err(|_| IdentityError::InvalidLength(value_len, PRIVATE_KEY_LEN))?;
126
127        Ok(Self::from(checked_value))
128    }
129}
130
131#[cfg(feature = "arbitrary")]
132impl<'a> Arbitrary<'a> for PrivateKey {
133    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
134        let bytes = <[u8; PRIVATE_KEY_LEN] as Arbitrary>::arbitrary(u)?;
135        Ok(PrivateKey::from_bytes(&bytes))
136    }
137}
138
139/// Public Ed25519 key used for identifying peers and verifying signed data.
140#[derive(Default, Hash, PartialEq, Eq, Copy, Clone)]
141pub struct PublicKey(ed25519_dalek::VerifyingKey);
142
143impl PartialOrd for PublicKey {
144    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
145        Some(self.cmp(other))
146    }
147}
148
149impl Ord for PublicKey {
150    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
151        self.to_hex().cmp(&other.to_hex())
152    }
153}
154
155impl PublicKey {
156    /// Create a `PublicKey` from its raw bytes representation.
157    pub fn from_bytes(bytes: &[u8; PUBLIC_KEY_LEN]) -> Result<Self, IdentityError> {
158        Ok(Self(ed25519_dalek::VerifyingKey::from_bytes(bytes)?))
159    }
160
161    /// Bytes of the public key.
162    pub fn as_bytes(&self) -> &[u8; PUBLIC_KEY_LEN] {
163        self.0.as_bytes()
164    }
165
166    /// Convert the public key to a hex string.
167    pub fn to_hex(&self) -> String {
168        hex::encode(self.0.as_bytes())
169    }
170
171    /// Verify a signature over a byte slice with this public key.
172    pub fn verify(&self, bytes: &[u8], signature: &Signature) -> bool {
173        self.0.verify_strict(bytes, &signature.0).is_ok()
174    }
175}
176
177impl fmt::Display for PublicKey {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        write!(f, "{}", self.to_hex())
180    }
181}
182
183impl fmt::Debug for PublicKey {
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        f.debug_tuple("PublicKey").field(self.0.as_bytes()).finish()
186    }
187}
188
189impl From<PublicKey> for ed25519_dalek::VerifyingKey {
190    fn from(value: PublicKey) -> Self {
191        value.0
192    }
193}
194
195impl From<ed25519_dalek::VerifyingKey> for PublicKey {
196    fn from(value: ed25519_dalek::VerifyingKey) -> Self {
197        Self(value)
198    }
199}
200
201impl TryFrom<[u8; PUBLIC_KEY_LEN]> for PublicKey {
202    type Error = IdentityError;
203
204    fn try_from(value: [u8; PUBLIC_KEY_LEN]) -> Result<Self, Self::Error> {
205        Self::from_bytes(&value)
206    }
207}
208
209impl From<PublicKey> for [u8; PUBLIC_KEY_LEN] {
210    fn from(value: PublicKey) -> Self {
211        *value.as_bytes()
212    }
213}
214
215impl TryFrom<&[u8; PUBLIC_KEY_LEN]> for PublicKey {
216    type Error = IdentityError;
217
218    fn try_from(value: &[u8; PUBLIC_KEY_LEN]) -> Result<Self, Self::Error> {
219        Self::from_bytes(value)
220    }
221}
222
223impl TryFrom<&[u8]> for PublicKey {
224    type Error = IdentityError;
225
226    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
227        let value_len = value.len();
228
229        let checked_value: [u8; PUBLIC_KEY_LEN] = value
230            .try_into()
231            .map_err(|_| IdentityError::InvalidLength(value_len, PUBLIC_KEY_LEN))?;
232
233        Self::try_from(checked_value)
234    }
235}
236
237impl FromStr for PublicKey {
238    type Err = IdentityError;
239
240    fn from_str(value: &str) -> Result<Self, Self::Err> {
241        Self::try_from(hex::decode(value)?.as_slice())
242    }
243}
244
245#[cfg(feature = "arbitrary")]
246impl<'a> Arbitrary<'a> for PublicKey {
247    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
248        let bytes = <[u8; PUBLIC_KEY_LEN] as Arbitrary>::arbitrary(u)?;
249        let public_key =
250            PublicKey::from_bytes(&bytes).map_err(|_| arbitrary::Error::IncorrectFormat)?;
251        Ok(public_key)
252    }
253}
254
255/// Ed25519 signature.
256#[derive(Copy, Eq, PartialEq, Clone)]
257pub struct Signature(ed25519_dalek::Signature);
258
259impl Signature {
260    /// Create a `Signature` from its raw bytes representation.
261    pub fn from_bytes(bytes: &[u8; SIGNATURE_LEN]) -> Self {
262        Self(ed25519_dalek::Signature::from_bytes(bytes))
263    }
264
265    /// Bytes of the signature.
266    pub fn to_bytes(&self) -> [u8; SIGNATURE_LEN] {
267        let mut ret = [0u8; SIGNATURE_LEN];
268        let (r, s) = ret.split_at_mut(32);
269        r.copy_from_slice(self.0.r_bytes());
270        s.copy_from_slice(self.0.s_bytes());
271        ret
272    }
273
274    /// Convert the signature to a hex string.
275    pub fn to_hex(&self) -> String {
276        hex::encode(self.to_bytes())
277    }
278}
279
280impl fmt::Display for Signature {
281    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282        write!(f, "{}", self.to_hex())
283    }
284}
285
286impl fmt::Debug for Signature {
287    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288        f.debug_tuple("Signature").field(&self.to_bytes()).finish()
289    }
290}
291
292impl FromStr for Signature {
293    type Err = IdentityError;
294
295    fn from_str(value: &str) -> Result<Self, Self::Err> {
296        Self::try_from(hex::decode(value)?.as_slice())
297    }
298}
299
300impl From<Signature> for ed25519_dalek::Signature {
301    fn from(value: Signature) -> Self {
302        value.0
303    }
304}
305
306impl From<ed25519_dalek::Signature> for Signature {
307    fn from(value: ed25519_dalek::Signature) -> Self {
308        Self(value)
309    }
310}
311
312impl From<[u8; SIGNATURE_LEN]> for Signature {
313    fn from(value: [u8; SIGNATURE_LEN]) -> Self {
314        Self::from_bytes(&value)
315    }
316}
317
318impl From<&[u8; SIGNATURE_LEN]> for Signature {
319    fn from(value: &[u8; SIGNATURE_LEN]) -> Self {
320        Self::from_bytes(value)
321    }
322}
323
324impl TryFrom<&[u8]> for Signature {
325    type Error = IdentityError;
326
327    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
328        let value_len = value.len();
329
330        let checked_value: [u8; SIGNATURE_LEN] = value
331            .try_into()
332            .map_err(|_| IdentityError::InvalidLength(value_len, SIGNATURE_LEN))?;
333
334        Ok(Self::from(checked_value))
335    }
336}
337
338#[cfg(feature = "arbitrary")]
339impl<'a> Arbitrary<'a> for Signature {
340    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
341        let bytes = <[u8; SIGNATURE_LEN] as Arbitrary>::arbitrary(u)?;
342        Ok(Signature::from_bytes(&bytes))
343    }
344}
345
346#[derive(Error, Debug)]
347pub enum IdentityError {
348    /// Invalid number of bytes.
349    #[error("invalid bytes length of {0}, expected {1} bytes")]
350    InvalidLength(usize, usize),
351
352    /// String contains invalid hexadecimal characters.
353    #[error("invalid hex encoding in string")]
354    InvalidHexEncoding(#[from] hex::FromHexError),
355
356    /// Errors which may occur while processing signatures and key pairs.
357    ///
358    /// This error may arise due to:
359    ///
360    /// * Being given bytes with a length different to what was expected.
361    ///
362    /// * A problem decompressing `r`, a curve point, in the `Signature`, or the curve point for a
363    ///   `PublicKey`.
364    ///
365    /// * Failure of a signature to satisfy the verification equation.
366    #[error("invalid signature: {0}")]
367    InvalidSignature(#[from] ed25519_dalek::SignatureError),
368}
369
370#[cfg(test)]
371mod tests {
372    use super::PrivateKey;
373
374    #[test]
375    fn signing() {
376        let private_key = PrivateKey::new();
377        let public_key = private_key.public_key();
378        let bytes = b"test";
379        let signature = private_key.sign(bytes);
380        assert!(public_key.verify(bytes, &signature));
381
382        // Invalid data
383        assert!(!public_key.verify(b"not test", &signature));
384
385        // Invalid public key
386        let public_key_2 = PrivateKey::new().public_key();
387        assert!(!public_key_2.verify(bytes, &signature));
388    }
389}