node: Create crypto module
Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
parent
b78bbc4ecc
commit
66d580019b
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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}")]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ mod address_book;
|
|||
mod address_manager;
|
||||
mod clock;
|
||||
mod collections;
|
||||
mod crypto;
|
||||
mod decoder;
|
||||
mod git;
|
||||
mod hash;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue