Skip to content
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
Binary file added .github/banner_identity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 0 additions & 83 deletions .github/banner_identity.svg

This file was deleted.

5 changes: 5 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ jobs:
}}

steps:


- name: git configure long path
if: matrix.os == 'windows-latest'
run: git config --global core.longpaths true
- uses: actions/checkout@v3

- name: Ensure, OpenSSL is available in Windows
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- name: Install wasm-bindgen-cli
uses: jetli/wasm-bindgen-action@24ba6f9fff570246106ac3f80f35185600c3f6c9
with:
version: '0.2.100'
version: '0.2.102'

- name: core clippy check
uses: actions-rs-plus/clippy-check@b09a9c37c9df7db8b1a5d52e8fe8e0b6e3d574c4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/shared-build-wasm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
- name: Install wasm-bindgen-cli
uses: jetli/wasm-bindgen-action@24ba6f9fff570246106ac3f80f35185600c3f6c9
with:
version: '0.2.100'
version: '0.2.102'

- name: Setup sccache
uses: './.github/actions/rust/sccache/setup-sccache'
Expand Down
10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,23 @@ members = [
"identity_jose",
"identity_ecdsa_verifier",
"identity_eddsa_verifier",
"identity_pqc_verifier",
"examples",
]

exclude = ["bindings/wasm/identity_wasm", "bindings/grpc"]

[workspace.dependencies]
bls12_381_plus = { version = "0.8.17" }
iota_interaction = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.0", package = "iota_interaction" }
iota_interaction_ts = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.0", package = "iota_interaction_ts" }
product_common = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.0", package = "product_common" }
iota_interaction = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.3", package = "iota_interaction" }
iota_interaction_ts = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.3", package = "iota_interaction_ts" }
product_common = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.3", package = "product_common" }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
serde_json = { version = "1.0", default-features = false }
oqs = { version = "0.10", default-features = false, features = ["sigs", "std", "vendored"] }
strum = { version = "0.25", default-features = false, features = ["std", "derive"] }
thiserror = { version = "1.0", default-features = false }
json-proof-token = { version = "0.3.5" }
json-proof-token = { version = "0.4" }
zkryptium = { version = "0.2.2", default-features = false, features = ["bbsplus"] }

[workspace.lints.clippy]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![banner](https://github.com/iotaledger/identity/raw/HEAD/.github/banner_identity.svg)
![banner](https://github.com/iotaledger/identity/raw/HEAD/.github/banner_identity.png)

<p align="center">
<a href="https://iota.stackexchange.com/" style="text-decoration:none;"><img src="https://img.shields.io/badge/StackExchange-9cf.svg?logo=stackexchange" alt="StackExchange"></a>
Expand Down
2 changes: 1 addition & 1 deletion bindings/grpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ identity_iota = { path = "../../identity_iota", features = ["resolver", "sd-jwt"
identity_jose = { path = "../../identity_jose" }
identity_storage = { path = "../../identity_storage", features = ["memstore"] }
identity_stronghold = { path = "../../identity_stronghold", features = ["send-sync-storage"] }
iota-sdk = { git = "https://github.com/iotaledger/iota.git", package = "iota-sdk", tag = "v1.4.1" }
iota-sdk = { git = "https://github.com/iotaledger/iota.git", package = "iota-sdk", tag = "v1.7.0" }
iota-sdk-legacy = { package = "iota-sdk", version = "1.1.2", features = ["stronghold"] }
prost = "0.13"
rand = "0.8.5"
Expand Down
16 changes: 10 additions & 6 deletions bindings/wasm/identity_wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "identity_wasm"
version = "1.6.0-beta.7"
version = "1.6.0-beta.10"
authors = ["IOTA Stiftung"]
edition = "2021"
homepage = "https://www.iota.org"
Expand All @@ -23,14 +23,15 @@ console_error_panic_hook = { version = "0.1" }
fastcrypto = { git = "https://github.com/MystenLabs/fastcrypto", rev = "69d496c71fb37e3d22fe85e5bbfd4256d61422b9", package = "fastcrypto" }
identity_ecdsa_verifier = { path = "../../../identity_ecdsa_verifier", default-features = false, features = ["es256", "es256k"] }
identity_eddsa_verifier = { path = "../../../identity_eddsa_verifier", default-features = false, features = ["ed25519"] }
iota-caip = { git = "https://github.com/iotaledger/iota-caip.git", features = ["serde"] }
# Remove iota-sdk dependency while working on issue #1445
iota-sdk = { version = "1.1.5", default-features = false, features = ["serde", "std"] }
iota_interaction = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.0", package = "iota_interaction", default-features = false }
iota_interaction_ts = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.0", package = "iota_interaction_ts" }
iota_interaction = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.3", package = "iota_interaction", default-features = false }
iota_interaction_ts = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.3", package = "iota_interaction_ts" }
js-sys = { version = "0.3.61" }
json-proof-token = "0.3.4"
json-proof-token = "0.4"
proc_typescript = { version = "0.1.0", path = "./proc_typescript" }
product_common = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.0", package = "product_common", features = ["core-client", "transaction", "bindings", "gas-station", "default-http-client"] }
product_common = { git = "https://github.com/iotaledger/product-core.git", tag = "v0.8.3", package = "product_common", features = ["core-client", "transaction", "bindings", "gas-station", "default-http-client"] }
secret-storage = { git = "https://github.com/iotaledger/secret-storage.git", default-features = false, tag = "v0.3.0" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.6.5"
Expand All @@ -39,7 +40,7 @@ serde_repr = { version = "0.1", default-features = false }
# Want to use the nice API of tokio::sync::RwLock for now even though we can't use threads.
tokio = { version = "1.46.1", default-features = false, features = ["sync"] }
tsify = "0.4.5"
wasm-bindgen = { version = "0.2.100", features = ["serde-serialize"] }
wasm-bindgen = { version = "=0.2.102", features = ["serde-serialize"] }
wasm-bindgen-futures = { version = "0.4", default-features = false }

[dependencies.identity_iota]
Expand All @@ -54,8 +55,11 @@ features = [
"sd-jwt-vc",
"status-list-2021",
"jpt-bbs-plus",
"pqc",
"hybrid",
"gas-station",
"default-http-client",
"irl",
]

[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/identity_wasm/examples/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![banner](https://github.com/iotaledger/identity/raw/HEAD/.github/banner_identity.svg)
![banner](https://github.com/iotaledger/identity/raw/HEAD/.github/banner_identity.png)

## IOTA Identity Examples

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Copyright 2020-2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import {
CoreDID,
Credential,
EdDSAJwsVerifier,
IdentityClientReadOnly,
IotaDocument,
IrlResolver,
JwsSignatureOptions,
Jwt,
JwtPresentationOptions,
JwtPresentationValidationOptions,
JwtPresentationValidator,
LinkedVerifiablePresentationService,
Presentation,
Resolver,
Storage,
} from "@iota/identity-wasm/node";
import { IotaClient } from "@iota/iota-sdk/client";
import { OnChainNotarization } from "@iota/notarization/node";
import {
createDocumentForNetwork,
getFundedClient,
getMemstorage,
getNotarizationClient,
IOTA_IDENTITY_PKG_ID,
NETWORK_URL,
TEST_GAS_BUDGET,
} from "../util";

/**
* This example shows how to create a Verifiable Presentation and validate it.
* A Verifiable Presentation is the format in which a (collection of) Verifiable Credential(s) gets shared.
* It is signed by the subject, to prove control over the Verifiable Credential with a nonce or timestamp.
*/
export async function linkedVp() {
// ===========================================================================
// Create identities and clients.
// ===========================================================================

// Create new client to connect to IOTA network
const iotaClient = new IotaClient({ url: NETWORK_URL });
const network = await iotaClient.getChainIdentifier();

// Create issuer account, create identity, and publish DID document for it
const storage = getMemstorage();
const identityClient = await getFundedClient(storage);
const [unpublishedDidDocument, fragment] = await createDocumentForNetwork(storage, network);
const notarizationClient = await getNotarizationClient(identityClient.signer());
const publishedDidDocument = await identityClient
.publishDidDocument(unpublishedDidDocument, identityClient.senderAddress())
.buildAndExecute(identityClient)
.then(res => res.output);

// ===========================================================================
// Create a Verifiable Presentation and host it on-chain.
// ===========================================================================

const jwtVp = await makeVpJwt(publishedDidDocument, storage, fragment);
const notarizedVp: OnChainNotarization = await notarizationClient
.createLocked()
.withStringState(jwtVp.toString(), "My Linked VP")
.finish()
.buildAndExecute(notarizationClient)
.then(res => res.output);

// ===========================================================================
// Create Linked Verifiable Presentation service.
// ===========================================================================

const serviceUrl = publishedDidDocument.id().join("#linked-vp");
const linkedVpService = new LinkedVerifiablePresentationService({
id: serviceUrl,
linkedVp: notarizedVp.iotaResourceLocatorBuilder(notarizationClient.network()).data(),
});
publishedDidDocument.insertService(linkedVpService.toService());

await identityClient.publishDidDocumentUpdate(publishedDidDocument, TEST_GAS_BUDGET);

// ===========================================================================
// Verification.
// ===========================================================================

const resolver = new Resolver<IotaDocument>({
client: await IdentityClientReadOnly.createWithPkgId(iotaClient, IOTA_IDENTITY_PKG_ID),
});
// Resolve the presentation holder.
const presentationHolderDID: CoreDID = JwtPresentationValidator.extractHolder(jwtVp);
const resolvedHolder = await resolver.resolve(
presentationHolderDID.toString(),
);

// Get the Linked Verifiable Presentation Services from the DID Document.
const linkedVpServices = resolvedHolder.service().filter(service =>
service.type().includes("LinkedVerifiablePresentation")
);
console.assert(linkedVpServices.length == 1, "expected exactly one Linked Verifiable Presentation service");

// Get the VPs included the service.
const vpUrl = LinkedVerifiablePresentationService.fromService(linkedVpServices[0]).verifiablePresentationUrls()[0];
console.log(`Fetching VP at \`${vpUrl}\``);

const irlResolver = new IrlResolver({ customNetworks: [{ chainId: network, endpoint: NETWORK_URL }] });
const resolvedJwtVp = await irlResolver.resolve(vpUrl).then(value => new Jwt(value as string));

// Validate presentation. Note that this doesn't validate the included credentials.
const _decodedPresentation = new JwtPresentationValidator(new EdDSAJwsVerifier()).validate(
resolvedJwtVp,
resolvedHolder,
new JwtPresentationValidationOptions(),
);

console.log("Successfully validated the fetched presentation");
}

async function makeVpJwt(didDocument: IotaDocument, storage: Storage, fragment: string): Promise<Jwt> {
const credential = new Credential({
id: "https://example.edu/credentials/3732",
type: "UniversityDegreeCredential",
issuer: didDocument.id(),
credentialSubject: {
id: didDocument.id(),
name: "Alice",
degreeName: "Bachelor of Science and Arts",
degreeType: "BachelorDegree",
GPA: "4.0",
},
});
const jwtCredential = await didDocument.createCredentialJwt(
storage,
fragment,
credential,
new JwsSignatureOptions(),
);

const presentation = new Presentation({
holder: didDocument.id(),
verifiableCredential: [jwtCredential],
});
const jwtVp = await didDocument.createPresentationJwt(
storage,
fragment,
presentation,
new JwsSignatureOptions(),
new JwtPresentationOptions(),
);

return jwtVp;
}
47 changes: 47 additions & 0 deletions bindings/wasm/identity_wasm/examples/src/1_advanced/8_zkp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,53 @@ import {
import { IotaClient } from "@iota/iota-sdk/client";
import { getFundedClient, getMemstorage, IOTA_IDENTITY_PKG_ID, NETWORK_URL } from "../util";

/** Creates a DID Document and publishes it in a new Alias Output.

Its functionality is equivalent to the "create DID" example
and exists for convenient calling from the other examples. */
export async function createDid(client: Client, secretManager: SecretManagerType, storage: Storage): Promise<{
address: Address;
document: IotaDocument;
fragment: string;
}> {
const didClient = new IotaIdentityClient(client);
const networkHrp: string = await didClient.getNetworkHrp();

const secretManagerInstance = new SecretManager(secretManager);
const walletAddressBech32 = (await secretManagerInstance.generateEd25519Addresses({
accountIndex: 0,
range: {
start: 0,
end: 1,
},
bech32Hrp: networkHrp,
}))[0];

console.log("Wallet address Bech32:", walletAddressBech32);

await ensureAddressHasFunds(client, walletAddressBech32);

const address: Address = Utils.parseBech32Address(walletAddressBech32);

// Create a new DID document with a placeholder DID.
// The DID will be derived from the Alias Id of the Alias Output after publishing.
const document = new IotaDocument(networkHrp);

const fragment = await document.generateMethodJwp(
storage,
ProofAlgorithm.BBS,
undefined,
MethodScope.VerificationMethod(),
);
// Construct an Alias Output containing the DID document, with the wallet address
// set as both the state controller and governor.
const aliasOutput: AliasOutput = await didClient.newDidOutput(address, document);

// Publish the Alias Output and get the published DID document.
const published = await didClient.publishDidOutput(secretManager, aliasOutput);

return { address, document: published, fragment };
}
export async function zkp() {
// ===========================================================================
// Step 1: Create identity for the issuer.
Expand Down
Loading