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