iroh_sync/
keys.rs

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