Skip to main content

iroh_docs/
keys.rs

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