Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean: Modified JWK to reflect spec #60 #70

Merged
merged 3 commits into from
Nov 9, 2023
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
66 changes: 40 additions & 26 deletions did-endpoint/src/didgen.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::util::{didweb, KeyStore};
use did_utils::{
didcore::{
AssertionMethod, Authentication, Document, Jwk, KeyAgreement, KeyFormat, Service,
AssertionMethod, Authentication, Document, KeyAgreement, KeyFormat, Service,
VerificationMethod,
},
ldmodel::Context,
key_jwk::jwk::Jwk,
};
use std::path::Path;

Expand Down Expand Up @@ -203,6 +204,10 @@ mod tests {
use super::*;
use crate::util::dotenv_flow_read;

use did_utils::key_jwk::{
bytes::Bytes, jwk::Jwk, key::Key, okp::Okp, okp::OkpCurves, prm::Parameters,
};

fn setup() -> (String, String) {
let storage_dirpath = dotenv_flow_read("STORAGE_DIRPATH")
.map(|p| format!("{}/{}", p, uuid::Uuid::new_v4()))
Expand Down Expand Up @@ -235,38 +240,47 @@ mod tests {
let (storage_dirpath, server_public_domain) = setup();

let authentication_key = Jwk {
key_id: None,
key_type: String::from("OKP"),
curve: String::from("Ed25519"),
x: Some(String::from(
"d75a980182b10ab2463c5b1be1b4d97e06ec21ebac8552059996bd962d77f259",
)),
y: None,
d: None,
key: Key::Okp(Okp {
crv: OkpCurves::Ed25519,
x: Bytes::from(
String::from(
"d75a980182b10ab2463c5b1be1b4d97e06ec21ebac8552059996bd962d77f259",
)
.into_bytes(),
),
d: None,
}),
prm: Parameters::default(),
};

let assertion_key = Jwk {
key_id: None,
key_type: String::from("OKP"),
curve: String::from("Ed25519"),
x: Some(String::from(
"d75a980182b10ab2463c5b1be1b4d97e06ec21ebac8552059996bd962d77f259",
)),
y: None,
d: None,
key: Key::Okp(Okp {
crv: OkpCurves::Ed25519,
x: Bytes::from(
String::from(
"d75a980182b10ab2463c5b1be1b4d97e06ec21ebac8552059996bd962d77f259",
)
.into_bytes(),
),
d: None,
}),
prm: Parameters::default(),
};

let agreement_key = Jwk {
key_id: None,
key_type: String::from("OKP"),
curve: String::from("X25519"),
x: Some(String::from(
"d75a980182b10ab2463c5b1be1b4d97e06ec21ebac8552059996bd962d77f259",
)),
y: None,
d: None,
key: Key::Okp(Okp {
crv: OkpCurves::X25519,
x: Bytes::from(
String::from(
"d75a980182b10ab2463c5b1be1b4d97e06ec21ebac8552059996bd962d77f259",
)
.into_bytes(),
),
d: None,
}),
prm: Parameters::default(),
};

let diddoc = gen_diddoc(
&storage_dirpath,
&server_public_domain,
Expand Down
50 changes: 33 additions & 17 deletions did-endpoint/src/util/keystore.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use chrono::Utc;
use did_utils::{
crypto::{ed25519::Ed25519KeyPair, traits::Generate, x25519::X25519KeyPair},
didcore::Jwk,
key_jwk::{ec::Ec, jwk::Jwk, key::Key, oct::Oct, okp::Okp, rsa::Rsa, secret::Secret},
};
use std::error::Error;
use zeroize::Zeroize;

pub struct KeyStore {
dirpath: String,
Expand Down Expand Up @@ -107,26 +106,43 @@ impl KeyStore {
}
}

impl Drop for KeyStore {
fn drop(&mut self) {
for jwk in &mut self.keys {
jwk.d.zeroize();
};
}
}

trait ToPublic {
fn to_public(&self) -> Self;
}

impl ToPublic for Jwk {
fn to_public(&self) -> Self {
Jwk {
d: None,
..self.clone()
}
}
}
fn to_public(&self) -> Self {
let public_key = match &self.key {
Key::Ec(ec) => Key::Ec(Ec {
crv: ec.crv.clone(),
x: ec.x.clone(),
y: ec.y.clone(),
d: None,
}),
Key::Rsa(rsa) => Key::Rsa(Rsa {
prv: None,
e: rsa.e.clone(),
n: rsa.n.clone(),
}),
Key::Oct(_oct) => Key::Oct(Oct {
k: Secret::default(),
}),
Key::Okp(okp) => Key::Okp(Okp {
d: None,
crv: okp.crv.clone(),
x: okp.x.clone(),
}),
_ => {
return self.clone();
}
};

Jwk {
key: public_key,
prm: self.prm.clone(),
}
}
}

#[cfg(test)]
mod tests {
Expand Down
3 changes: 2 additions & 1 deletion did-endpoint/src/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ mod tests {
http::{Request, StatusCode},
};
use did_utils::{
didcore::{Document, Jwk, KeyFormat, Proofs},
didcore::{Document, KeyFormat, Proofs},
key_jwk::jwk::Jwk,
proof::{eddsa_jcs_2022::EdDsaJcs2022, traits::CryptoProof},
vc::model::VerifiablePresentation,
};
Expand Down
16 changes: 14 additions & 2 deletions did-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ tokio = { version = "1.20.4" }
# cross-platform random number generator from os
getrandom = { version = "0.2", features = ["js"] }
ed25519-dalek = "2.0.0-rc.3"
x25519-dalek = {version="2.0.0-rc.3", features= ["static_secrets", "getrandom"]}
x25519-dalek = { version = "2.0.0-rc.3", features = [
"static_secrets",
"getrandom",
] }
curve25519-dalek = "4.0.0-rc.3"
sha2 = "0.10"

Expand All @@ -29,10 +32,19 @@ thiserror = "1.0.48"
url = "2.4.1"
num-bigint = "0.4.4"
hex = "0.4.3"
base64ct = { version = "1.6.0", default-features = false, features = ["alloc"] }
zeroize = { version = "1.6.0", default-features = false, features = [
"alloc",
"serde",
] }
subtle = "2.5.0"

[dev-dependencies]
hyper = { version = "0.14.26", features = ["server"] }
async-std = { version = "1.12.0", features = ["attributes"] }
hex = "0.4.3"
tokio = { version = "1.27.0", default-features = false, features = ["macros", "rt"] }
tokio = { version = "1.27.0", default-features = false, features = [
"macros",
"rt",
] }
tokio-test = "0.4.2"
2 changes: 1 addition & 1 deletion did-utils/examples/dsa-verify-with-jwk.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use did_utils::{
crypto::{ed25519::Ed25519KeyPair, traits::CoreSign},
didcore::Jwk,
key_jwk::jwk::Jwk
};
use multibase::Base::Base64Url;

Expand Down
107 changes: 60 additions & 47 deletions did-utils/src/crypto/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@ use crate::{
traits::{Error as CryptoError, Generate, KeyMaterial, BYTES_LENGTH_32},
x25519::X25519KeyPair,
},
didcore::Jwk,
key_jwk::jwk::Jwk,
key_jwk::prm::Parameters,
};

use crate::key_jwk::{key::Key, okp::Okp, okp::OkpCurves, secret::Secret, Bytes};
use multibase::Base::Base64Url;

impl TryFrom<Ed25519KeyPair> for Jwk {
type Error = CryptoError;

fn try_from(keypair: Ed25519KeyPair) -> Result<Self, Self::Error> {
Ok(Jwk {
key_id: None,
key_type: String::from("OKP"),
curve: String::from("Ed25519"),
x: Some(Base64Url.encode(keypair.public_key_bytes()?)),
y: None,
d: Some(Base64Url.encode(keypair.private_key_bytes()?)),
key: Key::Okp(Okp {
crv: OkpCurves::Ed25519,
x: Bytes::from(keypair.public_key_bytes()?.to_vec()),
d: Some(Secret::from(keypair.private_key_bytes()?.to_vec())),
}),
prm: Parameters::default(),
})
}
}
Expand All @@ -27,24 +30,29 @@ impl TryFrom<Jwk> for Ed25519KeyPair {
type Error = CryptoError;

fn try_from(jwk: Jwk) -> Result<Self, Self::Error> {
if jwk.key_type != "OKP" {
return Err(CryptoError::Unsupported);
}

if jwk.curve != "Ed25519" {
return Err(CryptoError::InvalidCurve);
}

match jwk.d {
Some(secret_key) => {
let secret_key = base64url_to_bytes(&secret_key).map_err(|_| CryptoError::InvalidSecretKey)?;
Ed25519KeyPair::from_secret_key(&secret_key)
}
None => {
let public_key = jwk.x.ok_or(CryptoError::InvalidPublicKey)?;
let public_key = base64url_to_bytes(&public_key).map_err(|_| CryptoError::InvalidPublicKey)?;
Ed25519KeyPair::from_public_key(&public_key)
match jwk.key {
Key::Okp(okp) => {
if okp.crv != OkpCurves::Ed25519 {
return Err(CryptoError::InvalidCurve);
}

match okp.d {
Some(secret_key) => {
let secret = secret_key;

let secret_key_vec = secret.to_vec();

let bytes: [u8; 32] = secret_key_vec.try_into().unwrap();
Ed25519KeyPair::from_secret_key(&bytes)
}
None => {
let public_key = okp.x;
let public_key_vec = public_key.to_vec();
Ed25519KeyPair::from_public_key(&public_key_vec.try_into().unwrap())
}
}
}
_ => Err(CryptoError::Unsupported),
}
}
}
Expand All @@ -54,12 +62,12 @@ impl TryFrom<X25519KeyPair> for Jwk {

fn try_from(keypair: X25519KeyPair) -> Result<Self, Self::Error> {
Ok(Jwk {
key_id: None,
key_type: String::from("OKP"),
curve: String::from("X25519"),
x: Some(Base64Url.encode(keypair.public_key_bytes()?)),
y: None,
d: Some(Base64Url.encode(keypair.private_key_bytes()?)),
key: Key::Okp(Okp {
crv: OkpCurves::X25519,
x: Bytes::from(keypair.public_key_bytes()?.to_vec()),
d: Some(Secret::from(keypair.private_key_bytes()?.to_vec())),
}),
prm: Parameters::default(),
})
}
}
Expand All @@ -68,28 +76,33 @@ impl TryFrom<Jwk> for X25519KeyPair {
type Error = CryptoError;

fn try_from(jwk: Jwk) -> Result<Self, Self::Error> {
if jwk.key_type != "OKP" {
return Err(CryptoError::Unsupported);
}

if jwk.curve != "X25519" {
return Err(CryptoError::InvalidCurve);
}

match jwk.d {
Some(secret_key) => {
let secret_key = base64url_to_bytes(&secret_key).map_err(|_| CryptoError::InvalidSecretKey)?;
X25519KeyPair::from_secret_key(&secret_key)
}
None => {
let public_key = jwk.x.ok_or(CryptoError::InvalidPublicKey)?;
let public_key = base64url_to_bytes(&public_key).map_err(|_| CryptoError::InvalidPublicKey)?;
X25519KeyPair::from_public_key(&public_key)
match jwk.key {
Key::Okp(okp) => {
if okp.crv != OkpCurves::X25519 {
return Err(CryptoError::InvalidCurve);
}
match okp.d {
Some(secret_key) => {
let secret = secret_key;

let secret_key_vec = secret.to_vec();

let bytes: [u8; 32] = secret_key_vec.try_into().unwrap();
X25519KeyPair::from_secret_key(&bytes)
}
None => {
let public_key = okp.x;
let public_key_vec = public_key.to_vec();
X25519KeyPair::from_public_key(&public_key_vec.try_into().unwrap())
}
}
}
_ => Err(CryptoError::Unsupported),
}
}
}

#[allow(dead_code)]
fn base64url_to_bytes(key: &str) -> Result<[u8; BYTES_LENGTH_32], ()> {
let key: Vec<u8> = Base64Url.decode(key).map_err(|_| ())?;
let key: [u8; BYTES_LENGTH_32] = key.try_into().map_err(|_| ())?;
Expand Down
Loading
Loading