-
Notifications
You must be signed in to change notification settings - Fork 82
/
merkle_key.js
96 lines (81 loc) · 3.93 KB
/
merkle_key.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright 2020-2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
import {
Client,
Config,
Digest,
KeyType,
Timestamp,
VerifiableCredential,
VerificationMethod,
KeyCollection
} from '@iota/identity-wasm';
import {createIdentity} from './create_did';
import {logExplorerUrl} from './utils';
/**
This example shows how to sign/revoke verifiable credentials on scale.
Instead of revoking the entire verification method, a single key can be revoked from a MerkleKeyCollection.
This MerkleKeyCollection can be created as a collection of a power of 2 amount of keys.
Every key should be used once by the issuer for signing a verifiable credential.
When the verifiable credential must be revoked, the issuer revokes the index of the revoked key.
@param {{defaultNodeURL: string, explorerURL: string, network: Network}} clientConfig
**/
async function merkleKey(clientConfig) {
// Create a default client configuration from the parent config network.
const config = Config.fromNetwork(clientConfig.network);
// Create a client instance to publish messages to the Tangle.
const client = Client.fromConfig(config);
// Creates new identities (See "create_did" example)
const alice = await createIdentity(clientConfig);
const issuer = await createIdentity(clientConfig);
// Add a Merkle Key Collection Verification Method with 8 keys (Must be a power of 2)
const keys = new KeyCollection(KeyType.Ed25519, 8);
const method = VerificationMethod.createMerkleKey(Digest.Sha256, issuer.doc.id, keys, "key-collection")
// Add to the DID Document as a general-purpose verification method
issuer.doc.insertMethod(method, "VerificationMethod");
issuer.doc.previousMessageId = issuer.receipt.messageId;
issuer.doc.updated = Timestamp.nowUTC();
issuer.doc.sign(issuer.key);
// Publish the Identity to the IOTA Network and log the results.
// This may take a few seconds to complete proof-of-work.
const receipt = await client.publishDocument(issuer.doc.toJSON());
logExplorerUrl("Identity Update:", clientConfig.network.toString(), receipt.messageId);
// Prepare a credential subject indicating the degree earned by Alice
let credentialSubject = {
id: alice.doc.id.toString(),
name: "Alice",
degreeName: "Bachelor of Science and Arts",
degreeType: "BachelorDegree",
GPA: "4.0"
};
// Create an unsigned `UniversityDegree` credential for Alice
const unsignedVc = VerifiableCredential.extend({
id: "http://example.edu/credentials/3732",
type: "UniversityDegreeCredential",
issuer: issuer.doc.id.toString(),
credentialSubject,
});
// Sign the credential with Issuer's Merkle Key Collection method, with key index 0
const signedVc = issuer.doc.signCredential(unsignedVc, {
method: method.id.toString(),
public: keys.public(0),
private: keys.private(0),
proof: keys.merkleProof(Digest.Sha256, 0)
});
// Check the verifiable credential is valid
const result = await client.checkCredential(signedVc.toString());
console.log(`VC verification result: ${result.verified}`);
if (!result.verified) throw new Error("VC not valid");
// The Issuer would like to revoke the credential (and therefore revokes key 0)
issuer.doc.revokeMerkleKey(method.id.toString(), 0);
issuer.doc.previousMessageId = receipt.messageId;
issuer.doc.updated = Timestamp.nowUTC();
issuer.doc.sign(issuer.key);
const nextReceipt = await client.publishDocument(issuer.doc.toJSON());
logExplorerUrl("Identity Update:", clientConfig.network.toString(), nextReceipt.messageId);
// Check the verifiable credential is revoked
const newResult = await client.checkCredential(signedVc.toString());
console.log(`VC verification result (false = revoked): ${newResult.verified}`);
if (newResult.verified) throw new Error("VC not revoked");
}
export {merkleKey};