iroh_docs/
keys.rs

1//! Keys used in iroh-docs
2
3use std::{cmp::Ordering, fmt, str::FromStr};
4
5use ed25519_dalek::{Signature, SignatureError, Signer, SigningKey, VerifyingKey};
6use rand_core::CryptoRngCore;
7use serde::{Deserialize, Serialize};
8
9use crate::store::PublicKeyStore;
10
11/// Author key to insert entries in a [`crate::Replica`]
12///
13/// Internally, an author is a [`SigningKey`] which is used to sign entries.
14#[derive(Clone, Serialize, Deserialize)]
15pub struct Author {
16    signing_key: SigningKey,
17}
18impl Author {
19    /// Create a new [`Author`] with a random key.
20    pub fn new<R: CryptoRngCore + ?Sized>(rng: &mut R) -> Self {
21        let signing_key = SigningKey::generate(rng);
22        Author { signing_key }
23    }
24
25    /// Create an [`Author`] from a byte array.
26    pub fn from_bytes(bytes: &[u8; 32]) -> Self {
27        SigningKey::from_bytes(bytes).into()
28    }
29
30    /// Returns the [`Author`] byte representation.
31    pub fn to_bytes(&self) -> [u8; 32] {
32        self.signing_key.to_bytes()
33    }
34
35    /// Get the [`AuthorPublicKey`] for this author.
36    pub fn public_key(&self) -> AuthorPublicKey {
37        AuthorPublicKey(self.signing_key.verifying_key())
38    }
39
40    /// Get the [`AuthorId`] for this author.
41    pub fn id(&self) -> AuthorId {
42        AuthorId::from(self.public_key())
43    }
44
45    /// Sign a message with this [`Author`] key.
46    pub fn sign(&self, msg: &[u8]) -> Signature {
47        self.signing_key.sign(msg)
48    }
49
50    /// Strictly verify a signature on a message with this [`Author`]'s public key.
51    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
52        self.signing_key.verify_strict(msg, signature)
53    }
54}
55
56/// Identifier for an [`Author`]
57///
58/// This is the corresponding [`VerifyingKey`] for an author. It is used as an identifier, and can
59/// be used to verify [`Signature`]s.
60#[derive(Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, derive_more::From)]
61pub struct AuthorPublicKey(VerifyingKey);
62
63impl AuthorPublicKey {
64    /// Verify that a signature matches the `msg` bytes and was created with the [`Author`]
65    /// that corresponds to this [`AuthorId`].
66    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
67        self.0.verify_strict(msg, signature)
68    }
69
70    /// Get the byte representation of this [`AuthorId`].
71    pub fn as_bytes(&self) -> &[u8; 32] {
72        self.0.as_bytes()
73    }
74
75    /// Create from a slice of bytes.
76    ///
77    /// Will return an error if the input bytes do not represent a valid [`ed25519_dalek`]
78    /// curve point. Will never fail for a byte array returned from [`Self::as_bytes`].
79    /// See [`VerifyingKey::from_bytes`] for details.
80    pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
81        Ok(AuthorPublicKey(VerifyingKey::from_bytes(bytes)?))
82    }
83}
84
85/// Namespace key of a [`crate::Replica`].
86///
87/// Holders of this key can insert new entries into a [`crate::Replica`].
88/// Internally, a [`NamespaceSecret`] is a [`SigningKey`] which is used to sign entries.
89#[derive(Clone, Serialize, Deserialize)]
90pub struct NamespaceSecret {
91    signing_key: SigningKey,
92}
93
94impl NamespaceSecret {
95    /// Create a new [`NamespaceSecret`] with a random key.
96    pub fn new<R: CryptoRngCore + ?Sized>(rng: &mut R) -> Self {
97        let signing_key = SigningKey::generate(rng);
98
99        NamespaceSecret { signing_key }
100    }
101
102    /// Create a [`NamespaceSecret`] from a byte array.
103    pub fn from_bytes(bytes: &[u8; 32]) -> Self {
104        SigningKey::from_bytes(bytes).into()
105    }
106
107    /// Returns the [`NamespaceSecret`] byte representation.
108    pub fn to_bytes(&self) -> [u8; 32] {
109        self.signing_key.to_bytes()
110    }
111
112    /// Get the [`NamespacePublicKey`] for this namespace.
113    pub fn public_key(&self) -> NamespacePublicKey {
114        NamespacePublicKey(self.signing_key.verifying_key())
115    }
116
117    /// Get the [`NamespaceId`] for this namespace.
118    pub fn id(&self) -> NamespaceId {
119        NamespaceId::from(self.public_key())
120    }
121
122    /// Sign a message with this [`NamespaceSecret`] key.
123    pub fn sign(&self, msg: &[u8]) -> Signature {
124        self.signing_key.sign(msg)
125    }
126
127    /// Strictly verify a signature on a message with this [`NamespaceSecret`]'s public key.
128    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
129        self.signing_key.verify_strict(msg, signature)
130    }
131}
132
133/// The corresponding [`VerifyingKey`] for a [`NamespaceSecret`].
134/// It is used as an identifier, and can be used to verify [`Signature`]s.
135#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, derive_more::From)]
136pub struct NamespacePublicKey(VerifyingKey);
137
138impl NamespacePublicKey {
139    /// Verify that a signature matches the `msg` bytes and was created with the [`NamespaceSecret`]
140    /// that corresponds to this [`NamespaceId`].
141    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
142        self.0.verify_strict(msg, signature)
143    }
144
145    /// Get the byte representation of this [`NamespaceId`].
146    pub fn as_bytes(&self) -> &[u8; 32] {
147        self.0.as_bytes()
148    }
149
150    /// Create from a slice of bytes.
151    ///
152    /// Will return an error if the input bytes do not represent a valid [`ed25519_dalek`]
153    /// curve point. Will never fail for a byte array returned from [`Self::as_bytes`].
154    /// See [`VerifyingKey::from_bytes`] for details.
155    pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
156        Ok(NamespacePublicKey(VerifyingKey::from_bytes(bytes)?))
157    }
158}
159
160impl fmt::Display for Author {
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        write!(f, "{}", hex::encode(self.to_bytes()))
163    }
164}
165
166impl fmt::Display for NamespaceSecret {
167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168        write!(f, "{}", hex::encode(self.to_bytes()))
169    }
170}
171
172impl fmt::Display for AuthorPublicKey {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        write!(f, "{}", hex::encode(self.as_bytes()))
175    }
176}
177
178impl fmt::Display for NamespacePublicKey {
179    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180        write!(f, "{}", hex::encode(self.as_bytes()))
181    }
182}
183
184impl fmt::Display for AuthorId {
185    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186        write!(f, "{}", hex::encode(self.as_bytes()))
187    }
188}
189
190impl fmt::Display for NamespaceId {
191    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192        write!(f, "{}", hex::encode(self.as_bytes()))
193    }
194}
195
196impl fmt::Debug for NamespaceSecret {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        write!(f, "Namespace({})", self)
199    }
200}
201
202impl fmt::Debug for NamespaceId {
203    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204        write!(f, "NamespaceId({})", hex::encode(self.0))
205    }
206}
207
208impl fmt::Debug for AuthorId {
209    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210        write!(f, "AuthorId({})", hex::encode(self.0))
211    }
212}
213
214impl fmt::Debug for Author {
215    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216        write!(f, "Author({})", self)
217    }
218}
219
220impl fmt::Debug for NamespacePublicKey {
221    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222        write!(f, "NamespacePublicKey({})", self)
223    }
224}
225
226impl fmt::Debug for AuthorPublicKey {
227    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228        write!(f, "AuthorPublicKey({})", self)
229    }
230}
231
232fn parse_hex_array(s: &str) -> anyhow::Result<[u8; 32]> {
233    let mut bytes = [0u8; 32];
234    hex::decode_to_slice(s, &mut bytes)?;
235    Ok(bytes)
236}
237
238impl FromStr for Author {
239    type Err = anyhow::Error;
240
241    fn from_str(s: &str) -> Result<Self, Self::Err> {
242        Ok(Self::from_bytes(&parse_hex_array(s)?))
243    }
244}
245
246impl FromStr for NamespaceSecret {
247    type Err = anyhow::Error;
248
249    fn from_str(s: &str) -> Result<Self, Self::Err> {
250        Ok(Self::from_bytes(&parse_hex_array(s)?))
251    }
252}
253
254impl FromStr for AuthorPublicKey {
255    type Err = anyhow::Error;
256
257    fn from_str(s: &str) -> Result<Self, Self::Err> {
258        Self::from_bytes(&parse_hex_array(s)?).map_err(Into::into)
259    }
260}
261
262impl FromStr for NamespacePublicKey {
263    type Err = anyhow::Error;
264
265    fn from_str(s: &str) -> Result<Self, Self::Err> {
266        Self::from_bytes(&parse_hex_array(s)?).map_err(Into::into)
267    }
268}
269
270impl From<SigningKey> for Author {
271    fn from(signing_key: SigningKey) -> Self {
272        Self { signing_key }
273    }
274}
275
276impl From<SigningKey> for NamespaceSecret {
277    fn from(signing_key: SigningKey) -> Self {
278        Self { signing_key }
279    }
280}
281
282impl PartialOrd for NamespacePublicKey {
283    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
284        Some(self.cmp(other))
285    }
286}
287
288impl Ord for NamespacePublicKey {
289    fn cmp(&self, other: &Self) -> Ordering {
290        self.0.as_bytes().cmp(other.0.as_bytes())
291    }
292}
293
294impl PartialOrd for AuthorPublicKey {
295    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
296        Some(self.cmp(other))
297    }
298}
299
300impl Ord for AuthorPublicKey {
301    fn cmp(&self, other: &Self) -> Ordering {
302        self.0.as_bytes().cmp(other.0.as_bytes())
303    }
304}
305
306impl From<NamespaceSecret> for NamespacePublicKey {
307    fn from(value: NamespaceSecret) -> Self {
308        value.public_key()
309    }
310}
311
312impl From<Author> for AuthorPublicKey {
313    fn from(value: Author) -> Self {
314        value.public_key()
315    }
316}
317
318impl From<&NamespaceSecret> for NamespacePublicKey {
319    fn from(value: &NamespaceSecret) -> Self {
320        value.public_key()
321    }
322}
323
324impl From<&Author> for AuthorPublicKey {
325    fn from(value: &Author) -> Self {
326        value.public_key()
327    }
328}
329
330/// [`NamespacePublicKey`] in bytes
331#[derive(
332    Default,
333    Clone,
334    Copy,
335    PartialOrd,
336    Ord,
337    Eq,
338    PartialEq,
339    Hash,
340    derive_more::From,
341    derive_more::Into,
342    derive_more::AsRef,
343    Serialize,
344    Deserialize,
345)]
346pub struct NamespaceId([u8; 32]);
347
348/// [`AuthorPublicKey`] in bytes
349#[derive(
350    Default,
351    Clone,
352    Copy,
353    PartialOrd,
354    Ord,
355    Eq,
356    PartialEq,
357    Hash,
358    derive_more::From,
359    derive_more::Into,
360    derive_more::AsRef,
361    Serialize,
362    Deserialize,
363)]
364pub struct AuthorId([u8; 32]);
365
366impl AuthorId {
367    /// Convert to byte array.
368    pub fn to_bytes(&self) -> [u8; 32] {
369        self.0
370    }
371
372    /// Convert to byte slice.
373    pub fn as_bytes(&self) -> &[u8; 32] {
374        &self.0
375    }
376
377    /// Convert into [`AuthorPublicKey`] by fetching from a [`PublicKeyStore`].
378    ///
379    /// Fails if the bytes of this [`AuthorId`] are not a valid [`ed25519_dalek`] curve point.
380    pub fn public_key<S: PublicKeyStore>(
381        &self,
382        store: &S,
383    ) -> Result<AuthorPublicKey, SignatureError> {
384        store.author_key(self)
385    }
386
387    /// Convert into [`AuthorPublicKey`].
388    ///
389    /// Fails if the bytes of this [`AuthorId`] are not a valid [`ed25519_dalek`] curve point.
390    pub fn into_public_key(&self) -> Result<AuthorPublicKey, SignatureError> {
391        AuthorPublicKey::from_bytes(&self.0)
392    }
393
394    /// Convert to a hex string limited to the first 10 bytes for a friendly string
395    /// representation of the key.
396    pub fn fmt_short(&self) -> String {
397        hex::encode(self.0).chars().take(10).collect()
398    }
399}
400
401impl NamespaceId {
402    /// Convert to byte array.
403    pub fn to_bytes(&self) -> [u8; 32] {
404        self.0
405    }
406
407    /// Convert to byte slice.
408    pub fn as_bytes(&self) -> &[u8; 32] {
409        &self.0
410    }
411
412    /// Convert into [`NamespacePublicKey`] by fetching from a [`PublicKeyStore`].
413    ///
414    /// Fails if the bytes of this [`NamespaceId`] are not a valid [`ed25519_dalek`] curve point.
415    pub fn public_key<S: PublicKeyStore>(
416        &self,
417        store: &S,
418    ) -> Result<NamespacePublicKey, SignatureError> {
419        store.namespace_key(self)
420    }
421
422    /// Convert into [`NamespacePublicKey`].
423    ///
424    /// Fails if the bytes of this [`NamespaceId`] are not a valid [`ed25519_dalek`] curve point.
425    pub fn into_public_key(&self) -> Result<NamespacePublicKey, SignatureError> {
426        NamespacePublicKey::from_bytes(&self.0)
427    }
428
429    /// Convert to a hex string limited to the first 10 bytes for a friendly string
430    /// representation of the key.
431    pub fn fmt_short(&self) -> String {
432        hex::encode(self.0).chars().take(10).collect()
433    }
434}
435
436impl From<&[u8; 32]> for NamespaceId {
437    fn from(value: &[u8; 32]) -> Self {
438        Self(*value)
439    }
440}
441
442impl From<&[u8; 32]> for AuthorId {
443    fn from(value: &[u8; 32]) -> Self {
444        Self(*value)
445    }
446}
447
448impl AsRef<[u8]> for NamespaceId {
449    fn as_ref(&self) -> &[u8] {
450        &self.0
451    }
452}
453
454impl AsRef<[u8]> for AuthorId {
455    fn as_ref(&self) -> &[u8] {
456        &self.0
457    }
458}
459
460impl From<AuthorPublicKey> for AuthorId {
461    fn from(value: AuthorPublicKey) -> Self {
462        Self(*value.as_bytes())
463    }
464}
465impl From<NamespacePublicKey> for NamespaceId {
466    fn from(value: NamespacePublicKey) -> Self {
467        Self(*value.as_bytes())
468    }
469}
470
471impl From<&AuthorPublicKey> for AuthorId {
472    fn from(value: &AuthorPublicKey) -> Self {
473        Self(*value.as_bytes())
474    }
475}
476impl From<&NamespacePublicKey> for NamespaceId {
477    fn from(value: &NamespacePublicKey) -> Self {
478        Self(*value.as_bytes())
479    }
480}
481
482impl From<Author> for AuthorId {
483    fn from(value: Author) -> Self {
484        value.id()
485    }
486}
487impl From<NamespaceSecret> for NamespaceId {
488    fn from(value: NamespaceSecret) -> Self {
489        value.id()
490    }
491}
492
493impl TryFrom<NamespaceId> for NamespacePublicKey {
494    type Error = SignatureError;
495    fn try_from(value: NamespaceId) -> Result<Self, Self::Error> {
496        Self::from_bytes(&value.0)
497    }
498}
499
500impl TryFrom<AuthorId> for AuthorPublicKey {
501    type Error = SignatureError;
502    fn try_from(value: AuthorId) -> Result<Self, Self::Error> {
503        Self::from_bytes(&value.0)
504    }
505}
506
507impl FromStr for AuthorId {
508    type Err = anyhow::Error;
509
510    fn from_str(s: &str) -> Result<Self, Self::Err> {
511        AuthorPublicKey::from_str(s).map(|x| x.into())
512    }
513}
514
515impl FromStr for NamespaceId {
516    type Err = anyhow::Error;
517
518    fn from_str(s: &str) -> Result<Self, Self::Err> {
519        NamespacePublicKey::from_str(s).map(|x| x.into())
520    }
521}