Skip to content

Commit

Permalink
add wasm bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
abdulmth committed Jan 10, 2024
1 parent 6a5cc5a commit 6459d98
Show file tree
Hide file tree
Showing 13 changed files with 630 additions and 14 deletions.
2 changes: 1 addition & 1 deletion bindings/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ wasm-bindgen-futures = { version = "0.4", default-features = false }
version = "1.0.0"
path = "../../identity_iota"
default-features = false
features = ["client", "revocation-bitmap", "resolver", "domain-linkage"]
features = ["client", "revocation-bitmap", "resolver", "domain-linkage", "sd-jwt"]

[dev-dependencies]
rand = "0.8.5"
Expand Down
173 changes: 161 additions & 12 deletions bindings/wasm/docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ It does not imply anything about a potentially present proof property on the cre
<p>Note that having an instance of this type only means the JWS it was constructed from was verified.
It does not imply anything about a potentially present proof property on the presentation itself.</p>
</dd>
<dt><a href="#Disclosure">Disclosure</a></dt>
<dd></dd>
<dt><a href="#DomainLinkageConfiguration">DomainLinkageConfiguration</a></dt>
<dd><p>DID Configuration Resource which contains Domain Linkage Credentials.
It can be placed in an origin&#39;s <code>.well-known</code> directory to prove linkage between the origin and a DID.
Expand Down Expand Up @@ -130,6 +132,10 @@ verifiable <a href="#Credential">Credential</a>s and <a href="#Presentation">Pre
<dt><a href="#RevocationBitmap">RevocationBitmap</a></dt>
<dd><p>A compressed bitmap for managing credential revocation.</p>
</dd>
<dt><a href="#SdObjectDecoder">SdObjectDecoder</a></dt>
<dd></dd>
<dt><a href="#SdObjectEncoder">SdObjectEncoder</a></dt>
<dd></dd>
<dt><a href="#Service">Service</a></dt>
<dd><p>A DID Document Service used to enable trusted interactions associated with a DID subject.</p>
</dd>
Expand All @@ -149,10 +155,6 @@ working with storage backed DID documents.</p>
## Members

<dl>
<dt><a href="#StateMetadataEncoding">StateMetadataEncoding</a></dt>
<dd></dd>
<dt><a href="#MethodRelationship">MethodRelationship</a></dt>
<dd></dd>
<dt><a href="#StatusCheck">StatusCheck</a></dt>
<dd><p>Controls validation behaviour when checking whether or not a credential has been revoked by its
<a href="https://www.w3.org/TR/vc-data-model/#status"><code>credentialStatus</code></a>.</p>
Expand Down Expand Up @@ -193,6 +195,10 @@ This variant is the default.</p>
<dt><a href="#FirstError">FirstError</a></dt>
<dd><p>Return after the first error occurs.</p>
</dd>
<dt><a href="#StateMetadataEncoding">StateMetadataEncoding</a></dt>
<dd></dd>
<dt><a href="#MethodRelationship">MethodRelationship</a></dt>
<dd></dd>
</dl>

## Functions
Expand Down Expand Up @@ -1384,6 +1390,65 @@ The `aud` property parsed from JWT claims.
The custom claims parsed from the JWT.

**Kind**: instance method of [<code>DecodedJwtPresentation</code>](#DecodedJwtPresentation)
<a name="Disclosure"></a>

## Disclosure
**Kind**: global class

* [Disclosure](#Disclosure)
* [new Disclosure(salt, claim_name, claim_value)](#new_Disclosure_new)
* _instance_
* [.disclosure()](#Disclosure+disclosure) ⇒ <code>string</code>
* [.salt()](#Disclosure+salt) ⇒ <code>string</code>
* [.claimName()](#Disclosure+claimName) ⇒ <code>string</code> \| <code>undefined</code>
* [.claimValue()](#Disclosure+claimValue) ⇒ <code>any</code>
* [.toJSON()](#Disclosure+toJSON) ⇒ <code>any</code>
* _static_
* [.fromJSON(json)](#Disclosure.fromJSON)[<code>Disclosure</code>](#Disclosure)

<a name="new_Disclosure_new"></a>

### new Disclosure(salt, claim_name, claim_value)

| Param | Type |
| --- | --- |
| salt | <code>string</code> |
| claim_name | <code>string</code> \| <code>undefined</code> |
| claim_value | <code>any</code> |

<a name="Disclosure+disclosure"></a>

### disclosure.disclosure() ⇒ <code>string</code>
**Kind**: instance method of [<code>Disclosure</code>](#Disclosure)
<a name="Disclosure+salt"></a>

### disclosure.salt() ⇒ <code>string</code>
**Kind**: instance method of [<code>Disclosure</code>](#Disclosure)
<a name="Disclosure+claimName"></a>

### disclosure.claimName() ⇒ <code>string</code> \| <code>undefined</code>
**Kind**: instance method of [<code>Disclosure</code>](#Disclosure)
<a name="Disclosure+claimValue"></a>

### disclosure.claimValue() ⇒ <code>any</code>
**Kind**: instance method of [<code>Disclosure</code>](#Disclosure)
<a name="Disclosure+toJSON"></a>

### disclosure.toJSON() ⇒ <code>any</code>
Serializes this to a JSON object.

**Kind**: instance method of [<code>Disclosure</code>](#Disclosure)
<a name="Disclosure.fromJSON"></a>

### Disclosure.fromJSON(json) ⇒ [<code>Disclosure</code>](#Disclosure)
Deserializes an instance from a JSON object.

**Kind**: static method of [<code>Disclosure</code>](#Disclosure)

| Param | Type |
| --- | --- |
| json | <code>any</code> |

<a name="DomainLinkageConfiguration"></a>

## DomainLinkageConfiguration
Expand Down Expand Up @@ -4627,6 +4692,90 @@ if it is a valid Revocation Bitmap Service.
| --- | --- |
| service | [<code>Service</code>](#Service) |

<a name="SdObjectDecoder"></a>

## SdObjectDecoder
**Kind**: global class
<a name="SdObjectDecoder+decode"></a>

### sdObjectDecoder.decode(object, disclosures) ⇒ <code>Record.&lt;string, any&gt;</code>
**Kind**: instance method of [<code>SdObjectDecoder</code>](#SdObjectDecoder)

| Param | Type |
| --- | --- |
| object | <code>Record.&lt;string, any&gt;</code> |
| disclosures | <code>Array.&lt;string&gt;</code> |

<a name="SdObjectEncoder"></a>

## SdObjectEncoder
**Kind**: global class

* [SdObjectEncoder](#SdObjectEncoder)
* [new SdObjectEncoder(object)](#new_SdObjectEncoder_new)
* [.conceal(path, salt)](#SdObjectEncoder+conceal)[<code>Disclosure</code>](#Disclosure)
* [.concealArrayEntry(path, element_index, salt)](#SdObjectEncoder+concealArrayEntry)[<code>Disclosure</code>](#Disclosure)
* [.addSdAlgProperty()](#SdObjectEncoder+addSdAlgProperty)
* [.toString()](#SdObjectEncoder+toString) ⇒ <code>string</code>
* [.encoded_object()](#SdObjectEncoder+encoded_object) ⇒ <code>Record.&lt;string, any&gt;</code>
* [.toJSON()](#SdObjectEncoder+toJSON) ⇒ <code>any</code>
* [.addDecoys(path, number_of_decoys)](#SdObjectEncoder+addDecoys)

<a name="new_SdObjectEncoder_new"></a>

### new SdObjectEncoder(object)

| Param | Type |
| --- | --- |
| object | <code>any</code> |

<a name="SdObjectEncoder+conceal"></a>

### sdObjectEncoder.conceal(path, salt) ⇒ [<code>Disclosure</code>](#Disclosure)
**Kind**: instance method of [<code>SdObjectEncoder</code>](#SdObjectEncoder)

| Param | Type |
| --- | --- |
| path | <code>Array.&lt;string&gt;</code> |
| salt | <code>string</code> \| <code>undefined</code> |

<a name="SdObjectEncoder+concealArrayEntry"></a>

### sdObjectEncoder.concealArrayEntry(path, element_index, salt) ⇒ [<code>Disclosure</code>](#Disclosure)
**Kind**: instance method of [<code>SdObjectEncoder</code>](#SdObjectEncoder)

| Param | Type |
| --- | --- |
| path | <code>Array.&lt;string&gt;</code> |
| element_index | <code>number</code> |
| salt | <code>string</code> \| <code>undefined</code> |

<a name="SdObjectEncoder+addSdAlgProperty"></a>

### sdObjectEncoder.addSdAlgProperty()
**Kind**: instance method of [<code>SdObjectEncoder</code>](#SdObjectEncoder)
<a name="SdObjectEncoder+toString"></a>

### sdObjectEncoder.toString() ⇒ <code>string</code>
**Kind**: instance method of [<code>SdObjectEncoder</code>](#SdObjectEncoder)
<a name="SdObjectEncoder+encoded_object"></a>

### sdObjectEncoder.encoded\_object() ⇒ <code>Record.&lt;string, any&gt;</code>
**Kind**: instance method of [<code>SdObjectEncoder</code>](#SdObjectEncoder)
<a name="SdObjectEncoder+toJSON"></a>

### sdObjectEncoder.toJSON() ⇒ <code>any</code>
**Kind**: instance method of [<code>SdObjectEncoder</code>](#SdObjectEncoder)
<a name="SdObjectEncoder+addDecoys"></a>

### sdObjectEncoder.addDecoys(path, number_of_decoys)
**Kind**: instance method of [<code>SdObjectEncoder</code>](#SdObjectEncoder)

| Param | Type |
| --- | --- |
| path | <code>Array.&lt;string&gt;</code> |
| number_of_decoys | <code>number</code> |

<a name="Service"></a>

## Service
Expand Down Expand Up @@ -5041,14 +5190,6 @@ Deserializes an instance from a JSON object.
| --- | --- |
| json | <code>any</code> |

<a name="StateMetadataEncoding"></a>

## StateMetadataEncoding
**Kind**: global variable
<a name="MethodRelationship"></a>

## MethodRelationship
**Kind**: global variable
<a name="StatusCheck"></a>

## StatusCheck
Expand Down Expand Up @@ -5124,6 +5265,14 @@ Return all errors that occur during validation.
## FirstError
Return after the first error occurs.

**Kind**: global variable
<a name="StateMetadataEncoding"></a>

## StateMetadataEncoding
**Kind**: global variable
<a name="MethodRelationship"></a>

## MethodRelationship
**Kind**: global variable
<a name="start"></a>

Expand Down
3 changes: 2 additions & 1 deletion bindings/wasm/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ impl_wasm_error_from!(
identity_iota::credential::JwtValidationError,
identity_iota::credential::RevocationError,
identity_iota::verification::Error,
identity_iota::credential::DomainLinkageValidationError
identity_iota::credential::DomainLinkageValidationError,
identity_iota::sd_jwt_payload::Error
);

// Similar to `impl_wasm_error_from`, but uses the types name instead of requiring/calling Into &'static str
Expand Down
1 change: 1 addition & 0 deletions bindings/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub mod iota;
pub mod jose;
pub mod resolver;
pub mod revocation;
pub mod sd_jwt;
pub mod storage;
pub mod verification;

Expand Down
41 changes: 41 additions & 0 deletions bindings/wasm/src/sd_jwt/decoder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2020-2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use crate::{
common::{ArrayString, RecordStringAny},
error::{Result, WasmResult},
};
use identity_iota::sd_jwt_payload::SdObjectDecoder;
use serde_json::{Map, Value};
use wasm_bindgen::prelude::*;

/// Substitutes digests in an SD-JWT object by their corresponding plaintext values provided by disclosures.
#[wasm_bindgen(js_name = SdObjectDecoder, inspectable)]
pub struct WasmSdObjectDecoder(pub(crate) SdObjectDecoder);

#[wasm_bindgen(js_class = SdObjectDecoder)]
impl WasmSdObjectDecoder {
/// Creates a new `SdObjectDecoder` with `sha-256` hasher.
#[wasm_bindgen(constructor)]
pub fn new() -> WasmSdObjectDecoder {
Self(SdObjectDecoder::new_with_sha256())
}

/// Decodes an SD-JWT `object` containing by Substituting the digests with their corresponding
/// plaintext values provided by `disclosures`.
///
/// ## Notes
/// * Claims like `exp` or `iat` are not validated in the process of decoding.
/// * `_sd_alg` property will be removed if present.
#[wasm_bindgen]
pub fn decode(&self, object: RecordStringAny, disclosures: ArrayString) -> Result<RecordStringAny> {
let object: Map<String, Value> = object.into_serde().wasm_result()?;
let disclosures: Vec<String> = disclosures.into_serde().wasm_result()?;
let decoded = self.0.decode(&object, &disclosures).wasm_result()?;
Ok(
JsValue::from_serde(&decoded)
.wasm_result()?
.unchecked_into::<RecordStringAny>(),
)
}
}
68 changes: 68 additions & 0 deletions bindings/wasm/src/sd_jwt/disclosure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2020-2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use crate::error::Result;
use crate::error::WasmResult;
use identity_iota::sd_jwt_payload::Disclosure;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsValue;

/// Represents an elements constructing a disclosure.
/// Object properties and array elements disclosures are supported.
///
/// See: https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-07.html#name-disclosures
#[wasm_bindgen(js_name = Disclosure, inspectable)]
pub struct WasmDisclosure(pub(crate) Disclosure);

#[wasm_bindgen(js_class = Disclosure)]
impl WasmDisclosure {
#[wasm_bindgen(constructor)]
pub fn new(salt: String, claim_name: Option<String>, claim_value: JsValue) -> Result<WasmDisclosure> {
Ok(Self(Disclosure::new(
salt,
claim_name,
claim_value.into_serde().wasm_result()?,
)))
}

/// Parses a Base64 encoded disclosure into a `Disclosure`.
///
/// ## Error
///
/// Returns an `InvalidDisclosure` if input is not a valid disclosure.
#[wasm_bindgen]
pub fn parse(disclosure: String) -> Result<WasmDisclosure> {
Ok(WasmDisclosure(Disclosure::parse(disclosure).wasm_result()?))
}

/// Returns a copy of the base64url-encoded string.
#[wasm_bindgen(js_name = disclosure)]
pub fn disclosure(&self) -> String {
self.0.disclosure.clone()
}

/// Returns a copy of the base64url-encoded string.
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> String {
self.0.disclosure.clone()
}

/// Returns a copy of the salt value.
#[wasm_bindgen(js_name = salt)]
pub fn salt(&self) -> String {
self.0.salt.clone()
}

/// Returns a copy of the claim name, optional for array elements.
#[wasm_bindgen(js_name = claimName)]
pub fn claim_name(&self) -> Option<String> {
self.0.claim_name.clone()
}

/// Returns a copy of the claim Value which can be of any type.
#[wasm_bindgen(js_name = claimValue)]
pub fn claim_value(&self) -> Result<JsValue> {
JsValue::from_serde(&self.0.claim_value.clone()).wasm_result()
}
}
impl_wasm_json!(WasmDisclosure, Disclosure);
Loading

0 comments on commit 6459d98

Please sign in to comment.