BBS for Verifiable Credentials - Data Integrity

Dr. Greg Bernstein

June 4th, 2024

BBS Signature with VC Data Integrity

Outline

  1. VC Data Integrity Review
  2. BBS Signature Review
  3. BBS Messages from JSON-LD VC
  4. Mandatory and Selective Disclosure with JSON
  5. Putting all the pieces together: Base and Derived Proofs

Me and My VC Work

* W3C “Invited Expert”, semi-retired, website: Grotto Networking

VC Data Integrity Review

Key Specifications

  1. Verifiable Credentials Data Model v2.0 In particular JSON-LD based with information specified in section Verifiable Credentials. We are concerned here with embedded proof securing mechanism as compared to an enveloping proof mechanism.
  2. Verifiable Credential Data Integrity 1.0 This specifies the proof field that gets embedded to secure a credential. Note that the embedded approach combined with DI allows for “parallel signatures”, proof sets, and proof chains

Data Model VC General Form

Data Model Verifiable Credentials, aka unsecured document

{
  "@context": [ "https://www.w3.org/ns/credentials/v2", "more..."], // Required
  "type": ["VerifiableCredential", "more..."], // Required
  "issuer": "URL or object", // Required
  "credentialSubject": {
    // Bulk of info here. Required!
  },

  "id": "a URL", // For the VC itself, Optional
  "validFrom": "2020-01-01T19:23:24Z", // Optional
  "validUntil": "2025-01-01T19:23:24Z", // Optional
  "name": "Example Windsurfing Credential", // Optional
  "description": "Dock Etiquette", // Optional
  "credentialSchema":  {}, // Optional
}

Data Integrity Proof General Form

From Proofs and DataIntegrityProof,

{
  "type": "DataIntegrityProof", // Required
  "proofPurpose": "assertionMethod", // Required
  "verificationMethod": "string/URL links to PK", // Required
  "proofValue": "string encoding binary data", // Required, Computed
  "cryptosuite": "bbs-2023", // Required for Data Integrity Proofs

  "id": "a URL", // for the proof, Optional, used in proof chains
  "previousProof": "string or array", // Optional, used in proof chains
  "created": "2024-05-25T19:23:24Z", // Optional
  "expires": "2026-05-25T19:23:24Z", // Optional
  "domain": "some kind of string", // Optional
  "challenge": "some kind of string", // Optional
  "nonce": "some kind of string" // Optional
}

DI (embedded) Secured Document Format

Only Required Properties Shown

{
  "@context": [ "https://www.w3.org/ns/credentials/v2", "more..."], // Required
  "id": "a URL", // For the VC itself, Optional
  "type": ["VerifiableCredential", "more..."], // Required
  "issuer": "URL or object", // Required
  "credentialSubject": {
    // Bulk of info here. Required!
  },
  "proof": { // Required, can be array of proof objects
    "type": "DataIntegrityProof", // Required
    "proofPurpose": "assertionMethod", // Required
    "verificationMethod": "string/URL links to PK", // Required
    "proofValue": "string encoding binary data", // Required
    "cryptosuite": "bbs-2023", // Required for Data Integrity Proofs
  }
}

General Approach High Level

Transform, Hash, Sign

General Approach I: EdDSA and ECDSA

  1. Starting with proof options which includes anything in the proof but the proofValue. This object is appropriately canonized (JCS or RDFC) and then hashed to produce proofConfigHash. Protects proof meta data
  2. The unsecured document gets canonized (JCS or RDFC) and then hashed to produce transformedDocumentHash. Protects document data and meta data

General Approach II: EdDSA and ECDSA

  1. The two hashes above are concatenated then a signature value, proofBytes, is computed with the appropriate algorithm (ECDSA-P256, ECDSA-P384, EdDSA).
  2. proofBytes is then (multibase) encoded to produce the proofValue field for inclusion in the proof field.

Why Canonicalization?

Example: JSON Canonicalization Scheme (JCS)

  1. Adding/removing whitespace between tokens in a JSON document does not change its meaning
  2. Changing the order of properties in a JSON object does not change its meaning
  3. Either of the above will change the value of a cryptographic hash over the text of the JSON
  4. Need equivalent documents to produce same hash! Solution ==> put in a canonical (standard) form.

Example for Canonicalization

{
  "@context": "https://json-ld.org/contexts/person.jsonld",
  "name": "Manu Sporny",
  "homepage": "http://manu.sporny.org/",
  "image": "http://manu.sporny.org/images/manu.png"
}

Example JCS Canonicalization

Note ordering of fields, removal of white space.

{"@context":"https://json-ld.org/contexts/person.jsonld","homepage":"http://manu.sporny.org/","image":"http://manu.sporny.org/images/manu.png","name":"Manu Sporny"}

BBS Signature Scheme Review

Background Reading and Demo

BBS Fundamental Properties

From DIF/IETF draft

  • Fixed Sized Signatures: The scheme allows a signer to sign multiple messages and produce a single -constant size- output signature, i.e., 80 bytes.
  • Selective Disclosure: The receiver of the signature can generate a BBS proof that discloses only a subset of the original set of messages.
  • Unlinkable Proofs: The BBS proofs are unlinkable to the original signature, and to each other.

Example: Tree Drivers License

From Grotto BBS demo, not a VC or mDL…

{
  "publicKey": "b65b7cbff4e81b723456a13936b6bcc77a078bf6291765f3ae13170072249dd7daa7ec1bd82b818ab60198030b45b8fa159c155fc3841a9ad4045e37161c9f0d9a4f361b93cfdc67d365f3be1a398e56aa173d7a55e01b4a8dd2494e7fb90da7",
  "header": "11223344556677889900aabbccddeeff",
  "messages": [
    "FirstName: Sequoia",
    "LastName: Sempervirens",
    "Address: Jedediah Smith Redwoods State Park, California",
    "Date of Birth: 1200/03/21",
    "Height: 296 feet",
    "Eyes: None",
    "Hair: Brown bark, green needles",
    "Picture: Encoded photo",
    "License Class: None, Trees can't drive"
  ],
  "signature": "94bb93062e05bc702d0ab222b861fd0311533d6dcbcad4050e45dd2392de951a912915af08bd87b2284807432245f9960e1f59680a59cd9fae490dee659d63fd3922a728e2ba3ee33db6bcc806ec2cea3d7264489a42ca09deeac7ca88b1811c2158b51d81560832daf6a0000037a87a"
}

Selective Disclosure Example: A Tree goes to a bar…

Selective Disclosure

Example Derived “Proof”

{
  "pk": "b65b7cbff4e81b723456a13936b6bcc77a078bf6291765f3ae13170072249dd7daa7ec1bd82b818ab60198030b45b8fa159c155fc3841a9ad4045e37161c9f0d9a4f361b93cfdc67d365f3be1a398e56aa173d7a55e01b4a8dd2494e7fb90da7",
  "header": "11223344556677889900aabbccddeeff",
  "ph": "",
  "disclosedIndexes": [
    0,
    3,
    7
  ],
  "disclosedMsgs": [
    "FirstName: Sequoia",
    "Date of Birth: 1200/03/21",
    "Picture: Encoded photo"
  ],
  "proof": "a6089a46f59e005a11885fe29e8e67679d6545b42e1126858ef2a3b6cbd5b2f1de1577194ce57077bfb1d555476e10a8afb64592f6e37e2e9f2f99422c7b6466cc49499f2e0a7d670a19a0e3765e6522b95376c06a776965a81e29238c3c9350b0e367daa23010490da97c2002027b43c6f7ba181f601eb4462964883c08e4ffcb9424180aaadc103f89c923d88b88c4015ff3d28a64887a88ae0944d3aaf1ed371173f068b3d0b79a5177c287b1c64271807cc03d331a3b18d3491898a1be13c6404cae9acbacd7ce635a4d7a6b520b1a33fb1ca1dbcbc90158269b2e2a58714fc97c892a5ebd839fb22f307d29bdf822b21bf1a906b428ee75f0dc408ebbb4085e6f4e057bb3b1f783e636e0de07eb542e2d1054e89b0451148bf703a9e59cce2e49e000d8aa1448acd514393d7f661b028cdbaec607bef03384028f6a47907c0d1e2b16c03e37c73b75b2d6d85a670186be482b4abbc2cecc90d29b16c11a12eeededc68fc16e0729e97a14d44a5e6cedca243afad6024d46f7fa738e635ff3e93c5502ad3b7772c1f0bc86d5fa930a34ea0771bddb3a9da5e308613b468421de3dc6789ae5c014915199d978082615a81214f0efb12fc824b3a1b5c9ab2ba7b62a4e44ef21eabe9fbf2803d13d360730c49c8e5c67617b739593e0824fc0f2e626f30e88d365007df318571b467b"
}

Good Tracking I

Tracking for Safety

Good Tracking II

Not a big enough boat…

Verifiers Tracking Holders

Not the good kind of tracking…

Unlinkable Proofs Example 1

  • A tree goes into a bar and needs to prove it lives in a local state park in order to get a very large glass of water.
  • It then goes to another local bar for another very large glass of water.
  • It doesn’t want to be tracked across bars or have its water consuming habits tracked.
  • Solution: Generate a separate BBS proof for each bar it visits

Unlinkable Proofs Example 2

BBS Proof presented at first bar

{
  "pk": "b65b7cbff4e81b723456a13936b6bcc77a078bf6291765f3ae13170072249dd7daa7ec1bd82b818ab60198030b45b8fa159c155fc3841a9ad4045e37161c9f0d9a4f361b93cfdc67d365f3be1a398e56aa173d7a55e01b4a8dd2494e7fb90da7",
  "header": "11223344556677889900aabbccddeeff",
  "ph": "",
  "disclosedIndexes": [
    2
  ],
  "disclosedMsgs": [
    "Address: Jedediah Smith Redwoods State Park, California"
  ],
  "proof": "a312e2476de36c0fc2a815ebd9236c6cc1831a3fcdb3d2cdaf4d3ff325259a4d36e910ea06b75f6708f035924c6488da989a57fbbcfe187e78d2550f23eabb577a3c2457147cbf68f82f16c75ba9b52ea0e36d264a7ac3304fb8892ad9c4c33ea2505ffb8c9aaa203094bf2bd917c1c18c62fd3b7c7459616dced8836d3d5f608201c7d0b7a80daf8205d2451bd33d5b06fab9f3dda846137539b4ae53d9dbaf699bb3f43f9ab38d936e8f4d035128af0e19867e3edcfeb58175d44ac6a4f471b2bca58d9b4de80291b2809658a804f570e9d7e0aa55bf157d138cdd6a82b7364db5443e1fa5fc9d52f404097d85889755761f48befdcb5d2d581d2911808e9d6b4b213b7eeb4c38b878195f13b004ba1179b5a7f88cc39aeca21ab781a5107c4e69b29db00876274df71d4460f09dfd3df287bb384c6efb9c6fd3cbb7f0f0d3545b07c5a039686ac1a10b7eb0cf52f46e28d38f970dccf6f4d039b78a11f42349a52d06397a10ed80ac567ee29f21e6022200ca71c088cf7bada1878150cd776716f66495ff0337e72572a325329539466cc3d1745034798b0a09e1c62090f3be3d4a22b518aff620a484d0bd5461f95c5ca7e5a8f50ddb96e29dda0192def462c611bccb9465c3457e1b69bce4b6676e190be338e030da06b481014271828eee6648b40626f4b293980e4267b22c39121236376dc2e786f92ba760d21f174068028e87c29e7167a5023295a4af6a8141ba8c5de8dd25e2f1b8b7fdfa72d60324c6c81e2ca3951dc761b75e10d05646"
}

Unlinkable Proofs Example 3

BBS Proof presented at second bar

{
  "pk": "b65b7cbff4e81b723456a13936b6bcc77a078bf6291765f3ae13170072249dd7daa7ec1bd82b818ab60198030b45b8fa159c155fc3841a9ad4045e37161c9f0d9a4f361b93cfdc67d365f3be1a398e56aa173d7a55e01b4a8dd2494e7fb90da7",
  "header": "11223344556677889900aabbccddeeff",
  "ph": "",
  "disclosedIndexes": [
    2
  ],
  "disclosedMsgs": [
    "Address: Jedediah Smith Redwoods State Park, California"
  ],
  "proof": "8175e24b57337bd8abed395c0d2440efe71e55cf06fbb1ead5d4e8589e2a5dc295688f561851d5f2e169a417c2ddde32b7801550cb442227db1503f1dfdf803125c9f10aae16b69ec58ad33a0ff9acc18405f0f24640e5381a2abadefcc6fb6e952bbd8ec908a60c28dc5913a25a586ee9b49f9a8fec0eff51dafc283ea44d07dd60292e6ef5711a202ef055fa7a203f727bdf0087f1b91d96a91e07ca417eed8cc03f00a1de1b013ceff998d9a6ff55559105abc53a80b30d68eb644150602f55cfb3de0bc949d9d3c85732df6d5d1535798679d0d29895bfe1ef58d9aa63f0fc160394a5739c65602d9bb21fffa4ed27408be6c0beb579b997eb0426d85fc3c7db1961992e85df1fd35cd421dc007b130d9f41568b7d9984689c883ea9a8b6e50b95c8cfd1bee71f2ad1c08cb2134b5337794d6a387aefc44af1929e456d857197d02acf1caddbd751380a9ac5a00c10c6df911dd00bc27e4d68dc6af5023e83e2e45f80b416b98d7d46ea967835c3155f3b6a22fcb8534a23b15c16805ae4adb98bfd17bc096a9ad0636dbdb844344c862d44b5d8d55d4fa0be73623ce5f1ea558cdb1e8dc8f4b958a8bda851115802a3b12ce54177b236dd98d819a2dbeafa1a04e0214fbb3bccb5edf94e0c9cfa575334bf48ffa11755435bc40945fc46e862f67c8f5ee6247f9f9a3c57dbd4122551605f3db005764db0717e2f8365a8458141c94549db43c8034798532817582507b679e7fc724518e281443a0f1d59c9d030df6e8ef65cd33093919ae1a018"
}

Unlinkable Proofs

  • The values (cryptographic byte array) contained in the BBS proofs are unlinkable. In particular they appear essentially random
  • Unlinkable proofs do not prevent correlation on disclosed messages! This information has been disclosed by the holder.
  • See Selective Disclosure and Unlinkability for a full discussion of unlinkability and its limits.

BBS API and Messages

Terminology Collision!

Important: We have a terminology collision! Both BBS signatures and verifiable credentials use the terms proof and signature. However these can have very different meanings, hence we will be verbose and use terms like “BBS signature”, “BBS proof”, and “VC data integrity proof”.

BBS Signature Scheme API 1

BBS has sign and verify

  1. signature = Sign(Secret_Key, Public_key, header, messages) used by issuer/(signer)
  2. result = Verify(Public_key, signature, header, messages) is used when the holder/(prover) verifies the VC it receives from the issuer/(signer).

BBS Signature Scheme APIs 2

but BBS is more than sign and verify

  1. bbs_proof = ProofGen(Public_key, signature, header, ph, messages, disclosed_indexes) is used when the holder want to prepare a derived VC that selectively discloses original VC information.
  2. result = ProofVerify(Public_key, bbs_proof, header, ph, disclosed_messages, disclosed_indexes) is used by the verifier to validate the derived VC against the original issuers public key.

BBS Messages from JSON-LD?

From VC BBS Test Vector

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "issuer": "https://vc.example/windsurf/racecommittee",
  "credentialSubject": {
    "sailNumber": "Earth101",
    "sails": [
      {
        "size": 5.5,
        "sailName": "Kihei",
        "year": 2023
      },
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2023
      },
      {
        "size": 7.0,
        "sailName": "Lahaina",
        "year": 2020
      },
      {
        "size": 7.8,
        "sailName": "Lahaina",
        "year": 2023
      }
    ],
    "boards": [
      {
        "boardName": "CompFoil170",
        "brand": "Wailea",
        "year": 2022
      },
      {
        "boardName": "Kanaha Custom",
        "brand": "Wailea",
        "year": 2019
      }
    ]
  }
}

Statements/Messages from JSON-LD

  • JSON-LD is a serialization, storage and exchange format for the Resource Description Framework (RDF)
  • RDF is a graph based data model consisting of: Subject, Predicate, Object, and if needed containing Graph.
  • RDF Canonicalization transforms a JSON-LD document into an ordered set of statements called quads.
  • We use these statements/quads as our BBS messages!

Example Statements/Messages

From VC BBS Test Vector

[
  "_:c14n0 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n",
  "_:c14n0 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n",
  "_:c14n0 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:c14n1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:c14n1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n2 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n",
  "_:c14n2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n",
  "_:c14n2 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:c14n3 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n3 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n4 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n",
  "_:c14n4 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:c14n4 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#boards> _:c14n0 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#boards> _:c14n2 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n1 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n4 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n6 .\n",
  "_:c14n6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:c14n6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:c14n6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
  "_:c14n7 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n5 .\n",
  "_:c14n7 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n"
]

Mandatory and Selectively Disclosed Statements

Selective Disclosure Requirements

  • An issuer can specify that a subset of the statements must be revealed by the holder to the verifier. These are the mandatory statements.
  • A holder can specify a subset of the non-mandatory statements to be revealed. These are the selectively disclosed statements.
  • Want to do this in a user and developer friendly way.

JSON Pointers

JavaScript Object Notation (JSON) Pointer (RFC6901)

  • “JSON Pointer defines a string syntax for identifying a specific value within a JavaScript Object Notation (JSON) document.”
  • Example: "/issuer" is used to match the issuer field.

Example: Mandatory Pointers

Prior to a fictional windsurfing race: declare two sails, most recent board

[ "/issuer",
  "/credentialSubject/sailNumber", // how they are identified
  "/credentialSubject/sails/1",
  "/credentialSubject/boards/0/year",
  "/credentialSubject/sails/2"
]

Example: Matching Fields

[
  {
    "pointer": "/issuer",
    "value": "https://vc.example/windsurf/racecommittee"
  },
  {
    "pointer": "/credentialSubject/sailNumber",
    "value": "Earth101"
  },
  {
    "pointer": "/credentialSubject/sails/1",
    "value": {
      "size": 6.1,
      "sailName": "Lahaina",
      "year": 2023
    }
  },
  {
    "pointer": "/credentialSubject/boards/0/year",
    "value": 2022
  },
  {
    "pointer": "/credentialSubject/sails/2",
    "value": {
      "size": 7,
      "sailName": "Lahaina",
      "year": 2020
    }
  }
]

Example: Mandatory Statements (nquads)

Behind the scenes!

[
  [
    0,
    "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
  ],
  [
    1,
    "_:b0 <https://www.w3.org/2018/credentials#credentialSubject> _:b3 .\n"
  ],
  [
    2,
    "_:b0 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n"
  ],
  [
    8,
    "_:b2 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
  ],
  [
    9,
    "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b2 .\n"
  ],
  [
    11,
    "_:b3 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n"
  ],
  [
    14,
    "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b6 .\n"
  ],
  [
    15,
    "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b7 .\n"
  ],
  [
    22,
    "_:b6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
  ],
  [
    23,
    "_:b6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
  ],
  [
    24,
    "_:b6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
  ],
  [
    25,
    "_:b7 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
  ],
  [
    26,
    "_:b7 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
  ],
  [
    27,
    "_:b7 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
  ]
]

Data Integrity Base BBS Proof (Issuer => Holder)

Issue a BBS Protected VC

Inputs:

  • proof options: Required and any optional fields for use in the attached proof
  • Unsecured document: The credential without proof
  • Key material: For use by the signing algorithm
  • Mandatory Pointers: Array (possibly empty) of JSON pointers to mandatory reveal information.

Details: Summarize and Protect Proof Options

  1. Canonicalize proof options using RDFC
  2. Hash canonized proof options ==> proofHash

Details: Summarize and Protect Mandatory Statements

  • Inputs: mandatory pointers and unsecured credential
  • Run “Canonicalize and Group” function to produce a list of mandatory quads and a list of non-mandatory quads.
  • Hash list of mandatory quads ==> mandatoryHash

Details: Compute BBS Signature Bytes

Sign(Secret_Key, Public_key, header, messages)

  • header = concatenation of proofHash and mandatoryHash
  • messages = non-mandatory quads
  • Note: BBS header is “associated data” that must be conveyed to holder and verifier

Details: Package up info into proofValue

  • Add a proof header (CBOR tag) of bytes 0xd9, 0x5d, and 0x02 to indicate base BBS proof
  • CBOR encode the components: BBS signature, BBS header, publicKey, hmacKey, and mandatoryPointers
  • Multibase encode the above to produce the proofValue string

Details: Attach Proof

  • Add proofValue string to proof options
  • Add proof options as proof field of unsecured document to produce the secured document.

Create Base Proof Example

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "issuer": "https://vc.example/windsurf/racecommittee",
  "credentialSubject": {
    "sailNumber": "Earth101",
    "sails": [
      {
        "size": 5.5,
        "sailName": "Kihei",
        "year": 2023
      },
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2023
      },
      {
        "size": 7,
        "sailName": "Lahaina",
        "year": 2020
      },
      {
        "size": 7.8,
        "sailName": "Lahaina",
        "year": 2023
      }
    ],
    "boards": [
      {
        "boardName": "CompFoil170",
        "brand": "Wailea",
        "year": 2022
      },
      {
        "boardName": "Kanaha Custom",
        "brand": "Wailea",
        "year": 2019
      }
    ]
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0ChVhQhruAY3aNS3CPmmWCHub-Qms9T2_lwsXJpfgMqlc_2MIMvfF4Jv5OGmJAcLpfIB2SAqD861WELqnmGnKnqgSJFDf8Nfarnvi_jsMATMRslFhYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfVV3gX4mIF-MTAbrBh9DD_ysD4svbSttNVowX3pYfmhhYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-FZy9pc3N1ZXJ4HS9jcmVkZW50aWFsU3ViamVjdC9zYWlsTnVtYmVyeBovY3JlZGVudGlhbFN1YmplY3Qvc2FpbHMvMXggL2NyZWRlbnRpYWxTdWJqZWN0L2JvYXJkcy8wL3llYXJ4Gi9jcmVkZW50aWFsU3ViamVjdC9zYWlscy8y"
  }
}

Data Integrity Derived BBS Proof (Holder => Verifier)

Create a Selectively Disclosed BBS VC

Inputs

  • Secured Document containing a base BBS proof.
  • Selective Pointers: JSON pointers to fields that holder want to disclose.

Output: Derived Data Integrity Secured Document

Details: Compute BBS Proof

ProofGen(Public_key, signature, header, ph, messages, disclosed_indexes) where

  • signature is the original BBS signature from issuer. Not sent to verifier!
  • messages are the non-mandatory quads
  • The disclosed_indexes are based on the selective pointers relative to the non-mandatory quads

Details: Create Disclosure Document

  • Recover the unsecured issued document from the secured document by removing the proof field.
  • Create the unsecured disclosed document based on mandatory and selective pointers applied to the unsecured issued document

Details: Create Derived proofValue

  • Add a proof header (CBOR tag) of bytes 0xd9, 0x5d, and 0x03.
  • CBOR encode the components: bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexes, and presentationHeader.
  • Multibase encode the above to produce the proofValue string

Details: Attach Derived Proof

  • proof options is obtained from the proof field of the secured document with the proofValue removed.
  • Add the new proofValue string to proof options
  • Add proof options as proof field of unsecured document to produce the secured derived document.

Create Derived: Example

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "issuer": "https://vc.example/windsurf/racecommittee",
  "credentialSubject": {
    "sailNumber": "Earth101",
    "sails": [
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2023
      },
      {
        "size": 7,
        "sailName": "Lahaina",
        "year": 2020
      }
    ],
    "boards": [
      {
        "year": 2022,
        "boardName": "CompFoil170",
        "brand": "Wailea"
      },
      {
        "boardName": "Kanaha Custom",
        "brand": "Wailea",
        "year": 2019
      }
    ]
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0DhVkCEJTXhOR_jHa_YPZ6UscS_68yPtbY0B0JXYD9WcaSEeBYLbTWGZsJ4tEktVOOI7Ygy7WafP3ISVPaOTGX7mEPL8rMg3eU-Ixz3uOnSP5nvCDAvj1bhRHE8eJ9CFf_Up7MOofMWhD_ONzGYzgQ4IrFqA2s_m597DymX7HauNGw2iK48mBAI4xwC4MQ3pLJwuwRi2Gv-qcs6eVJOmIbLBgbG-SLHqZzfEoyyzgpWxJMadxxUHsN9C00plRxXlaNbYncQKe-6XzudczdczOndR3bfXMFoV_eFFGetQf1UzNAFD5ACCEJ-26Gh93ZiaED7MLI7GjxspK4fyfvqzIR_Acw2p8jDckunU1_Y5pFi7pmnpRhAl3dJZz_uDoi5iaflf6BErq76wwsh2p8SfpQEh6bY1FgM1hzZDDdo6QKwqiNJ4n6K_fydl7R2rvORmBQbOzcmThH1_Sxui2pXo3jga4LHxhxNYdSt4RsnE1pnKjKfiq6N-jqJD2msOpm1HCyxZzTbsPyj6qM9pzyNmRjlIFR2RthSffpCXYMsEut4SBOocK4J-99J8gIYp7MOsDz1BYLFRn2zkfc5KaFKza8_V6O5lh6algvRyNg7Uq6cQ4zU8ErSQszBqhQDJAtZeo3iALauW2EenkHQRejv-cTqtqhIetQilZK5K2TcuDYaTWSdr9Jf44-v84VjSC_nmP93xP8IaYAAgEEAgMDBwQGBQCOAAECBQYICQoODxAREhOGAwQFCAkKRBEzd6o"
  }
}