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;
30use rand::rngs::OsRng;
31use thiserror::Error;
32
33use crate::traits::Author;
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
145#[cfg(feature = "arbitrary")]
146impl<'a> Arbitrary<'a> for SigningKey {
147    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
148        let bytes = <[u8; SIGNING_KEY_LEN] as Arbitrary>::arbitrary(u)?;
149        Ok(SigningKey::from_bytes(&bytes))
150    }
151}
152
153/// Public Ed25519 key used for identifying peers and verifying signed data.
154#[derive(Default, Hash, PartialEq, Eq, Copy, Clone)]
155pub struct VerifyingKey(ed25519_dalek::VerifyingKey);
156
157impl PartialOrd for VerifyingKey {
158    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
159        Some(self.cmp(other))
160    }
161}
162
163impl Ord for VerifyingKey {
164    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
165        self.to_hex().cmp(&other.to_hex())
166    }
167}
168
169impl VerifyingKey {
170    /// Create a `VerifyingKey` from its raw bytes representation.
171    pub fn from_bytes(bytes: &[u8; VERIFYING_KEY_LEN]) -> Result<Self, IdentityError> {
172        Ok(Self(ed25519_dalek::VerifyingKey::from_bytes(bytes)?))
173    }
174
175    /// Bytes of the public key.
176    pub fn as_bytes(&self) -> &[u8; VERIFYING_KEY_LEN] {
177        self.0.as_bytes()
178    }
179
180    /// Convert the public key to a hex string.
181    pub fn to_hex(&self) -> String {
182        hex::encode(self.0.as_bytes())
183    }
184
185    /// Verify a signature over a byte slice with this public key.
186    pub fn verify(&self, bytes: &[u8], signature: &Signature) -> bool {
187        self.0.verify_strict(bytes, &signature.0).is_ok()
188    }
189}
190
191impl fmt::Display for VerifyingKey {
192    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193        write!(f, "{}", self.to_hex())
194    }
195}
196
197impl fmt::Debug for VerifyingKey {
198    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199        f.debug_tuple("VerifyingKey")
200            .field(self.0.as_bytes())
201            .finish()
202    }
203}
204
205impl From<VerifyingKey> for ed25519_dalek::VerifyingKey {
206    fn from(value: VerifyingKey) -> Self {
207        value.0
208    }
209}
210
211impl From<ed25519_dalek::VerifyingKey> for VerifyingKey {
212    fn from(value: ed25519_dalek::VerifyingKey) -> Self {
213        Self(value)
214    }
215}
216
217impl TryFrom<[u8; VERIFYING_KEY_LEN]> for VerifyingKey {
218    type Error = IdentityError;
219
220    fn try_from(value: [u8; VERIFYING_KEY_LEN]) -> Result<Self, Self::Error> {
221        Self::from_bytes(&value)
222    }
223}
224
225impl From<VerifyingKey> for [u8; VERIFYING_KEY_LEN] {
226    fn from(value: VerifyingKey) -> Self {
227        *value.as_bytes()
228    }
229}
230
231impl TryFrom<&[u8; VERIFYING_KEY_LEN]> for VerifyingKey {
232    type Error = IdentityError;
233
234    fn try_from(value: &[u8; VERIFYING_KEY_LEN]) -> Result<Self, Self::Error> {
235        Self::from_bytes(value)
236    }
237}
238
239impl TryFrom<&[u8]> for VerifyingKey {
240    type Error = IdentityError;
241
242    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
243        let value_len = value.len();
244
245        let checked_value: [u8; VERIFYING_KEY_LEN] = value
246            .try_into()
247            .map_err(|_| IdentityError::InvalidLength(value_len, VERIFYING_KEY_LEN))?;
248
249        Self::try_from(checked_value)
250    }
251}
252
253impl FromStr for VerifyingKey {
254    type Err = IdentityError;
255
256    fn from_str(value: &str) -> Result<Self, Self::Err> {
257        Self::try_from(hex::decode(value)?.as_slice())
258    }
259}
260
261impl Author for VerifyingKey {}
262
263#[cfg(feature = "arbitrary")]
264impl<'a> Arbitrary<'a> for VerifyingKey {
265    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
266        let bytes = <[u8; VERIFYING_KEY_LEN] as Arbitrary>::arbitrary(u)?;
267        let verifying_key =
268            VerifyingKey::from_bytes(&bytes).map_err(|_| arbitrary::Error::IncorrectFormat)?;
269        Ok(verifying_key)
270    }
271}
272
273/// Ed25519 signature.
274#[derive(Copy, Eq, PartialEq, Clone)]
275pub struct Signature(ed25519_dalek::Signature);
276
277impl Signature {
278    /// Create a `Signature` from its raw bytes representation.
279    pub fn from_bytes(bytes: &[u8; SIGNATURE_LEN]) -> Self {
280        Self(ed25519_dalek::Signature::from_bytes(bytes))
281    }
282
283    /// Bytes of the signature.
284    pub fn to_bytes(&self) -> [u8; SIGNATURE_LEN] {
285        let mut ret = [0u8; SIGNATURE_LEN];
286        let (r, s) = ret.split_at_mut(32);
287        r.copy_from_slice(self.0.r_bytes());
288        s.copy_from_slice(self.0.s_bytes());
289        ret
290    }
291
292    /// Convert the signature to a hex string.
293    pub fn to_hex(&self) -> String {
294        hex::encode(self.to_bytes())
295    }
296}
297
298impl fmt::Display for Signature {
299    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300        write!(f, "{}", self.to_hex())
301    }
302}
303
304impl fmt::Debug for Signature {
305    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
306        f.debug_tuple("Signature").field(&self.to_bytes()).finish()
307    }
308}
309
310impl FromStr for Signature {
311    type Err = IdentityError;
312
313    fn from_str(value: &str) -> Result<Self, Self::Err> {
314        Self::try_from(hex::decode(value)?.as_slice())
315    }
316}
317
318impl From<Signature> for ed25519_dalek::Signature {
319    fn from(value: Signature) -> Self {
320        value.0
321    }
322}
323
324impl From<ed25519_dalek::Signature> for Signature {
325    fn from(value: ed25519_dalek::Signature) -> Self {
326        Self(value)
327    }
328}
329
330impl From<[u8; SIGNATURE_LEN]> for Signature {
331    fn from(value: [u8; SIGNATURE_LEN]) -> Self {
332        Self::from_bytes(&value)
333    }
334}
335
336impl From<&[u8; SIGNATURE_LEN]> for Signature {
337    fn from(value: &[u8; SIGNATURE_LEN]) -> Self {
338        Self::from_bytes(value)
339    }
340}
341
342impl TryFrom<&[u8]> for Signature {
343    type Error = IdentityError;
344
345    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
346        let value_len = value.len();
347
348        let checked_value: [u8; SIGNATURE_LEN] = value
349            .try_into()
350            .map_err(|_| IdentityError::InvalidLength(value_len, SIGNATURE_LEN))?;
351
352        Ok(Self::from(checked_value))
353    }
354}
355
356#[cfg(feature = "arbitrary")]
357impl<'a> Arbitrary<'a> for Signature {
358    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
359        let bytes = <[u8; SIGNATURE_LEN] as Arbitrary>::arbitrary(u)?;
360        Ok(Signature::from_bytes(&bytes))
361    }
362}
363
364#[derive(Error, Debug)]
365pub enum IdentityError {
366    /// Invalid number of bytes.
367    #[error("invalid bytes length of {0}, expected {1} bytes")]
368    InvalidLength(usize, usize),
369
370    /// String contains invalid hexadecimal characters.
371    #[error("invalid hex encoding in string")]
372    InvalidHexEncoding(#[from] hex::FromHexError),
373
374    /// Errors which may occur while processing signatures and key pairs.
375    ///
376    /// This error may arise due to:
377    ///
378    /// * Being given bytes with a length different to what was expected.
379    ///
380    /// * A problem decompressing `r`, a curve point, in the `Signature`, or the curve point for a
381    ///   `VerifyingKey`.
382    ///
383    /// * Failure of a signature to satisfy the verification equation.
384    #[error("invalid signature: {0}")]
385    InvalidSignature(#[from] ed25519_dalek::SignatureError),
386}
387
388#[cfg(test)]
389mod tests {
390    use super::SigningKey;
391
392    #[test]
393    fn signing() {
394        let signing_key = SigningKey::generate();
395        let verifying_key = signing_key.verifying_key();
396        let bytes = b"test";
397        let signature = signing_key.sign(bytes);
398        assert!(verifying_key.verify(bytes, &signature));
399
400        // Invalid data
401        assert!(!verifying_key.verify(b"not test", &signature));
402
403        // Invalid public key
404        let verifying_key_2 = SigningKey::generate().verifying_key();
405        assert!(!verifying_key_2.verify(bytes, &signature));
406    }
407}