spruceid/tzprofiles

Issue profile with TezosSignature2021

clehner opened this issue · 1 comments

Use TezosSignature2021 (spruceid/ssi#170) for profile credential proof.

Other changes:

  • Use IRI for CoreProfile term.
  • Verify credential after issuing it, as a sanity check.
  • Output VC to console.

Patch

Applies to 7fd3712

From ebed3b31f83267ed01c1e88e284530f5d4c85330 Mon Sep 17 00:00:00 2001
From: "Charles E. Lehner" <charles.lehner@spruceid.com>
Date: Fri, 16 Apr 2021 17:41:29 -0400
Subject: [PATCH] Sign profile credential with TezosMethod2021

---
 dapp/src/core_profile.ts | 47 +++++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/dapp/src/core_profile.ts b/dapp/src/core_profile.ts
index 7a21ec1..0ab7e35 100644
--- a/dapp/src/core_profile.ts
+++ b/dapp/src/core_profile.ts
@@ -1,6 +1,7 @@
 import { v4 as uuid } from 'uuid';
 import { alert, dappUrl } from 'src/store';
 import { signClaim } from 'src/utils';
+import { RequestSignPayloadInput, SigningType } from '@airgap/beacon-sdk';
 
 export const signCoreProfile = async (userData, wallet, networkStr, DIDKit, profile) => {
   try {
@@ -12,7 +13,8 @@ export const signCoreProfile = async (userData, wallet, networkStr, DIDKit, prof
         {
           name: 'https://schema.org/name',
           description: 'https://schema.org/description',
-          logo: 'https://schema.org/logo'
+          logo: 'https://schema.org/logo',
+          CoreProfile: 'https://tzprofiles.me/CoreProfile'
         }
       ],
       id: 'urn:uuid:' + uuid(),
@@ -29,31 +31,30 @@ export const signCoreProfile = async (userData, wallet, networkStr, DIDKit, prof
 
     let credentialString = JSON.stringify(credential);
     const proofOptions = {
-      verificationMethod: did + '#blockchainAccountId',
+      verificationMethod: did + '#TezosMethod2021',
       proofPurpose: 'assertionMethod',
     };
 
-    const keyType = {
-      kty: 'OKP',
-      crv: 'Ed25519',
-      x: 'Y-JndzKMXwcbIY9h0snDhFQZG0Weci9zfXHgeZTaMjo',
-      d: 'tJ3uEI9_ymV3Yxk77ZKGcSOFO06j379ql8ZXJEuh6eM',
-    };
-
+    const publicKey = userData.account.publicKey;
+    const publicKeyJwkString = await DIDKit.JWKFromTezos(publicKey);
     let prepStr = await DIDKit.prepareIssueCredential(
       credentialString,
       JSON.stringify(proofOptions),
-      JSON.stringify(keyType)
+      publicKeyJwkString
     );
+    const preparation = JSON.parse(prepStr);
+    const {signingInput} = preparation;
+    const micheline = signingInput && signingInput.micheline;
+    if (!micheline) {
+      throw new Error('Expected micheline signing input');
+    }
 
-    const fmtInput = [
-      'Tezos Signed Message: ',
-      dappUrl,
-      new Date().toISOString(),
-      prepStr,
-    ].join(' ');
-
-    const signature = await signClaim(userData, fmtInput, wallet);
+    const payload: RequestSignPayloadInput = {
+      signingType: SigningType.MICHELINE,
+      payload: micheline,
+      sourceAddress: userData.account.address,
+    };
+    const { signature } = await wallet.client.requestSignPayload(payload);
 
     let vcStr = await DIDKit.completeIssueCredential(
       credentialString,
@@ -61,6 +62,16 @@ export const signCoreProfile = async (userData, wallet, networkStr, DIDKit, prof
       signature
     );
 
+    const verifyOptionsString = '{}';
+    const verifyResult = JSON.parse(await DIDKit.verifyCredential(
+      vcStr,
+      verifyOptionsString
+    ));
+    if (verifyResult.errors.length > 0) {
+      throw new Error("Unable to verify credential: " + verifyResult);
+    }
+
+    console.log(vcStr);
     return vcStr;
   } catch (e) {
     alert.set({
-- 
2.30.2

Example

Profile credential signing request

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    {
      "logo": "https://schema.org/logo",
      "CoreProfile": "https://tzprofiles.me/CoreProfile",
      "name": "https://schema.org/name",
      "description": "https://schema.org/description"
    }
  ],
  "id": "urn:uuid:5fdb183c-5104-4412-a401-589fa17afe0e",
  "type": [
    "VerifiableCredential",
    "CoreProfile"
  ],
  "credentialSubject": {
    "id": "did:pkh:tz:tz1TwZZZSShtM73oEr74aDtDcns3UmFqaca6",
    "name": "asddasasd",
    "logo": "daadsdasdasddadasasddasads",
    "description": "dasadsadsadsasddas"
  },
  "issuer": "did:pkh:tz:tz1TwZZZSShtM73oEr74aDtDcns3UmFqaca6",
  "issuanceDate": "2021-04-16T21:50:04.926Z",
  "proof": {
    "@context": {
      "TezosMethod2021": "https://w3id.org/security#TezosMethod2021",
      "TezosSignature2021": {
        "@context": {
          "@protected": true,
          "@version": 1.1,
          "challenge": "https://w3id.org/security#challenge",
          "created": {
            "@id": "http://purl.org/dc/terms/created",
            "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
          },
          "domain": "https://w3id.org/security#domain",
          "expires": {
            "@id": "https://w3id.org/security#expiration",
            "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
          },
          "id": "@id",
          "nonce": "https://w3id.org/security#nonce",
          "proofPurpose": {
            "@context": {
              "@protected": true,
              "@version": 1.1,
              "assertionMethod": {
                "@container": "@set",
                "@id": "https://w3id.org/security#assertionMethod",
                "@type": "@id"
              },
              "authentication": {
                "@container": "@set",
                "@id": "https://w3id.org/security#authenticationMethod",
                "@type": "@id"
              },
              "id": "@id",
              "type": "@type"
            },
            "@id": "https://w3id.org/security#proofPurpose",
            "@type": "@vocab"
          },
          "proofValue": "https://w3id.org/security#proofValue",
          "publicKeyJwk": {
            "@id": "https://w3id.org/security#publicKeyJwk",
            "@type": "@json"
          },
          "type": "@type",
          "verificationMethod": {
            "@id": "https://w3id.org/security#verificationMethod",
            "@type": "@id"
          }
        },
        "@id": "https://w3id.org/security#TezosSignature2021"
      }
    },
    "type": "TezosSignature2021",
    "proofPurpose": "assertionMethod",
    "proofValue": "edsigtvAYxTbboKeM3PbgeH48diZk4DUwV7bCSHiNcurAUBrxZE9wpMowrREvMHJhv1SYQ6ckpFGCCCXhuf2D3QqfQnnqJzkpAg",
    "verificationMethod": "did:pkh:tz:tz1TwZZZSShtM73oEr74aDtDcns3UmFqaca6#TezosMethod2021",
    "created": "2021-04-16T21:50:04.932Z",
    "publicKeyJwk": {
      "alg": "EdDSA",
      "crv": "Ed25519",
      "kty": "OKP",
      "x": "rVEB0Icbomw1Ir-ck52iCZl1SICc5lCg2pxI8AmydDw"
    }
  }
}

Applied in #3 (comment)