/veanpods

Verifiable and anonymous personal datastore supporting zk-SPARQL queries, based on VC/VP with BBS+ signatures and zero-knowledge proof

Primary LanguageTypeScriptMIT LicenseMIT

veanpods

WORK IN PROGRESS

Experimental: do not use in production

Verifiable and anonymous personal datastore supporting zk-SPARQL queries, based on Verifiable Credentials (VCs) and Verifiable Presentations (VPs) with BBS+ signatures.

zk-SPARQL

TODO

Examples

Assume that the datastore owner (VC Holder) have the following two VCs in their veanpods:

The first VC shows that a person, John Smith, got vaccinated on April 4th, 2022. The type of vaccine used here is identified by URI http://example.org/vaccine/987.

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://zkp-ld.org/bbs-termwise-2021.jsonld",
    "https://schema.org",
    {
      "Vaccination": "http://example.org/vocab/Vaccination",
      "isPatientOf": "http://example.org/vocab/isPatientOf",
      "lotNumber": "http://example.org/vocab/lotNumber",
      "vaccinationDate": {
        "@id": "http://example.org/vocab/vaccinationDate",
        "@type": "xsd:dateTime"
      },
      "vaccine": {
        "@id": "http://example.org/vocab/vaccine",
        "@type": "@id"
      }
    }
  ],
  "id": "http://example.org/vaccinationCredential/04",
  "type": "VerifiableCredential",
  "issuer": "did:example:issuer1",
  "issuanceDate": "2022-04-04T00:00:00Z",
  "expirationDate": "2025-04-04T00:00:00Z",
  "credentialSubject": {
    "id": "did:example:xyz",
    "type": "Person",
    "name": "John Smith",
    "isPatientOf": {
      "type": "Vaccination",
      "id": "http://example.org/vaccination/04",
      "vaccinationDate": "2022-04-04T00:00:00Z",
      "lotNumber": "1111111",
      "vaccine": "http://example.org/vaccine/987"
    }
  },
  "proof": {
    "@context": "https://zkp-ld.org/bbs-termwise-2021.jsonld",
    "type": "BbsTermwiseSignature2021",
    "created": "2023-02-03T09:46:55Z",
    "verificationMethod": "did:example:issuer1#bbs-bls-key1",
    "proofPurpose": "assertionMethod",
    "proofValue": "srl0BzpD2zCy9iV6beV82zU+F6WnBSFiL7uERojkUNS7K3D1HUNVLlwfAOVvruHIU5PX0qbq1fW7vEz2KjQz8V987tzyNCMBfBv/uJ9/ovQf1iLSF+l8qAwiHWoQcflsBWEB2oBljfaRAFAGnZg1NA=="
  }
}

The second VC gives us the details of the vaccine identified by http://example.org/vaccine/987, that is, its name, its manufacturer, and its approval status.

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://zkp-ld.org/bbs-termwise-2021.jsonld",
    "https://schema.org",
    {
      "Vaccine": "http://example.org/vocab/Vaccine"
    }
  ],
  "id": "http://example.org/vaccineInfoCredentials/987",
  "type": "VerifiableCredential",
  "issuer": "did:example:issuer2",
  "issuanceDate": "2020-01-01T00:00:00Z",
  "expirationDate": "2023-12-31T00:00:00Z",
  "credentialSubject": {
    "id": "http://example.org/vaccine/987",
    "type": "Vaccine",
    "name": "AwesomeVaccine",
    "manufacturer": {
      "id": "http://example.org/awesomeCompany"
    },
    "status": "active"
  },
  "proof": {
    "@context": "https://zkp-ld.org/bbs-termwise-2021.jsonld",
    "type": "BbsTermwiseSignature2021",
    "created": "2023-02-03T09:49:25Z",
    "verificationMethod": "did:example:issuer2#bbs-bls-key1",
    "proofPurpose": "assertionMethod",
    "proofValue": "r3FbeXqzeJe0pSIK3fxwmXXRYOcphcFmF5wSPfo96FdZCch4ZtiwjWH015dZsqvTM2kraU3ah7Dt/bLfgnfYZCrU3blXeROPceBV8P7vJJMAlT9MABRzWWDbaRe/weL+kMWEDNRxcpIXuFPt09WtQg=="
  }
}

These two credentials are represented as the following RDF dataset (represented in N-Quads):

# VC1
<http://example.org/vaccinationCredential/04> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .
<http://example.org/vaccinationCredential/04> <https://www.w3.org/2018/credentials#credentialSubject> <did:example:xyz> .
<did:example:xyz> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://schema.org/Person> .
<did:example:xyz> <http://schema.org/name> "John Smith" .
<did:example:xyz> <http://example.org/vocab/isPatientOf> <http://example.org/vaccination/04> .
<http://example.org/vaccination/04> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/vocab/Vaccination> .
<http://example.org/vaccination/04> <http://example.org/vocab/vaccinationDate> "2022-04-04T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
<http://example.org/vaccination/04> <http://example.org/vocab/vaccine> <http://example.org/vaccine/987> .
# ... proof and some quads are omitted

# VC2
<http://example.org/vaccineInfoCredentials/987> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .
<http://example.org/vaccineInfoCredentials/987> <https://www.w3.org/2018/credentials#credentialSubject> <http://example.org/vaccine/987> .
<http://example.org/vaccine/987> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/vocab/Vaccine> .
<http://example.org/vaccine/987> <http://schema.org/name> "AwesomeVaccine" .
<http://example.org/vaccine/987> <http://schema.org/manufacturer> <http://example.org/awesomeCompany> .
<http://example.org/vaccine/987> <http://schema.org/status> "active" .
# ... proof and some quads are omitted

Then, imagine that an officer (verifier) asks John Smith to show that he has already got vaccinated after, say, 2022-03-31, and the vaccine used there is authorized as "active". The officer can express this requirement as zk-SPARQL query as follows:

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX s: <http://schema.org/>
PREFIX : <http://example.org/vocab/>

SELECT ?date WHERE {
  ?s a s:Person .
  ?s :isPatientOf ?ev .
  ?ev :vaccinationDate ?date .
  ?ev :vaccine ?vac .
  ?vac s:status "active" .
  FILTER ( ?date > "2022-03-31"^^xsd:dateTime )
}

Our zk-SPARQL endpoint can process this query and respond with the following query results in the zk-SPARQL Query Results JSON Format:

{
  "head": { "vars": [ "date", "vp" ] },
  "results": {
    "bindings": [
      {
        "date": {
          "type": "literal",
          "value": "2022-04-04T00:00:00Z",
          "datatype": "http://www.w3.org/2001/XMLSchema#dateTime"
        },
        "vp": {
          "type": "literal",
          "value": "{{{VP as JSON string}}}"
        }
      }
    ]
  }
}

This results are typically rendered as the following human-friendly table:

date vp
2022-04-04T00:00:00Z {{{VP as JSON string}}}

{{{VP as JSON string}}} part consists of the following VP:

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://zkp-ld.org/bbs-termwise-2021.jsonld",
    "https://schema.org"
  ],
  "type": "VerifiablePresentation",
  "verifiableCredential": [
    {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://zkp-ld.org/bbs-termwise-2021.jsonld",
        "https://schema.org"
      ],
      "id": "http://example.org/vaccinationCredential/04",
      "type": "VerifiableCredential",
      "credentialSubject": {
        "id": "anoni:IGDDf_",
        "type": "Person",
        "http://example.org/vocab/isPatientOf": {
          "id": "anoni:LnCuad",
          "http://example.org/vocab/vaccinationDate": {
            "type": "xsd:dateTime",
            "@value": "2022-04-04T00:00:00Z"
          },
          "http://example.org/vocab/vaccine": {
            "id": "anoni:R28Rl6"
          }
        }
      },
      "expirationDate": "2025-04-04T00:00:00Z",
      "issuanceDate": "2022-04-04T00:00:00Z",
      "issuer": "did:example:issuer1",
      "proof": {
        "type": "BbsTermwiseSignatureProof2021",
        "created": "2023-02-03T09:46:55Z",
        "nonce": "3ZH/2wGdxjFM/lcbVfDY6jPTWb7hu0qmj5sDk0OFU0RnkROFszYqeorAIm4iqRdaPfg=",
        "proofPurpose": "assertionMethod",
        "proofValue": "WzAsMSwyLDMsMTEsMTIsMTMsMTQsMTUsNCw2LDgsOV0=.owAYQAFZA9yih/bHL/IQ6fBl7sTEYLghDiSUBfvRu1k5muindmZFqfFrBQNAB1r3moFieNIX4LevHuoWFiAmEjLjwo+TOLxuAn+W2cqSfRvALboUcAoxrgG901zVsghlZGKw45LIQmW1RPVRkKLsKSwz0Gig90GS7N9LWSSqWojewYsp7ArTdpxbF7q51/scxDAXxQwu55EAAAB0kdBRQtkBaVXJoNNV3CdlsXCW2+g9JnLioSbeMd+Hz4EvSYEVId9Gq9HaSpgmi2vWAAAAAjVrDsl4COHkGPVZHVgIU3AZd07ngnDhwvEBkhfLzEfjXAn64GlbTmRI8s+crF1YHmd8M8euvuqbhpuEWlfoCam3JWf0dzGeQ342tZsLO7syLOaVdFunQnYykTdSfeZltCFn80KW3S+OosfKYjHH2qoAAAAVFUep3Gllly9aLtAkmOk977cGTt98/2PlugrCt1my8EEQeXeCG7v3SgfVSr7tiAq5ycwIvD0A7FpfYKnRSQpjVQjKkkPI14XjTaoh/uosRnhtaV/43MPe3izsiysJSYI5Mt++V+ISf/Z+P+qRxJF7f8YKvYF2jzlLPs7ZWh76Toc2U0PY3uRoDz7njH40nVPctr1coW8EtM4sWwL/8v8YkTWsjo8Kx4ZLwVivMwhifGVL8JKnCfxgt/+KSsEmZVUKPWsXSUTmaAZSdzaHiHqWgUKBQd2BKrbh8tN9hhRNW0RVVpnLJsKjomf7vBy+/gYI/CmT+eacNXVic9+5cKWG3QjKkkPI14XjTaoh/uosRnhtaV/43MPe3izsiysJSYI5cb09Gs9+OTjvLBJxiRlrlcrKHlUVCGcRmcGQqPPr34Vrf4qhZuBTx9UiY/ZFLE5VfC6v+le82hGWVrxfGxhJVzwt1xKRZzVu9eZHgiWoPJKxZak3RzfiwJ7moZlK8JA5VvO/A3E8XRM6xAFEId94asV+RSWTzgXetZNWgYNeQp0y375X4hJ/9n4/6pHEkXt/xgq9gXaPOUs+ztlaHvpOhzLfvlfiEn/2fj/qkcSRe3/GCr2Bdo85Sz7O2Voe+k6Hc6gJ0wHzXz382Yl/ayVdAVQ2gL1bZJ9CiUwM1FRgBG8YlK2+pfbIN4J+nLAvWH+WrZaTjCwZo8yQrM3v/1ZbqzGJuUJWqNsn/DhsLJexP2BDj1/5nhwfZRh+pJ8Fs2ODQKh79vDQMay4sydbMXsWiLjXLTVrU9iMa5MJwe+PkII5DpTrvt61Y/2U1ehs0EMLbckLCRk9bizILehLB7ZXmgjKkkPI14XjTaoh/uosRnhtaV/43MPe3izsiysJSYI5AoA=",
        "verificationMethod": "did:example:issuer1#bbs-bls-key1"
      }
    },
    {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://zkp-ld.org/bbs-termwise-2021.jsonld",
        "https://schema.org"
      ],
      "id": "http://example.org/vaccineInfoCredentials/987",
      "type": "VerifiableCredential",
      "credentialSubject": {
        "id": "anoni:R28Rl6",
        "status": "active"
      },
      "expirationDate": "2023-12-31T00:00:00Z",
      "issuanceDate": "2020-01-01T00:00:00Z",
      "issuer": "did:example:issuer2",
      "proof": {
        "type": "BbsTermwiseSignatureProof2021",
        "created": "2023-02-03T09:49:25Z",
        "nonce": "3ZH/2wGdxjFM/lcbVfDY6jPTWb7hu0qmj5sDk0OFU0RnkROFszYqeorAIm4iqRdaPfg=",
        "proofPurpose": "assertionMethod",
        "proofValue": "WzAsMSwyLDMsOCw5LDEwLDExLDEyLDZd.owAYNAFZAzypSzCSFGIHvFpYYcHsnIlRAcf6YElheBP8BhQE57DNt3fz68JNJiaqjw8VypkKhA2YPUuKwznV6QeY5X/3UE9JKYlM8Mw/slSa65QFNNHczcacunssPRcQuSenpAW6QnyCxGW1gop3JeJDLUpnBP3Dfx5p/wWG04s03mnaFFeRacaqNUfGNpCIKoMCfpaZqU8AAAB0svc+8XNpEEc3me0AhIVw+C1i4PLaLZiEecxULRns4i40uPvPpIxCC9Xb1eA7ThDHAAAAAjEltT3eDTVubX2Et8UPc/ABYs138cGx/lg9MGj+gl/pF85dRhamt1ymXYRUjel/X8zHzK7YYFgneTfD2RO5hsynZfT+q/rXO0wQm6rq9fu7fTiVqz38lm3kPF8A388lNxvQs3exVFvtaZPlCw8DA20AAAAQDmGkli1Vd8UrsJYEiw9DtDZyJLfzt9dAYVBBvh7OpG8d2qdm72nyP9BZs+RCZxXukwvVABfjhHGE9VWk+LBH+TBS7cgG62ikvLc4vZKrF+auREIiczmBgSfG7ULH8hieaKTQYAE7E86I3fyHH5u53qB97r1A3PknUxAypXtqYBFkgY2p0c5O09wuTEQ8ILtyF4WGpLgLqUD6kRclYgplWCiOsV1cVWeTVgBRyD0uKadEztsLZYexkJZ5k4FIhJcyMq1mWOJFLxiIriwW9VIAiJdF950qE4/hafpJdkJYalZmlPDnltUOSzL0VIgV1V4L28qtFE/cmakbyFQUfVgG4AXBL6+V5u/cu/3SGcwGhr23T8otlECiiGDbg4zv2lHKXlqcAiRXE36YHrjBACk7qGY4e5AqmruSyodMUoZAWvVzqAnTAfNfPfzZiX9rJV0BVDaAvVtkn0KJTAzUVGAEbwzqV+xABqYW1JftouleqKRXY7n62ilaPAZDlg80wG5pMk5nm9clTF2KMtJGSsqLDY5H0eJyBd3GraLzy6DJUAUhYkfimf9ciVn4pQbk9JrU3f7B4GWBLkK1i2Jms3UHblsTQ0eN5yyFdFf7uiJWjPHuYhIjKGIA3zXM4UW2Bizbc6gJ0wHzXz382Yl/ayVdAVQ2gL1bZJ9CiUwM1FRgBG8CgA==",
        "verificationMethod": "did:example:issuer2#bbs-bls-key1"
      }
    }
  ]
}

This VP itself is JSON-LD document so that the officer (verifier) can transform it into the following RDF dataset:

# derived from VC1
<http://example.org/vaccinationCredential/04> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> _:b1 .
<http://example.org/vaccinationCredential/04> <https://www.w3.org/2018/credentials#credentialSubject> <https://zkp-ld.org/.well-known/genid/anonymous/iri#IGDDf_> _:b1 .
<https://zkp-ld.org/.well-known/genid/anonymous/iri#IGDDf_> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://schema.org/Person> _:b1 .
<https://zkp-ld.org/.well-known/genid/anonymous/iri#IGDDf_> <http://example.org/vocab/isPatientOf> <https://zkp-ld.org/.well-known/genid/anonymous/iri#LnCuad> _:b1 .
<https://zkp-ld.org/.well-known/genid/anonymous/iri#LnCuad> <http://example.org/vocab/vaccinationDate> "2022-04-04T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> _:b1 .
<https://zkp-ld.org/.well-known/genid/anonymous/iri#LnCuad> <http://example.org/vocab/vaccine> <https://zkp-ld.org/.well-known/genid/anonymous/iri#R28Rl6> _:b1 .
# ... proof and some quads are omitted

# derived from VC2
<http://example.org/vaccineInfoCredentials/987> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> _:b4 .
<http://example.org/vaccineInfoCredentials/987> <https://www.w3.org/2018/credentials#credentialSubject> <https://zkp-ld.org/.well-known/genid/anonymous/iri#R28Rl6> _:b4 .
<https://zkp-ld.org/.well-known/genid/anonymous/iri#R28Rl6> <http://schema.org/status> "active" _:b4 .
# ... proof and some quads are omitted

Compared to the original N-Quads, we can see that some URIs are replaced with the pseudonymous values like <https://zkp-ld.org/.well-known/genid/anonymous/iri#IGDDf_> because they are not required to appear to answer to the zk-SPARQL query.

The officer (verifier) can execute their zk-SPARQL query against this N-Quads to check that this VP exactly includes the query result. The officer (verifier) can also verify the VP's authenticity using BBS+ verification algorithm. If both checks are passed, the officer can accept this zk-SPARQL query result as a verified result.