Skip to content
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
73 changes: 16 additions & 57 deletions matcher-rs/Cargo.lock

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

3 changes: 1 addition & 2 deletions matcher-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ crate-type = ["cdylib", "rlib"]

[dependencies]
lol_alloc = "0.4.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.145"
nanoserde = "0.1"

[dev-dependencies]

Expand Down
16 changes: 16 additions & 0 deletions matcher-rs/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 1. Build with maximum rustc optimizations
CARGO_PROFILE_RELEASE_PANIC=immediate-abort \
CARGO_PROFILE_RELEASE_OPT_LEVEL="z" \
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \
CARGO_PROFILE_RELEASE_STRIP=true \
cargo +nightly build \
-Z panic-immediate-abort \
-Z build-std \
--target wasm32-unknown-unknown \
--release

# 2. Further shrink using wasm-opt (if available)
wasm-opt -Oz --strip-debug --enable-bulk-memory \
target/wasm32-unknown-unknown/release/issuance.wasm \
-o target/wasm32-unknown-unknown/release/issuance.wasm

28 changes: 21 additions & 7 deletions matcher-rs/src/issuance.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::ffi::CString;

use crate::{
credman::CredmanApi,
issuance_matcher::IssuanceMatcherData,
openid4vci::{DigitalCredentialCreationRequest, RegularizedOpenId4VciRequestData},
};

use nanoserde::DeJson;

const ALLOWED_PROTOCOLS: [&str; 4] = [
"openid4vci-1.0",
"openid4vci1.0",
Expand All @@ -14,22 +18,32 @@ const ALLOWED_PROTOCOLS: [&str; 4] = [
pub fn issuance_main(credman: &mut impl CredmanApi) -> Result<(), Box<dyn std::error::Error>> {
let matcher_data_buffer = credman.get_registered_data();
let json_start = u32::from_le_bytes(matcher_data_buffer[..size_of::<u32>()].try_into()?);
let matcher_data: IssuanceMatcherData =
serde_json::from_slice(&matcher_data_buffer[json_start.try_into()?..])?;
let matcher_data: IssuanceMatcherData = DeJson::deserialize_json(std::str::from_utf8(
&matcher_data_buffer[json_start.try_into()?..],
)?)?;
let request: DigitalCredentialCreationRequest =
serde_json::from_slice(&credman.get_request_buffer())?;
DeJson::deserialize_json(std::str::from_utf8(&credman.get_request_buffer())?)?;
if request.requests.iter().any(|r| {
ALLOWED_PROTOCOLS.iter().any(|s| r.protocol == *s)
&& matcher_data
.filter
.matches(&RegularizedOpenId4VciRequestData::from(&r.data))
}) {
let icon = &matcher_data_buffer[matcher_data.icon.0..matcher_data.icon.1];
let entry_id = CString::new(matcher_data.entry_id)?;
let title = matcher_data
.title
.map(|s| CString::new(s))
.transpose()?;
let subtitle = matcher_data
.subtitle
.map(|s| CString::new(s))
.transpose()?;
credman.add_string_id_entry(
matcher_data.entry_id.as_c_str(),
&entry_id,
if icon.is_empty() { None } else { Some(icon) },
matcher_data.title.as_deref(),
matcher_data.subtitle.as_deref(),
title.as_deref(),
subtitle.as_deref(),
None,
None,
);
Expand Down Expand Up @@ -188,7 +202,7 @@ mod test {
};

let errmsg = format!("{:?}", issuance_main(&mut credman).unwrap_err());
assert!(errmsg.contains("EOF while parsing an object"));
assert!(errmsg.contains("Unexpected token Eof") || errmsg.contains("Unexpected end of file"));
}

#[test]
Expand Down
16 changes: 8 additions & 8 deletions matcher-rs/src/issuance_matcher.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::{collections::HashSet, ffi::CString};
use std::collections::HashSet;

use serde::Deserialize;
use nanoserde::DeJson;

use crate::openid4vci::RegularizedOpenId4VciRequestData;

#[derive(Deserialize, Debug)]
#[derive(DeJson, Debug)]
pub enum OpenId4VciFilter {
Unit {}, // A placeholder that always matches
And { filters: Vec<OpenId4VciFilter> },
Expand Down Expand Up @@ -79,12 +79,12 @@ impl OpenId4VciFilter {
}
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct IssuanceMatcherData {
pub entry_id: CString,
pub entry_id: String,
pub icon: (usize, usize),
pub title: Option<CString>,
pub subtitle: Option<CString>,
pub title: Option<String>,
pub subtitle: Option<String>,
pub filter: OpenId4VciFilter,
}
76 changes: 33 additions & 43 deletions matcher-rs/src/openid4vci.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
#![allow(unused)]

use serde::Deserialize;
use nanoserde::DeJson;

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct DigitalCredentialCreationRequest {
pub requests: Vec<OpenId4VciRequest>,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct OpenId4VciRequest {
pub protocol: String,
pub data: OpenId4VciRequestData,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct OpenId4VciRequestData {
pub credential_offer: credential_offer::CredentialOffer,
pub credential_issuer_metadata: Option<credential_issuer_metadata::CredentialIssuerMetadata>,
Expand Down Expand Up @@ -57,28 +57,28 @@ impl<'a> From<&'a OpenId4VciRequestData> for RegularizedOpenId4VciRequestData<'a
}

pub mod credential_offer {
use serde::Deserialize;
use nanoserde::DeJson;
use std::collections::HashMap;

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct CredentialOffer {
pub credential_issuer: String,
pub credential_configuration_ids: Vec<String>,
pub grants: HashMap<String, Grant>,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct Grant {}
}

mod credential_issuer_metadata {
use serde::Deserialize;
use nanoserde::DeJson;
use std::collections::{HashMap, HashSet};

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct CredentialIssuerMetadata {
// pub credential_issuer: String,
// pub authorization_servers: Option<Vec<String>>,
Expand All @@ -93,76 +93,66 @@ mod credential_issuer_metadata {
pub credential_configurations_supported: HashMap<String, CredentialConfiguration>,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct CredentialRequestEncryption {
// pub jwks: serde_json::Value,
// pub jwks: nanoserde::DeJson, // nanoserde doesn't have a Value type
pub enc_values_supported: HashSet<String>,
// pub zip_values_supported: Option<Vec<String>>,
pub encryption_required: bool,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct CredentialResponseEncryption {
pub alg_values_supported: HashSet<String>,
pub enc_values_supported: HashSet<String>,
// pub zip_values_supported: Vec<String>,
pub encryption_required: bool,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct BatchCredentialIssuance {
pub batch_size: u32,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct Display {
pub name: String,
pub locale: String,
pub logo: Option<Logo>,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct Logo {
pub uri: String,
pub alt_text: String,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct CredentialConfiguration {
pub format: String,
pub scope: String,
pub doctype: String,
pub vct: String,
pub credential_signing_alg_values_supported: SiginingAlgs,
pub credential_signing_alg_values_supported: Vec<String>,
pub cryptographic_binding_methods_supported: Option<Vec<String>>,
pub proof_types_supported: HashMap<String, ProofType>,
}

#[derive(Deserialize, Debug)]
#[serde(untagged)]
#[derive(Default)]
pub enum SiginingAlgs {
#[default]
Unspecified,
SringAlgs(Vec<String>),
IntAlgs(Vec<i32>),
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct ProofType {
pub proof_signing_alg_values_supported: Vec<String>,
pub key_attestations_required: Option<KeyAttestationsRequired>,
}

#[derive(Deserialize, Debug, Default)]
#[serde(default)]
#[derive(DeJson, Debug, Default)]
#[nserde(default)]
pub struct KeyAttestationsRequired {
pub key_storage: Option<Vec<String>>,
pub user_authentication: Option<Vec<String>>,
Expand Down
Loading