Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 48 additions & 45 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,31 @@

use std::{cmp::Ordering, fmt, str::FromStr};

use ed25519_dalek::{Signature, SignatureError, Signer, SigningKey, VerifyingKey};
use iroh::{KeyParsingError, PublicKey, SecretKey, Signature, SignatureError};
use rand::CryptoRng;
use serde::{Deserialize, Serialize};

use crate::store::PublicKeyStore;

/// Author key to insert entries in a [`crate::Replica`]
///
/// Internally, an author is a [`SigningKey`] which is used to sign entries.
/// Internally, an author wraps an [`iroh::SecretKey`] used to sign entries.
#[derive(Clone, Serialize, Deserialize)]
pub struct Author {
signing_key: SigningKey,
signing_key: SecretKey,
}
impl Author {
/// Create a new [`Author`] with a random key.
pub fn new<R: CryptoRng>(rng: &mut R) -> Self {
let signing_key = SigningKey::generate(rng);
let mut bytes = [0u8; 32];
rng.fill_bytes(&mut bytes);
let signing_key = SecretKey::from_bytes(&bytes);
Author { signing_key }
}

/// Create an [`Author`] from a byte array.
pub fn from_bytes(bytes: &[u8; 32]) -> Self {
SigningKey::from_bytes(bytes).into()
SecretKey::from_bytes(bytes).into()
}

/// Returns the [`Author`] byte representation.
Expand All @@ -34,7 +36,7 @@ impl Author {

/// Get the [`AuthorPublicKey`] for this author.
pub fn public_key(&self) -> AuthorPublicKey {
AuthorPublicKey(self.signing_key.verifying_key())
AuthorPublicKey(self.signing_key.public())
}

/// Get the [`AuthorId`] for this author.
Expand All @@ -49,22 +51,22 @@ impl Author {

/// Strictly verify a signature on a message with this [`Author`]'s public key.
pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
self.signing_key.verify_strict(msg, signature)
self.signing_key.public().verify(msg, signature)
}
}

/// Identifier for an [`Author`]
///
/// This is the corresponding [`VerifyingKey`] for an author. It is used as an identifier, and can
/// be used to verify [`Signature`]s.
#[derive(Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, derive_more::From)]
pub struct AuthorPublicKey(VerifyingKey);
/// This is the corresponding [`iroh::PublicKey`] for an author. It is used as an identifier,
/// and can be used to verify [`Signature`]s.
#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, derive_more::From)]
pub struct AuthorPublicKey(PublicKey);

impl AuthorPublicKey {
/// Verify that a signature matches the `msg` bytes and was created with the [`Author`]
/// that corresponds to this [`AuthorId`].
pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
self.0.verify_strict(msg, signature)
self.0.verify(msg, signature)
}

/// Get the byte representation of this [`AuthorId`].
Expand All @@ -74,34 +76,35 @@ impl AuthorPublicKey {

/// Create from a slice of bytes.
///
/// Will return an error if the input bytes do not represent a valid [`ed25519_dalek`]
/// Will return an error if the input bytes do not represent a valid ed25519
/// curve point. Will never fail for a byte array returned from [`Self::as_bytes`].
/// See [`VerifyingKey::from_bytes`] for details.
pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
Ok(AuthorPublicKey(VerifyingKey::from_bytes(bytes)?))
/// See [`iroh::PublicKey::from_bytes`] for details.
pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, KeyParsingError> {
Ok(AuthorPublicKey(PublicKey::from_bytes(bytes)?))
}
}

/// Namespace key of a [`crate::Replica`].
///
/// Holders of this key can insert new entries into a [`crate::Replica`].
/// Internally, a [`NamespaceSecret`] is a [`SigningKey`] which is used to sign entries.
/// Internally, a [`NamespaceSecret`] wraps an [`iroh::SecretKey`] used to sign entries.
#[derive(Clone, Serialize, Deserialize)]
pub struct NamespaceSecret {
signing_key: SigningKey,
signing_key: SecretKey,
}

impl NamespaceSecret {
/// Create a new [`NamespaceSecret`] with a random key.
pub fn new<R: CryptoRng>(rng: &mut R) -> Self {
let signing_key = SigningKey::generate(rng);

let mut bytes = [0u8; 32];
rng.fill_bytes(&mut bytes);
let signing_key = SecretKey::from_bytes(&bytes);
NamespaceSecret { signing_key }
}

/// Create a [`NamespaceSecret`] from a byte array.
pub fn from_bytes(bytes: &[u8; 32]) -> Self {
SigningKey::from_bytes(bytes).into()
SecretKey::from_bytes(bytes).into()
}

/// Returns the [`NamespaceSecret`] byte representation.
Expand All @@ -111,7 +114,7 @@ impl NamespaceSecret {

/// Get the [`NamespacePublicKey`] for this namespace.
pub fn public_key(&self) -> NamespacePublicKey {
NamespacePublicKey(self.signing_key.verifying_key())
NamespacePublicKey(self.signing_key.public())
}

/// Get the [`NamespaceId`] for this namespace.
Expand All @@ -126,20 +129,20 @@ impl NamespaceSecret {

/// Strictly verify a signature on a message with this [`NamespaceSecret`]'s public key.
pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
self.signing_key.verify_strict(msg, signature)
self.signing_key.public().verify(msg, signature)
}
}

/// The corresponding [`VerifyingKey`] for a [`NamespaceSecret`].
/// The corresponding [`iroh::PublicKey`] for a [`NamespaceSecret`].
/// It is used as an identifier, and can be used to verify [`Signature`]s.
#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, derive_more::From)]
pub struct NamespacePublicKey(VerifyingKey);
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, derive_more::From)]
pub struct NamespacePublicKey(PublicKey);

impl NamespacePublicKey {
/// Verify that a signature matches the `msg` bytes and was created with the [`NamespaceSecret`]
/// that corresponds to this [`NamespaceId`].
pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
self.0.verify_strict(msg, signature)
self.0.verify(msg, signature)
}

/// Get the byte representation of this [`NamespaceId`].
Expand All @@ -149,11 +152,11 @@ impl NamespacePublicKey {

/// Create from a slice of bytes.
///
/// Will return an error if the input bytes do not represent a valid [`ed25519_dalek`]
/// Will return an error if the input bytes do not represent a valid ed25519
/// curve point. Will never fail for a byte array returned from [`Self::as_bytes`].
/// See [`VerifyingKey::from_bytes`] for details.
pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
Ok(NamespacePublicKey(VerifyingKey::from_bytes(bytes)?))
/// See [`iroh::PublicKey::from_bytes`] for details.
pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, KeyParsingError> {
Ok(NamespacePublicKey(PublicKey::from_bytes(bytes)?))
}
}

Expand Down Expand Up @@ -267,14 +270,14 @@ impl FromStr for NamespacePublicKey {
}
}

impl From<SigningKey> for Author {
fn from(signing_key: SigningKey) -> Self {
impl From<SecretKey> for Author {
fn from(signing_key: SecretKey) -> Self {
Self { signing_key }
}
}

impl From<SigningKey> for NamespaceSecret {
fn from(signing_key: SigningKey) -> Self {
impl From<SecretKey> for NamespaceSecret {
fn from(signing_key: SecretKey) -> Self {
Self { signing_key }
}
}
Expand Down Expand Up @@ -376,18 +379,18 @@ impl AuthorId {

/// Convert into [`AuthorPublicKey`] by fetching from a [`PublicKeyStore`].
///
/// Fails if the bytes of this [`AuthorId`] are not a valid [`ed25519_dalek`] curve point.
/// Fails if the bytes of this [`AuthorId`] are not a valid ed25519 curve point.
pub fn public_key<S: PublicKeyStore>(
&self,
store: &S,
) -> Result<AuthorPublicKey, SignatureError> {
) -> Result<AuthorPublicKey, KeyParsingError> {
store.author_key(self)
}

/// Convert into [`AuthorPublicKey`].
///
/// Fails if the bytes of this [`AuthorId`] are not a valid [`ed25519_dalek`] curve point.
pub fn into_public_key(&self) -> Result<AuthorPublicKey, SignatureError> {
/// Fails if the bytes of this [`AuthorId`] are not a valid ed25519 curve point.
pub fn into_public_key(&self) -> Result<AuthorPublicKey, KeyParsingError> {
AuthorPublicKey::from_bytes(&self.0)
}

Expand All @@ -411,18 +414,18 @@ impl NamespaceId {

/// Convert into [`NamespacePublicKey`] by fetching from a [`PublicKeyStore`].
///
/// Fails if the bytes of this [`NamespaceId`] are not a valid [`ed25519_dalek`] curve point.
/// Fails if the bytes of this [`NamespaceId`] are not a valid ed25519 curve point.
pub fn public_key<S: PublicKeyStore>(
&self,
store: &S,
) -> Result<NamespacePublicKey, SignatureError> {
) -> Result<NamespacePublicKey, KeyParsingError> {
store.namespace_key(self)
}

/// Convert into [`NamespacePublicKey`].
///
/// Fails if the bytes of this [`NamespaceId`] are not a valid [`ed25519_dalek`] curve point.
pub fn into_public_key(&self) -> Result<NamespacePublicKey, SignatureError> {
/// Fails if the bytes of this [`NamespaceId`] are not a valid ed25519 curve point.
pub fn into_public_key(&self) -> Result<NamespacePublicKey, KeyParsingError> {
NamespacePublicKey::from_bytes(&self.0)
}

Expand Down Expand Up @@ -491,14 +494,14 @@ impl From<NamespaceSecret> for NamespaceId {
}

impl TryFrom<NamespaceId> for NamespacePublicKey {
type Error = SignatureError;
type Error = KeyParsingError;
fn try_from(value: NamespaceId) -> Result<Self, Self::Error> {
Self::from_bytes(&value.0)
}
}

impl TryFrom<AuthorId> for AuthorPublicKey {
type Error = SignatureError;
type Error = KeyParsingError;
fn try_from(value: AuthorId) -> Result<Self, Self::Error> {
Self::from_bytes(&value.0)
}
Expand Down
6 changes: 3 additions & 3 deletions src/store/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{
};

use anyhow::{anyhow, Result};
use ed25519_dalek::{SignatureError, VerifyingKey};
use iroh::{KeyParsingError, PublicKey};
use iroh_blobs::Hash;
use n0_future::time::SystemTime;
use rand::CryptoRng;
Expand Down Expand Up @@ -611,7 +611,7 @@ impl Store {
}

impl PublicKeyStore for Store {
fn public_key(&self, id: &[u8; 32]) -> Result<VerifyingKey, SignatureError> {
fn public_key(&self, id: &[u8; 32]) -> Result<PublicKey, KeyParsingError> {
self.pubkeys.public_key(id)
}
}
Expand Down Expand Up @@ -648,7 +648,7 @@ impl<'a> StoreInstance<'a> {
}

impl PublicKeyStore for StoreInstance<'_> {
fn public_key(&self, id: &[u8; 32]) -> std::result::Result<VerifyingKey, SignatureError> {
fn public_key(&self, id: &[u8; 32]) -> std::result::Result<PublicKey, KeyParsingError> {
self.store.public_key(id)
}
}
Expand Down
32 changes: 16 additions & 16 deletions src/store/pubkeys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,67 @@ use std::{
sync::{Arc, RwLock},
};

use ed25519_dalek::{SignatureError, VerifyingKey};
use iroh::{KeyParsingError, PublicKey};

use crate::{AuthorId, AuthorPublicKey, NamespaceId, NamespacePublicKey};

/// Store trait for expanded public keys for authors and namespaces.
///
/// Used to cache [`ed25519_dalek::VerifyingKey`].
/// Used to cache [`iroh::PublicKey`].
///
/// This trait is implemented for the unit type `()`, where no caching is used.
pub trait PublicKeyStore {
/// Convert a byte array into a [`VerifyingKey`].
/// Convert a byte array into a [`iroh::PublicKey`].
///
/// New keys are inserted into the [`PublicKeyStore ] and reused on subsequent calls.
fn public_key(&self, id: &[u8; 32]) -> Result<VerifyingKey, SignatureError>;
/// New keys are inserted into the [`PublicKeyStore`] and reused on subsequent calls.
fn public_key(&self, id: &[u8; 32]) -> Result<PublicKey, KeyParsingError>;

/// Convert a [`NamespaceId`] into a [`NamespacePublicKey`].
///
/// New keys are inserted into the [`PublicKeyStore ] and reused on subsequent calls.
fn namespace_key(&self, bytes: &NamespaceId) -> Result<NamespacePublicKey, SignatureError> {
/// New keys are inserted into the [`PublicKeyStore`] and reused on subsequent calls.
fn namespace_key(&self, bytes: &NamespaceId) -> Result<NamespacePublicKey, KeyParsingError> {
self.public_key(bytes.as_bytes()).map(Into::into)
}

/// Convert a [`AuthorId`] into a [`AuthorPublicKey`].
///
/// New keys are inserted into the [`PublicKeyStore ] and reused on subsequent calls.
fn author_key(&self, bytes: &AuthorId) -> Result<AuthorPublicKey, SignatureError> {
/// New keys are inserted into the [`PublicKeyStore`] and reused on subsequent calls.
fn author_key(&self, bytes: &AuthorId) -> Result<AuthorPublicKey, KeyParsingError> {
self.public_key(bytes.as_bytes()).map(Into::into)
}
}

impl<T: PublicKeyStore> PublicKeyStore for &T {
fn public_key(&self, id: &[u8; 32]) -> Result<VerifyingKey, SignatureError> {
fn public_key(&self, id: &[u8; 32]) -> Result<PublicKey, KeyParsingError> {
(*self).public_key(id)
}
}

impl<T: PublicKeyStore> PublicKeyStore for &mut T {
fn public_key(&self, id: &[u8; 32]) -> Result<VerifyingKey, SignatureError> {
fn public_key(&self, id: &[u8; 32]) -> Result<PublicKey, KeyParsingError> {
PublicKeyStore::public_key(*self, id)
}
}

impl PublicKeyStore for () {
fn public_key(&self, id: &[u8; 32]) -> Result<VerifyingKey, SignatureError> {
VerifyingKey::from_bytes(id)
fn public_key(&self, id: &[u8; 32]) -> Result<PublicKey, KeyParsingError> {
PublicKey::from_bytes(id)
}
}

/// In-memory key storage
// TODO: Make max number of keys stored configurable.
#[derive(Debug, Clone, Default)]
pub struct MemPublicKeyStore {
keys: Arc<RwLock<HashMap<[u8; 32], VerifyingKey>>>,
keys: Arc<RwLock<HashMap<[u8; 32], PublicKey>>>,
}

impl PublicKeyStore for MemPublicKeyStore {
fn public_key(&self, bytes: &[u8; 32]) -> Result<VerifyingKey, SignatureError> {
fn public_key(&self, bytes: &[u8; 32]) -> Result<PublicKey, KeyParsingError> {
if let Some(id) = self.keys.read().unwrap().get(bytes) {
return Ok(*id);
}
let id = VerifyingKey::from_bytes(bytes)?;
let id = PublicKey::from_bytes(bytes)?;
self.keys.write().unwrap().insert(*bytes, id);
Ok(id)
}
Expand Down
Loading
Loading