https://github.com/zcloak-network/zkid-sdk-example
Demo for how to use our zkid-sdk.
https://github.com/zcloak-network/zkid-sdk-example
Last synced: 3 months ago
JSON representation
Demo for how to use our zkid-sdk.
- Host: GitHub
- URL: https://github.com/zcloak-network/zkid-sdk-example
- Owner: zCloak-Network
- Created: 2023-03-21T06:59:15.000Z (about 2 years ago)
- Default Branch: sdk-v2
- Last Pushed: 2024-01-25T02:49:50.000Z (over 1 year ago)
- Last Synced: 2024-01-25T03:41:25.756Z (over 1 year ago)
- Language: TypeScript
- Homepage:
- Size: 7.45 MB
- Stars: 3
- Watchers: 2
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README-zh.md
Awesome Lists containing this project
README
# Zkid-SDK 使用说明
Hi👋,各位开发者🧑💻,本教程将向你展示如何使用 SDK来完成 credential分发的 **request模式**(claimer发起 attestation请求,attester批准或拒绝请求)与 **issue模式**(attester 直接向指定 claimer发送 VC)。
各位Attester🧑🏻⚖️,准备好了么?🚀 让我们出发吧!!!
⚠️ 最新的代码分支为 **sdk-v2**,请确保您的服务是基于 **sdk-v2**分支进行开发。
## 快速使用
请确保使用最新兼容版本,您可以使用 `npm update` 命令来升级依赖。
```bash
git clone https://github.com/zCloak-Network/zkid-sdk-example.git
cd zkid-sdk-example/
npm installnpm run create-did
npm run ctype
npm run claim
npm run attest
npm run multiAttest
npm run issue
npm run vp-send
npm run vp-send-verify
npm run zkp
```## ⚠️ Issue Verifiable Credential ⚠️
如果您的需求只是使用 SDK向用户直接发送 VC(即 issue模式),那么您只需参考 `/src/issue/issue.ts`文件。## 使用向导
### Demo文件说明
所有 Demo文件位于 `src/`文件夹中,以下将根据文件夹的归类来分别介绍几个主要功能模块。**claim-attest**
在 claim-attest文件夹下,包含了 claim.ts脚本与 attest.ts脚本,二者用于展示签发 VC的 request模式,即 claimer发起 attestation请求,attester批准/拒绝请求,attester批准请求后签发 VC。**issue**
在 issue文件夹下,只包含一个 issue.ts脚本文件,该文件用于展示签发 VC的 issue模式,即 attester直接向指定用户签发一个 VC,用户不需要提前请求。**ctype**
在 ctype文件夹中,只包含一个 createCtype.ts脚本文件,该文件用于展示如何创建一个 ctype。建议各位开发者使用 [card center 平台](https://card.zkid.app/#/)创建 ctype。Card Maker => Create New Template,其中 Template 为 CType 的上层结构体,创建 Template 后,Data Field Hash 即为 ctype hash。### 📨 Issue Credential API Tutorial
🤓 在 issue模式的教程中,我们将以 `src/issue/issue.ts`文件为基础,详细介绍一下如何使用 API来 Issue Credential。
**前置条件**
```typescript
await initCrypto();
```
在前置步骤中,我们需要对密码学库进行初始化操作:
调用 `initCrypto()`接口,初始化 @noble密码学库与 wasm,此步骤为必需,因为我们的 API基于此开发。
1. 生成 resolver,resolver指定了具体的环境,其中 `server`为正式环境或者测试环境的 URL,通过 resolver,可以解析 DID或者通过给定的 DID URL来获取对应的 DID Document。**Step 0: 根据 claimer DID URL 获取其 DID对象**
```typescript
const holderDidDoc = await resolver.resolve(holderDidUrl);
const holder = fromDidDocument(holderDidDoc);const keyring = new Keyring();
const json = readDidKeysFile();
const password = "12345678"; // password to decrypt your DID-keys-file
const attester = restore(keyring, json, password);// src/utils/resolverHelper.ts
export const resolver = new ArweaveDidResolver();// src/utils/didHelper.ts
export function readDidKeysFile() {
const attesterKeysFile = fs.readFileSync(
path.resolve(__dirname, "../../attester-DID-keys-file.json"),
{ encoding: "utf-8" }
);
return JSON.parse(attesterKeysFile) as DidKeys$Json;
}```
在本步骤中,我们用到以下API,
1. `fromDidDocument(document: DidDocument, keyring?: KeyringInstance)`该 API可通过 DID Document恢复 DID,其中 Document的获取通过调用接口 `resoler.resolve(didUrl: string)`。注意⚠️:resolver可以作为某些 API的参数,对于这类 API,开发者应当在使用中明确指定 resolver,特别是当您在我们的开发环境中进行测试时。这是因为我们的 resolver默认连接生产环境,如果您没有指定 resolver,则可能会出现 DID Method找不到等情况;
2. `restore(keyring: Keyring, json: DidKeys$Json, password: string)`该 API旨在通过 DID-keys-file来恢复 DID,需要注意一点:password参数为创建 DID时的密码,正确的使用该密码才可以解密 DID-keys-file并恢复 DID。除了使用上述方法恢复 DID外,我们还提供了通过助记词来恢复 DID,具体接口为:`fromMnemonic(keyring: KeyringInstance, mnemonic: string, signingKeyType?: 'ecdsa' | 'ed25519', index?: number)`。
```typescript
import { keys } from "@zcloak/did";
import { Keyring } from "@zcloak/keyring";const keyring = new Keyring();
const mnemonic = 'xxx';
const attester = keys.fromMnemonic(keyring, mnemonic, "ecdsa");
```**Step 1: 根据 cType hash值获取 CType对象**
```typescript
const ctype: CType = await getCtypeFromHash(ctypeHash);// src/utils/ctypeHelper.ts
export async function getCtypeFromHash(
hash: string | undefined,
url = process.env.BASE_URL
): Promise {
if (hash === undefined) {
throw new Error("ctype hash undefined !!!");
}const res = await axios.get(`${url}/ctype?${qs.stringify({ id: hash })}`);
if (res.status !== 200) {
throw new Error(`ctype query failed ${hash}`);
}
const ctype: CType = res.data.data.rawData;
return ctype;
}
```
在本步骤中,我们使用 axios方法向我们的 RESTful API发起 GET请求,将ctype hash作为查询参数请求 ctype对象。**Step 2: 构建 Raw对象**
```typescript
const raw = new Raw({
contents: {
id: 9870456,
name: "vss-claimer",
},
owner: holderDidUrl,
ctype: ctype,
hashType: "Keccak256",
});
```
在本步骤中,我们构建了一个 Raw对象,该对象用于后续构建 RawCredential使用。下面解释一下各个参数:
- contents: 对应 ctype构建时要求用户填入的字段
- owner: claimer,接收该 credential的用户
- ctype: 对应的 ctype对象
- hashType: 加密算法类型,此处选择 Keccak256(我们还支持 Blake2、Blake3、RescuePrimeOptimized等加密算法。注意:考虑到 Keccak256的哈希效率在链上最高,因此如果您的 vc使用场景不包括 zk计算,那么建议使用 Keccak256作为构建 Raw时的哈希,否则使用 RescuePrimeOptimized哈希。)**Step 3: 构建 Raw Credential**
```typescript
const rawCredential: RawCredential = raw.toRawCredential("Keccak256");
```
在这一步中,我们基于上一步生成的 Raw对象,调用 `toRawCredential(digestHashType?: HashType)`接口生成 Raw Credential,这一步用到的加密算法默认为 Keccak256(同时我们还支持其他加密算法,与构建 Raw时可用的加密算法一致)。**Step 4: 构建 vcBuilder**
```typescript
const vcBuilder = VerifiableCredentialBuilder.fromRawCredential(
rawCredential,
ctype
)
.setExpirationDate(null)
.setIssuanceDate(Date.now());
```
在该步骤中,我们构建了一个 vcBuilder对象,后续的 VC可由该 vcBuilder构建。vcBuilder 提供多个方法,对于一般通用型的 VC,一般设置其为永不过期,签发时间设置为当前时间。**Step 5: 构建 VC**
```typescript
const vc: VerifiableCredential = await vcBuilder.build(
attester,
false
);
```
在该步骤中,我们通过 vcBuilder的 `build(issuer: Did, isPublic?: false)`接口成功的构建了 VC。
该接口的两个参数需要说明一下:
- issuer: 一个 DID对象,这里的角色为 issuer,即签发人,一般指某个 attester;
- isPublic: 当该参数为 `false`时,生成的 VC为 private VC,如果为 `true`则生成 public VC,如果此参数指定为 `false`,则生成的 VC类型为 `VerifiableCredential`;一般意义上的 VC均为 private VC,因此默认的VC均指 private VC,考虑到日后某些 VC可以公开,因此我们也设计了可公开的 public VC。**Step 6: 构建加密 message**
```typescript
const message = await encryptMessage(
"Send_issuedVC",
vc,
attester,
holder.getKeyUrl("keyAgreement"),
undefined,
resolver
);
```
在该步骤中,我们使用 `encryptMessage(type: T, data: MessageData[T], sender: IDidKeyring, receiverUrl: DidUrl, reply?: string, resolver?: DidResolver)`接口生成加密信息,其中在 issue credential过程中会用到以下几个参数:
- type: 消息类型,issue 对应的消息类型为 “Send_issuedVC”;
- MessageData: 消息数据,这里指VC;
- sender: issuer,或者前面构建的 attester;
- receiverUrl: 用户 DID对应的 keyAgreement类型的 key,该 key在此处用于加密 MessageData;
- resolver: 环境 DID resolver**Step 7: 发送加密后的 message至服务器**
```typescript
await sendMessage2Server(message);// src/utils/messageHelper.ts
export async function sendMessage2Server(
message: any,
templateId = -1,
token = null,
url = process.env.BASE_URL
): Promise {
const sendRes = await axios.post(`${url}/message`, {
templateId,
msg: message,
token,
});
if (sendRes.status === 200) {
console.log(`SUCCESS: send encrypted message to server`);
} else {
console.log(`send encrypted message response status: ${sendRes.status}`);
}
}
```
在该步骤中,我们通过 axios向服务器发送加密后的消息,我们的后端服务在接收到该加密消息后会将消息推送到 card center平台。
使用该加密通信方式是为了保护用户的 VC隐私,所有经过 zCloak服务器的内容均为加密后的信息;对于发送 VC的情景,只有 claimer (即用户自己)才能解密该 message,zCloak 只做中间邮递人。