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

feat(wasm): adding wasm compatibility #8

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ local.properties
anoncred-kmm/anoncred-wrapper-rust/src/*
**/.DS_Store
anoncred-kmm/anoncred-kmm/anoncred-wrapper-rust/src/*
pkg/
18 changes: 15 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ crate-type = ["staticlib", "rlib", "cdylib"]

[features]
default = ["ffi", "logger", "zeroize"]
ffi = ["ffi-support"]
ffi = ["ffi-support", "non_wasm"]
logger = ["env_logger"]
vendored = ["openssl", "openssl/vendored"]
non_wasm = ["ursa/cl_native", "ursa/serde"]
wasm = ["ursa/portable_wasm", "zeroize", "wasm-bindgen", "wasm-logger", "console_error_panic_hook", "serde-wasm-bindgen"]

[dependencies]
bs58 = "0.4.0"
Expand All @@ -36,14 +38,24 @@ serde_json = { version = "1.0.94", features = ["raw_value"]}
sha2 = "0.10.6"
tempfile = "3.4.0"
thiserror = "1.0.39"
ursa = { version = "0.3.7", default-features = false, features = ["cl_native", "serde"] }
zeroize = { version = "1.5.7", optional = true, features = ["zeroize_derive"] }
zeroize = { version = "=1.4", optional = true, features = ["zeroize_derive"] }
wasm-bindgen = { version = "0.2.84", optional = true }
wasm-logger = { version = "0.2.0", optional = true }
console_error_panic_hook = { version="0.1.7", optional = true }
serde-wasm-bindgen = { version = "0.4", optional = true}

# We add the openssl dependency here because ursa does not expose a vendored openssl feature
# Since we use "cl_native" as a feature, which uses openssl, we can add a vendored build with
# the new exposed "vendored" feature
openssl = { version = "0.10.45", optional = true }

[dependencies.ursa]
git = "https://github.com/hyperledger/ursa.git"
rev = "390f004e3e91f1257da4bbcd6bc2d72f67b62c0f"
version = "0.3.7"
default-features = false


[profile.release]
lto = true
codegen-units = 1
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ mod utils;
#[cfg(feature = "ffi")]
mod ffi;

#[cfg(feature = "wasm")]
mod wasm;

pub mod data_types;
1 change: 1 addition & 0 deletions src/services/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ pub mod verifier;

pub mod utils {
pub use super::helpers::encode_credential_attribute;
pub use super::helpers::new_nonce;
}
16 changes: 16 additions & 0 deletions src/wasm/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use wasm_bindgen::prelude::*;

#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize)]
#[repr(usize)]
#[wasm_bindgen]
pub enum ErrorCode {
Success = 0,
Input = 1,
IOError = 2,
InvalidState = 3,
Unexpected = 4,
CredentialRevoked = 5,
InvalidUserRevocId = 6,
ProofRejected = 7,
RevocationRegistryFull = 8,
}
145 changes: 145 additions & 0 deletions src/wasm/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// --- HELPERS ---
use wasm_bindgen::prelude::*;

use std::str::FromStr;

use crate::data_types::credential::Credential;
use crate::data_types::cred_def::SignatureType;
use crate::data_types::cred_def::CredentialDefinition;
use crate::data_types::cred_offer::CredentialOffer;
use crate::data_types::cred_request::CredentialRequestMetadata;
use crate::data_types::link_secret::LinkSecret;
use crate::data_types::pres_request::PresentationRequest;
use crate::data_types::schema::Schema;

use crate::services::issuer;

use crate::types::CredentialDefinitionConfig;

use crate::utils::validation::Validatable;

use super::error::ErrorCode;

#[wasm_bindgen(js_name = anoncredsSetDefaultLogger)]
pub fn anoncreds_set_default_logger() -> ErrorCode {
console_error_panic_hook::set_once();
wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
debug!("Initialized default logger");

ErrorCode::Success
}

#[wasm_bindgen(js_name = anoncredsCreateSchema)]
pub fn anoncreds_create_schema(
name: &str,
version: &str,
issuer_id: &str,
attribute_names: Vec<JsValue>,
) -> JsValue {
let mut attribute_names_vec: Vec<String> = vec![];

for name in &attribute_names {
let name = name.as_string();
if let Some(name) = name {
attribute_names_vec.push(name.to_owned());
}
}

let schema =
issuer::create_schema(name, version, issuer_id, attribute_names_vec.into()).unwrap();

serde_wasm_bindgen::to_value(&schema).unwrap()
}

#[wasm_bindgen(js_name = anoncredsCreateCredentialDefinition)]
pub fn anoncreds_create_credential_definition(
schema_id: &str,
schema: JsValue,
tag: &str,
issuer_id: &str,
signature_type: &str,
support_revocation: bool,
) -> Vec<JsValue> {
let schema: Schema = serde_wasm_bindgen::from_value(schema).unwrap();
let signature_type = SignatureType::from_str(signature_type)
.map_err(err_map!(Input))
.unwrap();
let (cred_def, cred_def_pvt, key_proof) = issuer::create_credential_definition(
schema_id,
&schema,
issuer_id,
tag,
signature_type,
CredentialDefinitionConfig { support_revocation },
)
.unwrap();

let cred_def = serde_wasm_bindgen::to_value(&cred_def).unwrap();
let cred_def_pvt = serde_wasm_bindgen::to_value(&cred_def_pvt).unwrap();
let key_proof = serde_wasm_bindgen::to_value(&key_proof).unwrap();

vec![cred_def, cred_def_pvt, key_proof]
}

#[wasm_bindgen(js_name = anoncredsCreateCredentialDefinitionCustom)]
pub fn anoncreds_create_credential_definition_custom(
schema_id: &str,
schema: JsValue,
tag: &str,
issuer_id: &str,
) -> Vec<JsValue> {
let schema: Schema = serde_wasm_bindgen::from_value(schema).unwrap();

let (cred_def, cred_def_pvt, key_proof) = issuer::create_credential_definition(
schema_id,
&schema,
issuer_id,
tag,
SignatureType::CL,
CredentialDefinitionConfig { support_revocation: false },
)
.unwrap();

let cred_def = serde_wasm_bindgen::to_value(&cred_def).unwrap();
let cred_def_pvt = serde_wasm_bindgen::to_value(&cred_def_pvt).unwrap();
let key_proof = serde_wasm_bindgen::to_value(&key_proof).unwrap();

vec![cred_def, cred_def_pvt, key_proof]
}


#[wasm_bindgen(js_name = anoncredsValidateCredentialDefinitionFromJson)]
pub fn anoncreds_validate_credential_definition_from_json(
json: JsValue
) -> Result<bool, JsValue> {
let cred_def: CredentialDefinition = serde_wasm_bindgen::from_value(json).map_err(|e| <serde_wasm_bindgen::Error as Into<JsValue>>::into(e))?;
cred_def.validate().map(|_| true).map_err(|e| JsValue::from_str(&e.to_string()))
}


// --- SERDE ---

pub fn deserialise_credential(credential: JsValue) -> Credential {
serde_wasm_bindgen::from_value(credential).expect("Unable to deserialise Credential")
}

pub fn deserialise_credential_offer(cred_offer: JsValue) -> CredentialOffer {
serde_wasm_bindgen::from_value(cred_offer).expect("Unable to deserialise Credential Offer")
}

pub fn deserialise_credential_definition(cred_def: JsValue) -> CredentialDefinition {
serde_wasm_bindgen::from_value(cred_def).expect("Unable to deserialise Credential Definition")
}

pub fn deserialise_credential_request_metadata(cred_req_meta: JsValue) -> CredentialRequestMetadata {
serde_wasm_bindgen::from_value(cred_req_meta).expect("Unable to deserialise Credential Request Metadata")
}

pub fn deserialise_link_secret(link_secret: &str) -> LinkSecret {
LinkSecret::try_from(link_secret).expect("Unable to deserialise Link Secret")
}

pub fn deserialise_presentation_request(pres_req: JsValue) -> PresentationRequest {
let json = serde_wasm_bindgen::from_value(pres_req).expect("Unable to deserialise Presentation Request");
serde_json::from_value(json).expect("Unable to parse Presentation Request")
}
71 changes: 71 additions & 0 deletions src/wasm/issuer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// --- ISSUER ---
use wasm_bindgen::prelude::*;

use crate::data_types::cred_def::CredentialDefinition;
use crate::data_types::cred_def::CredentialDefinitionPrivate;
use crate::data_types::cred_def::SignatureType;
use crate::data_types::cred_offer::CredentialOffer;
use crate::data_types::cred_request::CredentialRequest;
use crate::data_types::schema::Schema;

use crate::services::issuer;

use crate::types::CredentialDefinitionConfig;
use crate::types::MakeCredentialValues;

#[wasm_bindgen(js_name = issuerCreateCredentialOffer)]
pub fn issuer_create_credential_offer(js_schema: JsValue) -> Vec<JsValue> {
let schema: Schema = serde_wasm_bindgen::from_value(js_schema).unwrap();

let (cred_def, cred_def_priv, key_correctness_proof) =
issuer::create_credential_definition("did:web:xyz/resource/schema",
&schema,
"did:web:xyz",
"default-tag",
SignatureType::CL,
CredentialDefinitionConfig::default()
).expect("Unable to create Credential Definition");

let credential_offer =
issuer::create_credential_offer("did:web:xyz/resource/schema",
"did:web:xyz/resource/cred-def",
&key_correctness_proof,
).expect("Unable to create Credential Offer");

let js_cred_offer = serde_wasm_bindgen::to_value(&credential_offer).unwrap();
let js_cred_def = serde_wasm_bindgen::to_value(&cred_def).unwrap();
let js_cred_def_priv = serde_wasm_bindgen::to_value(&cred_def_priv).unwrap();

vec![js_cred_offer, js_cred_def, js_cred_def_priv]
}

#[wasm_bindgen(js_name = issuerCreateCredential)]
pub fn issuer_create_credential(
js_cred_offer: JsValue,
js_cred_def: JsValue,
js_cred_def_priv: JsValue,
js_cred_request: JsValue
) -> JsValue {
let cred_def: CredentialDefinition = serde_wasm_bindgen::from_value(js_cred_def).unwrap();
let cred_def_priv: CredentialDefinitionPrivate = serde_wasm_bindgen::from_value(js_cred_def_priv).unwrap();
let credential_offer: CredentialOffer = serde_wasm_bindgen::from_value(js_cred_offer).unwrap();
let credential_request: CredentialRequest = serde_wasm_bindgen::from_value(js_cred_request).unwrap();

let mut credential_values = MakeCredentialValues::default();
credential_values.add_raw("name", "john").expect("Unable to add credential value");
credential_values.add_raw("age", "28").expect("Unable to add credential value");

let credential = issuer::create_credential(
&cred_def,
&cred_def_priv,
&credential_offer,
&credential_request,
credential_values.into(),
None,
None,
None
)
.expect("Unable to create credential");

serde_wasm_bindgen::to_value(&credential).unwrap()
}
8 changes: 8 additions & 0 deletions src/wasm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mod error;
mod helpers;

pub mod prover;

// not currently required for SDKs
// pub mod issuer;
// pub mod verifier;
Loading
Loading