Skip to content

Commit

Permalink
Ed25519Signature2020 test suite passing
Browse files Browse the repository at this point in the history
  • Loading branch information
sbihel committed Jul 2, 2024
1 parent 3319713 commit 9111a35
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 177 deletions.
11 changes: 6 additions & 5 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name: CD
name: cd

# Temporarily disabled until ssi is published
on:
push:
branches: [ main ]
release:
types: [published, created, edited]
# push:
# branches: [ main ]
# release:
# types: [published, created, edited]
workflow_dispatch:

jobs:
Expand Down
96 changes: 48 additions & 48 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,51 +45,51 @@ jobs:
- name: Clippy
run: cargo clippy

# vc_api_test_suites:
# runs-on: ubuntu-latest
# strategy:
# matrix:
# suite:
# # - "vc-api-issuer-test-suite" # not updated to latest test suites config
# # - "vc-api-verifier-test-suite" # not updated to latest test suites config
# # - "vc-di-ecdsa-test-suite" # ssi lost support for ecdsa and they updated the ids
# # - "vc-di-eddsa-test-suite" # ssi doesn't have support for eddsa-rdfc-2022 just yet
# # - "vc-di-ed25519signature2020-test-suite" # ssi needs support for editing VC context
# # - "did-key-test-suite" # not updated to latest test suites config
# # - "vc-data-model-2.0-test-suite" # ssi doesn't yet have full support for VCDM 2
# # - "vc-di-bbs-test-suite" # ssi doesn't yet have support for BBS
# steps:
# - uses: actions/checkout@v4
# with:
# path: didkit-http
# submodules: true
# - name: Checkout SSI library
# uses: actions/checkout@v4
# with:
# repository: spruceid/ssi
# path: ssi
# ref: ${{env.SSI_REF}}
# - name: Rust Cache
# uses: Swatinem/rust-cache@v2
# with:
# workspaces: |
# didkit-http
# shared-key: "vc-api"
# - uses: actions/setup-node@v4
# with:
# node-version: 18
# - name: Start VC API
# run: |
# cargo build
# DIDKIT_HTTP_ISSUER_KEYS='[{"kty":"OKP","crv":"Ed25519","x":"HvjBEw94RHAh9KkiD385aYZNxGkxIkwBcrLBY5Z7Koo","d":"1onWu34oC29Y09qCRl0aD2FOp5y5obTqHZxQQRT3-bs"}]' cargo run &
# - name: Start HTTPS Proxy
# run: npx local-ssl-proxy --source 9000 --target 3000 --hostname 127.0.0.1 &
# - name: Setup Test Suite
# run: |
# cd tests/${{ matrix.suite }}
# npm i
# ln ../localConfig.cjs localConfig.cjs
# - name: Run Test Suite
# run: |
# cd tests/${{ matrix.suite }}
# npm test
vc_api_test_suites:
runs-on: ubuntu-latest
strategy:
matrix:
suite:
# - "vc-api-issuer-test-suite" # not updated to latest test suites config
# - "vc-api-verifier-test-suite" # not updated to latest test suites config
# - "vc-di-ecdsa-test-suite" # ssi lost support for ecdsa and they updated the ids
# - "vc-di-eddsa-test-suite" # ssi doesn't have support for eddsa-rdfc-2022 just yet
- "vc-di-ed25519signature2020-test-suite"
# - "did-key-test-suite" # not updated to latest test suites config
# - "vc-data-model-2.0-test-suite" # ssi doesn't yet have full support for VCDM 2
# - "vc-di-bbs-test-suite" # ssi doesn't yet have support for BBS
steps:
- uses: actions/checkout@v4
with:
path: didkit-http
submodules: true
- name: Checkout SSI library
uses: actions/checkout@v4
with:
repository: spruceid/ssi
path: ssi
ref: ${{env.SSI_REF}}
- name: Rust Cache
uses: Swatinem/rust-cache@v2
with:
workspaces: |
didkit-http
shared-key: "vc-api"
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Start VC API
run: |
cargo build
DIDKIT_HTTP_ISSUER_KEYS='[{"kty":"OKP","crv":"Ed25519","x":"HvjBEw94RHAh9KkiD385aYZNxGkxIkwBcrLBY5Z7Koo","d":"1onWu34oC29Y09qCRl0aD2FOp5y5obTqHZxQQRT3-bs"}]' cargo run &
- name: Start HTTPS Proxy
run: npx local-ssl-proxy --source 9000 --target 3000 --hostname 127.0.0.1 &
- name: Setup Test Suite
run: |
cd tests/${{ matrix.suite }}
npm i
ln ../localConfig.cjs localConfig.cjs
- name: Run Test Suite
run: |
cd tests/${{ matrix.suite }}
npm test
93 changes: 39 additions & 54 deletions src/credentials.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
use std::borrow::{Borrow, BorrowMut, Cow};
use std::borrow::Cow;

use anyhow::Context;
use anyhow::{anyhow, Context};
use axum::{http::StatusCode, Extension, Json};
use serde::{Deserialize, Serialize};
use ssi::{
claims::{
data_integrity::{CryptographicSuite, DataIntegrity},
data_integrity::CryptographicSuite,
vc::{
v1::{Credential as _, ToJwtClaims},
v2::{self, Credential as _},
v2::Credential as _,
AnyJsonCredential, AnySpecializedJsonCredential,
},
JsonCredentialOrJws, VerifiableClaims, VerificationEnvironment,
},
dids::{AnyDidMethod, DIDResolver, VerificationMethodDIDResolver, DID},
json_ld::{self, json_ld::Iri},
json_ld::json_ld::Iri,
prelude::JWSPayload,
verification_methods::{
AnyMethod, GenericVerificationMethod, MaybeJwkVerificationMethod, ReferenceOrOwned,
Expand Down Expand Up @@ -56,52 +56,45 @@ pub async fn issue(
let resolver = VerificationMethodDIDResolver::<_, AnyMethod>::new(AnyDidMethod::default());

let issuer = match req.credential {
AnySpecializedJsonCredential::V1(ref vc) => &vc.issuer,
AnySpecializedJsonCredential::V2(ref vc) => &vc.issuer,
AnySpecializedJsonCredential::V1(ref vc) => vc.issuer.clone(),
AnySpecializedJsonCredential::V2(ref vc) => vc.issuer.clone(),
};

// Find an appropriate verification method.
let method = match &req.options.ldp_options.input_options.verification_method {
Some(method) => {
resolver
.resolve_verification_method(Some(issuer.id().as_iri()), Some(method.borrowed()))
.await?
}
Some(method) => resolver
.resolve_verification_method(Some(issuer.id().as_iri()), Some(method.borrowed()))
.await
.context("Could not resolve VM")?,
None => {
let did = DID::new(issuer.id()).map_err(|_| {
(
StatusCode::INTERNAL_SERVER_ERROR,
"Could not get any verification method for issuer URI".to_string(),
)
})?;
let did = DID::new(issuer.id())
.map_err(|_| anyhow!("Could not get any verification method for issuer URI"))?;

let output = resolver.resolve(did).await.map_err(|_| {
(
StatusCode::INTERNAL_SERVER_ERROR,
"Could not fetch issuer DID document".to_string(),
)
})?;
let output = resolver
.resolve(did)
.await
.context("Could not fetch issuer DID document")?;

let method = output
.document
.into_document()
.into_any_verification_method()
.ok_or((
StatusCode::INTERNAL_SERVER_ERROR,
"Could not get any verification method for issuer DID document",
))?;
.context("Could not get any verification method for issuer DID document")?;

req.options.ldp_options.input_options.verification_method =
Some(ReferenceOrOwned::Reference(method.id.clone().into_iri()));

Cow::Owned(GenericVerificationMethod::from(method).try_into()?)
Cow::Owned(
GenericVerificationMethod::from(method)
.try_into()
.context("Could not convert VM")?,
)
}
};

let public_jwk = method.try_to_jwk().ok_or((
StatusCode::INTERNAL_SERVER_ERROR,
"Could not get any verification method for issuer DID".to_string(),
))?;
let public_jwk = method
.try_to_jwk()
.context("Could not get any verification method for issuer DID")?;

if req.options.ldp_options.type_ == Some("DataIntegrityProof".to_string()) {
if req.options.ldp_options.cryptosuite.is_none() {
Expand Down Expand Up @@ -181,26 +174,19 @@ pub async fn issue(
)
.await
.context("Failed to sign VC")?;
//if let Some(p) = vc.proofs.first_mut() {
// if let Some(proof_context) = &p.context {
// match vc.claims {
// AnySpecializedJsonCredential::V1(ref mut vc) => {
// let mut context = vc.context.as_ref();
// *context = &json_ld::syntax::Context::Many(
// context.into_iter().chain(proof_context).cloned().collect(),
// );
// }
// AnySpecializedJsonCredential::V2(ref mut vc) => {
// //let context = vc.context.borrow_mut();
// //context = json_ld::syntax::Context::Many(
// // context.into_iter().chain(proof_context).cloned().collect(),
// //);
// todo!();
// }
// }
// p.context = None;
// }
//}
if let Some(p) = vc.proofs.first_mut() {
if let Some(proof_context) = &p.context {
match vc.claims {
AnySpecializedJsonCredential::V1(ref mut vc) => {
vc.context.extend(proof_context.clone());
}
AnySpecializedJsonCredential::V2(ref mut vc) => {
vc.context.extend(proof_context.clone());
}
}
p.context = None;
}
}

JsonCredentialOrJws::Credential(vc)
}
Expand Down Expand Up @@ -347,7 +333,6 @@ mod test {
let _ = issue(Extension(keys), CustomErrorJson(req)).await.unwrap();
}

#[ignore = "Depends on https://github.com/spruceid/ssi/pull/560"]
#[test(tokio::test)]
async fn issue_ed25519() {
let keys = default_keys();
Expand Down
55 changes: 25 additions & 30 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use anyhow::{anyhow, Context};
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
};
use ssi::{
dids::resolution,
verification_methods::{InvalidVerificationMethod, VerificationMethodResolutionError},
};
use ssi::dids::resolution;
use tracing::{debug, error};

#[derive(Debug, Clone)]
Expand All @@ -20,24 +18,6 @@ pub enum ErrorBody {
// Json(serde_json::Value),
}

impl From<VerificationMethodResolutionError> for Error {
fn from(value: VerificationMethodResolutionError) -> Self {
Error {
status: StatusCode::INTERNAL_SERVER_ERROR,
body: ErrorBody::Text(value.to_string()),
}
}
}

impl From<InvalidVerificationMethod> for Error {
fn from(value: InvalidVerificationMethod) -> Self {
Error {
status: StatusCode::INTERNAL_SERVER_ERROR,
body: ErrorBody::Text(value.to_string()),
}
}
}

impl From<resolution::Error> for Error {
fn from(value: resolution::Error) -> Self {
Self {
Expand All @@ -49,7 +29,12 @@ impl From<resolution::Error> for Error {
| resolution::Error::InvalidOptions
| resolution::Error::NoRepresentation => StatusCode::BAD_REQUEST,
resolution::Error::MethodNotSupported(_) => StatusCode::NOT_IMPLEMENTED,
resolution::Error::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
e @ resolution::Error::Internal(_) => {
return Err::<(), _>(e)
.context("Internal resolution error")
.unwrap_err()
.into()
}
},
body: ErrorBody::Text(format!("Resolution failed: {value}")),
}
Expand All @@ -58,7 +43,8 @@ impl From<resolution::Error> for Error {

impl From<resolution::DerefError> for Error {
fn from(value: resolution::DerefError) -> Self {
let status = match &value {
let body = ErrorBody::Text(format!("Dereferencing failed: {value}"));
let status = match value {
resolution::DerefError::Resolution(e) => match e {
resolution::Error::NotFound => StatusCode::NOT_FOUND,
resolution::Error::RepresentationNotSupported(_) => StatusCode::NOT_ACCEPTABLE,
Expand All @@ -67,7 +53,12 @@ impl From<resolution::DerefError> for Error {
| resolution::Error::InvalidOptions
| resolution::Error::NoRepresentation => StatusCode::BAD_REQUEST,
resolution::Error::MethodNotSupported(_) => StatusCode::NOT_IMPLEMENTED,
resolution::Error::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
e @ resolution::Error::Internal(_) => {
return Err::<(), _>(e)
.context("Internal resolution error")
.unwrap_err()
.into()
}
},
resolution::DerefError::NotFound | resolution::DerefError::ResourceNotFound(_) => {
StatusCode::NOT_FOUND
Expand All @@ -77,13 +68,17 @@ impl From<resolution::DerefError> for Error {
| resolution::DerefError::UnsupportedMultipleServiceEndpoints => {
StatusCode::NOT_IMPLEMENTED
}
_ => StatusCode::INTERNAL_SERVER_ERROR,
e @ resolution::DerefError::ServiceEndpointConstructionFailed(_) => {
return Err::<(), _>(e)
.context("service endpoint construction failed")
.unwrap_err()
.into()
}
resolution::DerefError::FragmentConflict => return anyhow!("Fragment conflict").into(),
resolution::DerefError::NullDereference => return anyhow!("Null Dereference").into(),
};

Self {
status,
body: ErrorBody::Text(format!("Dereferencing failed: {value}")),
}
Self { status, body }
}
}

Expand Down
16 changes: 4 additions & 12 deletions src/identifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,8 @@ pub async fn resolve(
match content_type {
ContentType::JsonLdDidResolution => {
serde_json::to_vec(&ResolutionResult::Success {
content: String::from_utf8(output.document).map_err(|_| {
(
StatusCode::INTERNAL_SERVER_ERROR,
"Non UTF-8 representation".to_string(),
)
})?,
content: String::from_utf8(output.document)
.context("Non UTF-8 representation".to_string())?,
metadata: output.metadata,
document_metadata: output.document_metadata,
})
Expand Down Expand Up @@ -145,12 +141,8 @@ pub async fn resolve(
match content_type {
ContentType::JsonLdDidResolution => {
serde_json::to_vec(&ResolutionResult::Success {
content: String::from_utf8(bytes).map_err(|_| {
(
StatusCode::INTERNAL_SERVER_ERROR,
"Non UTF-8 representation".to_string(),
)
})?,
content: String::from_utf8(bytes)
.context("Non UTF-8 representation".to_string())?,
metadata: output.metadata,
document_metadata: output.content_metadata,
})
Expand Down
Loading

0 comments on commit 9111a35

Please sign in to comment.