Skip to main content

p2panda_core/
identity.rs

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