Skip to content

Commit

Permalink
Added pub_key getters
Browse files Browse the repository at this point in the history
  • Loading branch information
TheButlah committed May 19, 2024
1 parent 0c19d66 commit 3fd716e
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 15 deletions.
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ version = "0.0.0"
license = "MIT OR BSD-2-Clause-Patent OR Apache-2.0"
repository = "https://github.com/NexusSocial/nexus-vr"
edition = "2021"
rust-version = "1.76"
rust-version = "1.78.0"

[workspace.dependencies]
base64 = "0.21.7"
Expand Down
1 change: 1 addition & 0 deletions crates/did-simple/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ publish = false
thiserror = "1.0.60"
bytes = "1.6.0"
bs58 = "0.5.1"
ref-cast = "1.0.23"

[dev-dependencies]
eyre = "0.6.12"
Expand Down
61 changes: 56 additions & 5 deletions crates/did-simple/src/key_algos.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use ref_cast::RefCast;

use crate::varint::encode_varint;

/// A key algorithm.
pub trait KeyAlgo {
type PubKey: AsRef<[u8]>;
fn pub_key_size(&self) -> usize;
fn multicodec_value(&self) -> u16;
}
Expand All @@ -12,9 +15,12 @@ pub trait StaticKeyAlgo: KeyAlgo {
const MULTICODEC_VALUE: u16;
const MULTICODEC_VALUE_ENCODED: &'static [u8] =
encode_varint(Self::MULTICODEC_VALUE).as_slice();
type PubKeyArray: AsRef<[u8]>;
}

impl<T: StaticKeyAlgo> KeyAlgo for T {
type PubKey = T::PubKeyArray;

fn pub_key_size(&self) -> usize {
Self::PUB_KEY_SIZE
}
Expand All @@ -24,17 +30,17 @@ impl<T: StaticKeyAlgo> KeyAlgo for T {
}
}

#[derive(RefCast)]
#[repr(transparent)]
pub struct PubKey<T: StaticKeyAlgo>(pub T::PubKeyArray);

#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
pub struct Ed25519;

impl StaticKeyAlgo for Ed25519 {
const PUB_KEY_SIZE: usize = 32;
const MULTICODEC_VALUE: u16 = 0xED;
}

#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
pub enum DynKeyAlgo {
Ed25519,
type PubKeyArray = [u8; Self::PUB_KEY_SIZE];
}

impl PartialEq<Ed25519> for DynKeyAlgo {
Expand All @@ -43,7 +49,14 @@ impl PartialEq<Ed25519> for DynKeyAlgo {
}
}

#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
pub enum DynKeyAlgo {
Ed25519,
}

impl KeyAlgo for DynKeyAlgo {
type PubKey = DynPubKey;

fn pub_key_size(&self) -> usize {
match self {
Self::Ed25519 => Ed25519::PUB_KEY_SIZE,
Expand All @@ -56,3 +69,41 @@ impl KeyAlgo for DynKeyAlgo {
}
}
}

#[non_exhaustive]
pub enum DynPubKey {
Ed25519(PubKey<Ed25519>),
}

impl From<PubKey<Ed25519>> for DynPubKey {
fn from(value: PubKey<Ed25519>) -> Self {
Self::Ed25519(value)
}
}

impl AsRef<[u8]> for DynPubKey {
fn as_ref(&self) -> &[u8] {
match self {
Self::Ed25519(k) => k.0.as_ref(),
}
}
}

#[non_exhaustive]
pub enum DynPubKeyRef<'a> {
Ed25519(&'a PubKey<Ed25519>),
}

impl<'a> From<&'a PubKey<Ed25519>> for DynPubKeyRef<'a> {
fn from(value: &'a PubKey<Ed25519>) -> Self {
Self::Ed25519(value)
}
}

impl AsRef<[u8]> for DynPubKeyRef<'_> {
fn as_ref(&self) -> &[u8] {
match *self {
Self::Ed25519(k) => k.0.as_ref(),
}
}
}
31 changes: 23 additions & 8 deletions crates/did-simple/src/methods/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
//!
//! [did:key]: https://w3c-ccg.github.io/did-method-key/
use ref_cast::RefCast;
use std::fmt::Display;

use crate::{
key_algos::{DynKeyAlgo, Ed25519, KeyAlgo, StaticKeyAlgo},
key_algos::{DynKeyAlgo, DynPubKeyRef, Ed25519, KeyAlgo, PubKey, StaticKeyAlgo},
uri::{DidMethod, DidUri},
utf8bytes::Utf8Bytes,
varint::decode_varint,
Expand All @@ -14,19 +15,19 @@ use crate::{
/// An implementation of the `did:key` method. See the [module](self) docs for more
/// info.
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub struct DidKey<A = DynKeyAlgo> {
pub struct DidKey {
/// The string representation of the DID.
s: Utf8Bytes,
/// The decoded multibase portion of the DID.
mb_value: Vec<u8>,
key_algo: A,
key_algo: DynKeyAlgo,
/// The index into [`Self::mb_value`] that is the public key.
pubkey_bytes: std::ops::RangeFrom<usize>,
}

pub const PREFIX: &str = "did:key:";

impl<A> DidKey<A> {
impl DidKey {
pub const PREFIX: &'static str = PREFIX;

/// Gets the buffer representing the did:key uri as a str.
Expand All @@ -44,11 +45,25 @@ impl<A> DidKey<A> {
pub fn as_utf8_bytes(&self) -> &Utf8Bytes {
&self.s
}
}

impl<A: Clone> DidKey<A> {
pub fn key_algo(&self) -> A {
self.key_algo.clone()
pub fn key_algo(&self) -> DynKeyAlgo {
self.key_algo
}

/// Gets the decoded bytes of the public key.
pub fn pub_key(&self) -> DynPubKeyRef<'_> {
match self.key_algo {
DynKeyAlgo::Ed25519 => {
// with a cast.
let bytes: &[u8] = &self.mb_value[self.pubkey_bytes.clone()];
debug_assert_eq!(bytes.len(), Ed25519::PUB_KEY_SIZE);
// TODO: Convert to an unsafe cast behind a feature flag later.
// This is because the slice is guaranteed by our parsing logic
// to match the key algo size.
let bytes: &[u8; Ed25519::PUB_KEY_SIZE] = bytes.try_into().unwrap();
PubKey::<Ed25519>::ref_cast(bytes).into()
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[toolchain]
channel = "1.76" # See workspace Cargo.toml
channel = "1.78.0" # See workspace Cargo.toml
components = ["rust-src"]
profile = "default"
targets = ["x86_64-pc-windows-msvc", "aarch64-linux-android", "x86_64-unknown-linux-gnu"]

0 comments on commit 3fd716e

Please sign in to comment.