DIDKit(Node)でVerifiable Credentialsの発行と署名をやってみる
DIDKitを使ってローカル環境でVCの発行と検証を試してみます。
やること
- DIDKitのビルド
- DIDKitを使ってVCの発行
- DIDKitを使ってVCの検証
やらないこと
- DIDKitの説明
- Verifiable Credentialsの説明
環境用意
DIDKitのnpmパッケージがあるのですが、バージョンが古い(0.2.1)ので手元でビルドしたものを今回は使います。
使うバージョンはTagがついてないのですが、
のcommitが反映されているバージョンを使います。git clone
でソースを落としてきます。
git clone git@github.com:spruceid/didkit.git
DIDKitのリポジトリの他にspruceid/ssi
のリポジトリも必要なので落としてきます。
参考: https://github.com/spruceid/didkit#manual
git clone https://github.com/spruceid/ssi --recurse-submodules
Node用にビルドします。
参考: https://github.com/spruceid/didkit/tree/main/lib/web#readme
今回はRustの環境はDockerコンテナで用意します。
Dockerfileとdocker-compose.ymlを作成してwasm-pack build
します。
FROM rust
WORKDIR /myapp
RUN rustup target add wasm32-unknown-unknown
RUN cargo install wasm-pack
version: '3'
services:
app:
build: .
volumes:
- .:/myapp
docker-compose run --rm app wasm-pack build didkit/lib/web --target nodejs --out-dir /myapp/didkit-wasm-node
これでDIDKitのNodeパッケージが生成されて、ディレクトリとしては以下の状態になっています。
VCの発行
JWK生成
最初にJWKファイルを生成しておきます。
const DIDKit = require("./didkit-wasm-node");
const fs = require("fs");
async function main() {
generateKey()
}
function generateKey() {
const key = DIDKit.generateEd25519Key()
fs.writeFileSync("issuer_key.jwk", key)
}
main().then((res) => {
}).catch((err) => {
console.log("err", err)
})
node index.js
以下のような、JWKが生成されます。
{"kty":"OKP","crv":"Ed25519","x":"52_9TqZnoF9CC-QjMh1RoVMg4hQNC4rvvvJi0dNNhBE","d":"qP8nGCOrYJ4J4mTzcA--oM8iTPzV_cImhEiR1Zy3f3k"}
VC署名
署名前のVCのJSONを用意した後に、issuer_key.jwk
で署名します。
参考: https://www.spruceid.dev/quickstart
const DIDKit = require("./didkit-wasm-node");
const fs = require("fs");
const crypto = require("crypto")
async function main() {
// generateKey()
const key = fs.readFileSync("issuer_key.jwk").toString()
const issuerDid = DIDKit.keyToDID("key", key)
const unsignedVc = {
"@context": "https://www.w3.org/2018/credentials/v1",
"id": `urn:uuid:${crypto.randomUUID()}`,
"type": ["VerifiableCredential"],
"issuer": issuerDid,
"issuanceDate": "2023-01-08T18:23:56Z",
"credentialSubject": {
"id": "did:example:my-data-subject-identifier"
}
}
const proofOptions = {};
const signedVc = await DIDKit.issueCredential(
JSON.stringify(unsignedVc),
JSON.stringify(proofOptions),
key
)
fs.writeFileSync("signed-vc.json", signedVc)
}
function generateKey() {
const key = DIDKit.generateEd25519Key()
fs.writeFileSync("issuer_key.jwk", key)
}
main().then((res) => {
}).catch((err) => {
console.log("err", err)
})
以下のようなjsonファイルが出力されます。
これでVCの発行に成功しました。
{
"@context": "https://www.w3.org/2018/credentials/v1",
"id": "urn:uuid:86a109aa-a3f6-4374-b46f-92c58fcb16a1",
"type": [
"VerifiableCredential"
],
"credentialSubject": {
"id": "did:example:my-data-subject-identifier"
},
"issuer": "did:key:z6Mkv2hGUtUdKdEVdqc7esowafyriuqPvxQFnVTrRqjMknj2",
"issuanceDate": "2023-01-08T18:23:56Z",
"proof": {
"type": "Ed25519Signature2018",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:key:z6Mkv2hGUtUdKdEVdqc7esowafyriuqPvxQFnVTrRqjMknj2#z6Mkv2hGUtUdKdEVdqc7esowafyriuqPvxQFnVTrRqjMknj2",
"created": "2023-01-08T07:43:50.818Z",
"jws": "eyJhbGciOiJFZERTQSIsImNyaXQiOlsiYjY0Il0sImI2NCI6ZmFsc2V9..jyR9O8nb-ino0TXSCAhUdP2Z9iBc0E-aX7tyTHcFuOzOGd_uWpwHhA4gTOX961SUHB0un34e2YV41qc2lk0nCw"
}
}
VCの検証
先程生成したsigned-vc.json
を検証します。
const DIDKit = require("./didkit-wasm-node");
const fs = require("fs");
async function main() {
const signedVc = fs.readFileSync("signed-vc.json").toString()
const proofOptions = {};
const result = await DIDKit.verifyCredential(
signedVc,
JSON.stringify(proofOptions)
)
console.log("result", result)
}
main().then((res) => {
}).catch((err) => {
console.log("err", err)
})
これで検証に成功しました。
hide@hidenoMacBook-Pro didkit_vc % node verify.js
result {"checks":["proof"],"warnings":[],"errors":[]}
試しに、signed-vc.json
を改ざんして検証をしてみます。
signed-vc.json
のissuanceDate
が2023-01-08だったのを2023-01-09に変更してみます。
"issuanceDate": "2023-01-08T18:23:56Z",
↓
"issuanceDate": "2023-01-09T18:23:56Z",
すると、以下のように検証に失敗することが確認できました。
hide@hidenoMacBook-Pro didkit_vc % node verify.js
result {"checks":["proof"],"warnings":[],"errors":["signature error: Verification equation was not satisfied"]}
Discussion