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 nonempty::NonEmpty;
|
||||||
use radicle_git_ext::Oid;
|
use radicle_git_ext::Oid;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::crypto;
|
||||||
use crate::hash;
|
use crate::hash;
|
||||||
|
|
||||||
|
/// A user's identifier is simply their public key.
|
||||||
|
pub type UserId = crypto::PublicKey;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ProjIdError {
|
pub enum ProjIdError {
|
||||||
#[error("invalid digest: {0}")]
|
#[error("invalid digest: {0}")]
|
||||||
|
|
@ -59,10 +62,10 @@ impl From<hash::Digest> for ProjId {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug, Clone)]
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug, Clone)]
|
||||||
pub struct Did(UserId);
|
pub struct Did(crypto::PublicKey);
|
||||||
|
|
||||||
impl Did {
|
impl Did {
|
||||||
fn encode(&self) -> String {
|
pub fn encode(&self) -> String {
|
||||||
format!("did:key:{}", self.0.encode())
|
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)]
|
#[derive(Error, Debug)]
|
||||||
pub enum DocError {
|
pub enum DocError {
|
||||||
#[error("toml: {0}")]
|
#[error("toml: {0}")]
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ mod address_book;
|
||||||
mod address_manager;
|
mod address_manager;
|
||||||
mod clock;
|
mod clock;
|
||||||
mod collections;
|
mod collections;
|
||||||
|
mod crypto;
|
||||||
mod decoder;
|
mod decoder;
|
||||||
mod git;
|
mod git;
|
||||||
mod hash;
|
mod hash;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::hash::Hash;
|
||||||
use std::ops::RangeBounds;
|
use std::ops::RangeBounds;
|
||||||
|
|
||||||
use crate::collections::HashMap;
|
use crate::collections::HashMap;
|
||||||
|
use crate::crypto::PublicKey;
|
||||||
use crate::hash;
|
use crate::hash;
|
||||||
use crate::identity::{ProjId, UserId};
|
use crate::identity::{ProjId, UserId};
|
||||||
use crate::storage;
|
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 {
|
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
||||||
use ed25519_consensus::SigningKey;
|
use ed25519_consensus::SigningKey;
|
||||||
|
|
||||||
|
|
@ -88,6 +89,6 @@ impl quickcheck::Arbitrary for UserId {
|
||||||
let sk = SigningKey::from(bytes);
|
let sk = SigningKey::from(bytes);
|
||||||
let vk = sk.verification_key();
|
let vk = sk.verification_key();
|
||||||
|
|
||||||
UserId(vk)
|
PublicKey(vk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue