node: Create crypto module

Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
Alexis Sellier 2022-08-30 21:09:30 +02:00
parent b78bbc4ecc
commit 66d580019b
No known key found for this signature in database
4 changed files with 76 additions and 66 deletions

65
node/src/crypto.rs Normal file
View File

@ -0,0 +1,65 @@
use std::{fmt, ops::Deref, str::FromStr};
use ed25519_consensus as ed25519;
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Serialize, Deserialize, Eq, Debug, Clone)]
#[serde(transparent)]
pub struct PublicKey(pub ed25519::VerificationKey);
#[derive(Error, Debug)]
pub enum PublicKeyError {
#[error("invalid length {0}")]
InvalidLength(usize),
#[error("invalid multibase string: {0}")]
Multibase(#[from] multibase::Error),
#[error("invalid key: {0}")]
InvalidKey(#[from] ed25519_consensus::Error),
}
impl std::hash::Hash for PublicKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.as_bytes().hash(state)
}
}
impl fmt::Display for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.encode())
}
}
impl PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl PublicKey {
pub fn encode(&self) -> String {
multibase::encode(multibase::Base::Base58Btc, &self.0)
}
}
impl FromStr for PublicKey {
type Err = PublicKeyError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (_, bytes) = multibase::decode(s)?;
let array: [u8; 32] = bytes
.try_into()
.map_err(|v: Vec<u8>| PublicKeyError::InvalidLength(v.len()))?;
let key = ed25519::VerificationKey::try_from(ed25519::VerificationKeyBytes::from(array))?;
Ok(Self(key))
}
}
impl Deref for PublicKey {
type Target = ed25519::VerificationKey;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View File

@ -1,13 +1,16 @@
use std::{ffi::OsString, fmt, io, ops::Deref, str::FromStr};
use std::{ffi::OsString, fmt, io, str::FromStr};
use ed25519_consensus::{VerificationKey, VerificationKeyBytes};
use nonempty::NonEmpty;
use radicle_git_ext::Oid;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::crypto;
use crate::hash;
/// A user's identifier is simply their public key.
pub type UserId = crypto::PublicKey;
#[derive(Error, Debug)]
pub enum ProjIdError {
#[error("invalid digest: {0}")]
@ -59,10 +62,10 @@ impl From<hash::Digest> for ProjId {
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug, Clone)]
pub struct Did(UserId);
pub struct Did(crypto::PublicKey);
impl Did {
fn encode(&self) -> String {
pub fn encode(&self) -> String {
format!("did:key:{}", self.0.encode())
}
}
@ -73,66 +76,6 @@ impl fmt::Display for Did {
}
}
#[derive(Serialize, Deserialize, Eq, Debug, Clone)]
#[serde(transparent)]
pub struct UserId(pub VerificationKey);
impl std::hash::Hash for UserId {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.as_bytes().hash(state)
}
}
impl fmt::Display for UserId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.encode())
}
}
impl PartialEq for UserId {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl UserId {
fn encode(&self) -> String {
multibase::encode(multibase::Base::Base58Btc, &self.0)
}
}
impl FromStr for UserId {
type Err = UserIdError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (_, bytes) = multibase::decode(s)?;
let array: [u8; 32] = bytes
.try_into()
.map_err(|v: Vec<u8>| UserIdError::InvalidLength(v.len()))?;
let key = VerificationKey::try_from(VerificationKeyBytes::from(array))?;
Ok(Self(key))
}
}
impl Deref for UserId {
type Target = VerificationKey;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Error, Debug)]
pub enum UserIdError {
#[error("invalid length {0}")]
InvalidLength(usize),
#[error("invalid multibase string: {0}")]
Multibase(#[from] multibase::Error),
#[error("invalid key: {0}")]
InvalidKey(#[from] ed25519_consensus::Error),
}
#[derive(Error, Debug)]
pub enum DocError {
#[error("toml: {0}")]

View File

@ -5,6 +5,7 @@ mod address_book;
mod address_manager;
mod clock;
mod collections;
mod crypto;
mod decoder;
mod git;
mod hash;

View File

@ -3,6 +3,7 @@ use std::hash::Hash;
use std::ops::RangeBounds;
use crate::collections::HashMap;
use crate::crypto::PublicKey;
use crate::hash;
use crate::identity::{ProjId, UserId};
use crate::storage;
@ -76,7 +77,7 @@ impl quickcheck::Arbitrary for hash::Digest {
}
}
impl quickcheck::Arbitrary for UserId {
impl quickcheck::Arbitrary for PublicKey {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
use ed25519_consensus::SigningKey;
@ -88,6 +89,6 @@ impl quickcheck::Arbitrary for UserId {
let sk = SigningKey::from(bytes);
let vk = sk.verification_key();
UserId(vk)
PublicKey(vk)
}
}