Skip to content

Commit

Permalink
Export EdDSAJwsVerifier & add verifyEd25519
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippGackstatter committed Sep 20, 2023
1 parent b4bf485 commit 8d6cf18
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 32 deletions.
3 changes: 2 additions & 1 deletion bindings/wasm/examples/src/0_basic/5_create_vc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import {
Credential,
EdDSAJwsVerifier,
FailFast,
JwkMemStore,
JwsSignatureOptions,
Expand All @@ -12,7 +13,7 @@ import {
Storage,
} from "@iota/identity-wasm/node";
import { Client, MnemonicSecretManager, Utils } from "@iota/sdk-wasm/node";
import { API_ENDPOINT, createDid, EdDSAJwsVerifier } from "../util";
import { API_ENDPOINT, createDid } from "../util";

/**
* This example shows how to create a Verifiable Credential and validate it.
Expand Down
3 changes: 2 additions & 1 deletion bindings/wasm/examples/src/0_basic/6_create_vp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CoreDID,
Credential,
Duration,
EdDSAJwsVerifier,
FailFast,
IotaIdentityClient,
JwkMemStore,
Expand All @@ -24,7 +25,7 @@ import {
Timestamp,
} from "@iota/identity-wasm/node";
import { Client, MnemonicSecretManager, Utils } from "@iota/sdk-wasm/node";
import { API_ENDPOINT, createDid, EdDSAJwsVerifier } from "../util";
import { API_ENDPOINT, createDid } from "../util";

/**
* This example shows how to create a Verifiable Presentation and validate it.
Expand Down
22 changes: 20 additions & 2 deletions bindings/wasm/examples/src/0_basic/7_revoke_vc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@

import {
Credential,
EdCurve,
FailFast,
IJwsVerifier,
IotaDocument,
IotaIdentityClient,
Jwk,
JwkMemStore,
JwsAlgorithm,
JwsSignatureOptions,
JwtCredentialValidationOptions,
JwtCredentialValidator,
Expand All @@ -16,9 +20,10 @@ import {
Service,
Storage,
VerificationMethod,
verifyEd25519,
} from "@iota/identity-wasm/node";
import { AliasOutput, Client, IRent, MnemonicSecretManager, Utils } from "@iota/sdk-wasm/node";
import { API_ENDPOINT, createDid, EdDSAJwsVerifier } from "../util";
import { API_ENDPOINT, createDid } from "../util";

/**
* This example shows how to revoke a verifiable credential.
Expand Down Expand Up @@ -134,7 +139,7 @@ export async function revokeVC() {
console.log(`Credential JWT > ${credentialJwt.toString()}`);

// Validate the credential using the issuer's DID Document.
let jwtCredentialValidator = new JwtCredentialValidator(new EdDSAJwsVerifier());
let jwtCredentialValidator = new JwtCredentialValidator(new Ed25519JwsVerifier());
jwtCredentialValidator.validate(
credentialJwt,
issuerDocument,
Expand Down Expand Up @@ -225,3 +230,16 @@ export async function revokeVC() {
console.log(`Credential successfully revoked!`);
}
}

// A custom JWS Verifier capabale of verifying EdDSA signatures with curve Ed25519.
class Ed25519JwsVerifier implements IJwsVerifier {
verify(alg: JwsAlgorithm, signingInput: Uint8Array, decodedSignature: Uint8Array, publicKey: Jwk) {
switch (alg) {
case JwsAlgorithm.EdDSA:
// This verifies that the curve is Ed25519 so we don't need to check ourselves.
return verifyEd25519(alg, signingInput, decodedSignature, publicKey);
default:
throw new Error(`unsupported jws algorithm ${alg}`);
}
}
}
3 changes: 2 additions & 1 deletion bindings/wasm/examples/src/1_advanced/5_domain_linkage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
DIDUrl,
DomainLinkageConfiguration,
Duration,
EdDSAJwsVerifier,
IotaDID,
IotaDocument,
IotaIdentityClient,
Expand All @@ -20,7 +21,7 @@ import {
Timestamp,
} from "@iota/identity-wasm/node";
import { AliasOutput, Client, IRent, MnemonicSecretManager, Utils } from "@iota/sdk-wasm/node";
import { API_ENDPOINT, createDid, EdDSAJwsVerifier } from "../util";
import { API_ENDPOINT, createDid } from "../util";

/**
* Demonstrates how to link a domain and a DID and verify the linkage.
Expand Down
15 changes: 0 additions & 15 deletions bindings/wasm/examples/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import {
IJwsVerifier,
IotaDocument,
IotaIdentityClient,
Jwk,
JwkMemStore,
JwsAlgorithm,
MethodScope,
Storage,
verifyEdDSA,
} from "@iota/identity-wasm/node";
import {
type Address,
Expand All @@ -22,18 +19,6 @@ import {
export const API_ENDPOINT = "http://localhost:14265";
export const FAUCET_ENDPOINT = "http://localhost:8091/api/enqueue";

// A JWS Verifier capabale of verifying EdDSA signatures with curve Ed25519.
export class EdDSAJwsVerifier implements IJwsVerifier {
verify(alg: JwsAlgorithm, signingInput: Uint8Array, decodedSignature: Uint8Array, publicKey: Jwk) {
switch (alg) {
case JwsAlgorithm.EdDSA:
return verifyEdDSA(alg, signingInput, decodedSignature, publicKey);
default:
throw new Error(`unsupported jws algorithm ${alg}`);
}
}
}

/** Creates a DID Document and publishes it in a new Alias Output.
Its functionality is equivalent to the "create DID" example
Expand Down
58 changes: 51 additions & 7 deletions bindings/wasm/src/verification/jws_verifier.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2020-2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use identity_eddsa_verifier::Ed25519Verifier;
use identity_eddsa_verifier::EdDSAJwsVerifier;
use identity_iota::verification::jws::JwsAlgorithm;
use identity_iota::verification::jws::JwsVerifier;
Expand All @@ -11,18 +12,18 @@ use crate::error::WasmResult;
use crate::jose::WasmJwk;
use crate::jose::WasmJwsAlgorithm;

/// Verify a JWS signature secured with the `JwsAlgorithm::EdDSA` algorithm.
/// Only the `EdCurve::Ed25519` variant is supported for now.
/// Verify a JWS signature secured with the `EdDSA` algorithm and curve `Ed25519`.
///
/// This function is useful when one is building an `IJwsVerifier` that extends the default provided by
/// the IOTA Identity Framework.
/// This function is useful when one is composing a {@link IJwsVerifier} that delegates
/// `EdDSA` verification with curve `Ed25519` to this function.
///
/// # Warning
///
/// This function does not check whether `alg = EdDSA` in the protected header. Callers are expected to assert this
/// prior to calling the function.
#[wasm_bindgen(js_name = verifyEdDSA)]
#[wasm_bindgen(js_name = verifyEd25519)]
#[allow(non_snake_case)]
pub fn verify_eddsa(
pub fn verify_ed25519(
alg: WasmJwsAlgorithm,
signingInput: &[u8],
decodedSignature: &[u8],
Expand All @@ -34,5 +35,48 @@ pub fn verify_eddsa(
signing_input: Box::from(signingInput),
decoded_signature: Box::from(decodedSignature),
};
EdDSAJwsVerifier::default().verify(input, &publicKey.0).wasm_result()
Ed25519Verifier::verify(input, &publicKey.0).wasm_result()
}

/// An implementor of {@link IJwsVerifier} that can handle the
/// `EdDSA` algorithm.
#[wasm_bindgen(js_name = EdDSAJwsVerifier)]
pub struct WasmEdDSAJwsVerifier();

#[wasm_bindgen(js_class = EdDSAJwsVerifier)]
#[allow(clippy::new_without_default)]
impl WasmEdDSAJwsVerifier {
/// Constructs an EdDSAJwsVerifier.
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self()
}

/// Verify a JWS signature secured with the `EdDSA` algorithm.
/// Only the `Ed25519` curve is supported for now.
///
/// This function is useful when one is building an `IJwsVerifier` that extends the default provided by
/// the IOTA Identity Framework.
///
/// # Warning
///
/// This function does not check whether `alg = EdDSA` in the protected header. Callers are expected to assert this
/// prior to calling the function.
#[wasm_bindgen]
#[allow(non_snake_case)]
pub fn verify(
&self,
alg: WasmJwsAlgorithm,
signingInput: &[u8],
decodedSignature: &[u8],
publicKey: &WasmJwk,
) -> Result<(), JsValue> {
let alg: JwsAlgorithm = JwsAlgorithm::try_from(alg)?;
let input: VerificationInput = VerificationInput {
alg,
signing_input: signingInput.into(),
decoded_signature: decodedSignature.into(),
};
EdDSAJwsVerifier::default().verify(input, &publicKey.0).wasm_result()
}
}
3 changes: 2 additions & 1 deletion bindings/wasm/tests/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as assert from "assert";
import {
CoreDocument,
Credential,
EdDSAJwsVerifier,
JwkMemStore,
JwsAlgorithm,
JwsSignatureOptions,
Expand Down Expand Up @@ -251,7 +252,7 @@ describe("Presentation", function() {
let issuer = JwtPresentationValidator.extractHolder(presentationJwt);
assert.deepStrictEqual(issuer.toString(), doc.id().toString());

const decodedPresentation = new JwtPresentationValidator().validate(
const decodedPresentation = new JwtPresentationValidator(new EdDSAJwsVerifier()).validate(
presentationJwt,
doc,
new JwtPresentationValidationOptions(),
Expand Down
9 changes: 5 additions & 4 deletions bindings/wasm/tests/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Credential,
DecodedJwtPresentation,
Duration,
EdDSAJwsVerifier,
FailFast,
IJwsVerifier,
IotaDocument,
Expand Down Expand Up @@ -95,7 +96,7 @@ describe("#JwkStorageDocument", function() {
);

// Verify the signature and obtain a decoded token.
const token = doc.verifyJws(jws, new JwsVerificationOptions());
const token = doc.verifyJws(jws, new JwsVerificationOptions(), new EdDSAJwsVerifier());
assert.deepStrictEqual(testString, token.claims());

// Check that we can also verify it using a custom verifier
Expand Down Expand Up @@ -138,7 +139,7 @@ describe("#JwkStorageDocument", function() {
);

// Check that the credentialJwt can be decoded and verified
let credentialValidator = new JwtCredentialValidator();
let credentialValidator = new JwtCredentialValidator(new EdDSAJwsVerifier());
const credentialRetrieved = credentialValidator
.validate(
credentialJwt,
Expand Down Expand Up @@ -206,7 +207,7 @@ describe("#JwkStorageDocument", function() {
);

// Verify the signature and obtain a decoded token.
const token = doc.verifyJws(jws, new JwsVerificationOptions());
const token = doc.verifyJws(jws, new JwsVerificationOptions(), new EdDSAJwsVerifier());
assert.deepStrictEqual(testString, token.claims());

// Check that we can also verify it using a custom verifier
Expand Down Expand Up @@ -248,7 +249,7 @@ describe("#JwkStorageDocument", function() {
);

// Check that the credentialJwt can be decoded and verified
let credentialValidator = new JwtCredentialValidator();
let credentialValidator = new JwtCredentialValidator(new EdDSAJwsVerifier());
const credentialRetrieved = credentialValidator
.validate(
credentialJwt,
Expand Down

0 comments on commit 8d6cf18

Please sign in to comment.