How to Certify ?

After having registering you in our Trust Registry as a Trusted Source, you can now certify proofs

1) Certify digital documents

a) Presentation of the digitalDocument schema

The digitalDocument schema is already anchored. Here is how it was built:

{
    "id": "c42e2516",
    "name": "DigitalDocument",
    "description": "An electronic file or document",
    "version": "0.9.0",
    "namespace": "archipels.io",
    "hash_algorithm": "SHA256",
    "matching_conditions": {
        "or": [
            "sha256"
        ]
    },
    "inputs": [
        "sha256",
        "dateCreated",
        "expires",
        "creator",
        "category",
        "description",
        null,
        null
    ],
    "input_definitions": {
        "sha256": {
            "description": "The SHA-2 SHA256 hash of the content of the item.",
            "standardization_function": "hexadecimal"
        },
        "dateCreated": {
            "description": "The date on which the CreativeWork was created or the item was added to a DataFeed.",
            "standardization_function": "formatDateTime"
        },
        "expires": {
            "description": "Date the content expires and is no longer useful or available.",
            "standardization_function": "formatDateTime"
        },
        "creator": {
            "description": "The creator/author of this CreativeWork.",
            "standardization_function": "replaceDiacritics.capitalize"
        },
        "category": {
            "description": "A category for the item. Greater signs or slashes can be used to informally indicate a category hierarchy.",
            "standardization_function": "digitalDocumentCategory"
        },
        "description": {
            "description": "A description of the item.",
            "standardization_function": ""
        }
    },
    "metadatum_definitions": {
        "sha256": {
            "id": "i1",
            "description": "The SHA-2 SHA256 hash of the content of the item.",
            "mandatory": true,
            "publication_flag": "searchable"
        },
        "dateCreated": {
            "id": "i2",
            "description": "The date on which the CreativeWork was created or the item was added to a DataFeed.",
            "mandatory": true,
            "publication_flag": "public"
        },
        "expires": {
            "id": "i3",
            "description": "Date the content expires and is no longer useful or available.",
            "mandatory": true,
            "publication_flag": "public"
        },
        "creator": {
            "id": "i4",
            "description": "The creator/author of this CreativeWork.",
            "mandatory": true,
            "publication_flag": "public"
        },
        "category": {
            "id": "i5",
            "description": "A category for the item. Greater signs or slashes can be used to informally indicate a category hierarchy.",
            "mandatory": true,
            "publication_flag": "public"
        },
        "description": {
            "id": "i6",
            "description": "A description of the item.",
            "mandatory": true,
            "publication_flag": "public"
        }
    }
}

See the next part 2. b. i. Create your proof schema to know more about *"*matching_conditions*"*, *"*standardization_function*",* *"*mandatory*"* and *"*publication_flag*"*.

b) Create a digitalDocument proof

Now you know how the schema is built, you can certify digital documents. First you must hash with SHA 256 your document using the following command to obtain the"document_hash" of your document.

$ openssl dgst -sha256 /document_path

There are the data you need to create a proof :

"schema_id": "c42e2516",
"sha256": "<"0x"+"document_hash">",
"dateCreated" : "<creation_date>",
"expires": "<expiration_date>",
"creator": "<creator_name>",
"category": "<document_category>",
"description": "<description>",
"secret" : "<12_characters_optional_secret>"

WARNING : make sure to put โ€œ0xโ€ before the "document_hash" of your document.

The secret is used to generate a nullifier. You can create a proof without filling in a secret, but one will be returned after each creation. Please keep these secrets as they are the only data allowing someone to nullify a proof. WARNING : The secretmust be a random number generated separately and kept safe as this is required to revoke the proof we've just created. A good secret should have a high entropy level. For example : a good secret can be generated as an UUID, a hash or a password generated by a password manager. For the same proof, making requests one after the other without secret will trigger the creation of a proof twice and generate a new ID every calls. Now you know how to structure a digitalDocument proof, you will find how to certify your proof in the 2. Certify your own proof part in the .

2) Certify you type of proofs

a) Create your own proof schema

If you're creating a new type of proof, you have to create the schema first.

In the production environment, your proof schema will be created by the Archipels team after discussing of your use cases.

In the sandbox environment youโ€™ll need the following information to create a proof schema.

The proof schema is the proofโ€™s architecture. It is composed from :

  • "id" : the proof schema identifier

  • "name" : the name of the proof schema

  • "description" : the description of the proof schema

  • "version" : the version of the proof schema

  • "namespace" : โ€œarchipels.ioโ€

  • "hash_algorithm" : โ€œSHA256โ€

  • "inputs" : the inputs you need to create and characterize a proof. For example : โ€œinput_1โ€. Note that the number of inputs must be equal to a power of 2. If you donโ€™t have enough inputs you need to complete it with null rows to complete it up to the higher power of 2.

  • "input_definitions" : for each input, you need to complete :

    "input_1" : { 
    "definition" : "<definition_of_the_input>",
    "standardization_function": "<the_function_used_to_standardize_the_input>"
    }
    • "standardization_function":

      • capitalize

      • digitalDocumentCategory

      • formatDate

      • formatDateTime

      • hexadecimal

      • removeSpaces

      • replaceDiacritics

  • "metadatum_definitions" :

    "input_1": {
      "id": "i1",
      "description": "<definition_of_the_input>",
      "mandatory": "<boolean>",
      "publication_flag": "<searchable_or_private_or_public>"
    }

    See the References for more details about the "id", the "mandatory" and the "publication_flag" inputs.

    • "id": identifier for the place of the Merkle tree where the input is. "i" identify the first stage, "n"is the second. When creating your schema, alway put "i", Archipels can change it after exploring your use case.

    • "mandatory": "true" or "false", it defines if the input is mandatory or not when creating a proof

    • "publication_flag":

      • "searchable": the input is a key for the proof verification, you can use it to identify the proof in the Archipels blockchain

      • "public": the input is disclosed when the proof verification is OK

      • "private": the input is not disclosed when the proof verification is OK

  • "matching_conditions" : a boolean combination of inputs needed to make a proof verification OK

You can see an example of an existing proof schema in the part 1. Presentation of the digitalDocument schema in or in the example below with two inputs:

{
    "id": "0aaaaa3b",
    "name": "Example",
    "description": "Example of proof schema",
    "version": "0.1.0",
    "namespace": "archipels.io",
    "hash_algorithm": "SHA256",
    "inputs": [
    "input_1",
    "input_2",
    "input_3",
    null
	  ],
	  "input_definitions": {
	    "input_1": {
	      "description": "Description of input_1",
	      "standardization_function": "<standardization_function>"
	    },
	    "input_2": {
	      "description": "Description of input_2",
	      "standardization_function": "standardization_function"
	    },
	    "input_3": {
	      "description": "Description of input_3",
	      "standardization_function": "<standardization_function>"
	    }
	  },
	  "metadatum_definitions": {
	    "input_1": {
	      "id": "i1",
	      "description": "Description of input_1",
	      "mandatory": true,
	      "publication_flag": "searchable"
	    },
	    "input_2": {
	      "id": "i2",
	      "description": "Description input_2",
	      "mandatory": true,
	      "publication_flag": "searchable"
	    },
	    "input_3": {
	      "id": "i3",
	      "description": "Description of input_3",
	      "mandatory": true,
	      "publication_flag": "public"
	    }
	  },
    "matching_conditions": {
        "and": [
            "input_1","input_2"
        ]
    }
}

Create a .json file (example.json for example) containing your proof schema.

There is the code to create the schema in the Trust Registry :

POST /schemas -H 'Content-Type: application/json' --data '@example.jsonโ€™
Host : "<yourLocalApiInstanceUrl>"

If the schema already exists youโ€™ll get :

{
  "status": 409,
  "message": "ProofSchemaExisting"
}

If it doesnโ€™t, the Trust Registry will send you a 201 response with the details of your schema. The response for the example before is :

{
  "id": "0aaaaa3b",
  "name": "Example",
  "version": "0.1.0",
  "hash_algorithm": "SHA256",
  "tree_height": 2,
  "description": "Example of proof schema",
  "owner": null,
  "namespace": "archipels.io",
  "inputs": [
    "input_1",
    "input_2",
    "input_3",
    null
  ],
  "input_definitions": {
    "input_1": {
      "description": "Description of input_1",
      "standardization_function": "<standardization_function>"
    },
    "input_2": {
      "description": "Description of input_2",
      "standardization_function": "<standardization_function>"
    },
    "input_3": {
      "description": "Description of input_3",
      "standardization_function": "<standardization_function>"
    }
  },
  "metadatum_definitions": {
    "input_1": {
      "id": "i1",
      "description": "Description of input_1",
      "mandatory": true,
      "publication_flag": "searchable"
    },
    "input_2": {
      "id": "i2",
      "description": "Description input_2",
      "mandatory": true,
      "publication_flag": "searchable"
    },
    "input_3": {
      "id": "i3",
      "description": "Description of input_3",
      "mandatory": true,
      "publication_flag": "public"
    }
  },
  "matching_conditions": {
    "and": [
      "input_1",
      "input_2"
    ]
  }
}

Once you have created your proof schema, you can certify proofs using this schema on the Archipels Trust Registry.

b) Certify your own proof

The data you need to create a proof are the inputs for which mandatoryis true.

There is the an example based on the "0aaaaa3b"proof schema created in the part before.

"schema_id": "0aaaaa3b",
"input_1": "<input_1>",
"input_2": "<input_2>",
"input_3": "<input_3>",
"secret" : "<12_characters_optional_secret>"

The secret given is used to generate a nullifier. You can create a proof without giving a secret, but one will be returned after each creation. Please keep these secrets as they are the only data allowing someone to nullify a proof.

WARNING : The secretmust be a random number generated separately and kept safe as this is required to revoke the proof we've just created. A good secret should have a high entropy level. For example : a good secret can be generated as an UUID, a hash or a password generated by a password manager.

For the same proof, making requests one after the other without secret will trigger the creation of a proof twice and generate a new ID every calls.

If one of your inputs is a document hash, you can use the command below to compute the sha256 of your document :

$ openssl dgst -sha256 /<pathToFile>/<nameFile>.<extensionFile>

Then, the input would be

"document_hash": "<"Ox"+"sha256">"

WARNING : make sure to put โ€œ0xโ€ before the "sha256" of your document.

The command you need to create a proof in the Trust Registry are :

  • if you want to create it from data :

POST /proofs -H 'Content-Type: application/json' --data '{ "schema_id": "0aaaaa3b", "secret" : "<12_characters_optional_secret>", "data": { "input_1": "<input_1>","input_2": "<input_2>", "input_3": "<input_3>" }}'
Host : "<yourLocalApiInstanceUrl>"
  • if you want to create it from a .json file (example.json for example) :

Here is the example.json file :

{
"schema_id": "0aaaaa3b",
"data": {
"input_1": "<input_1>",
"input_2": "<input_2>",
"input_3": "<input_3>",
},
"secret": "<12_characters_optional_secret>"
}

And the command :

POST /proofs -H 'Content-Type: application/json' --data '@example.json'
Host : "<yourLocalApiInstanceUrl>"
  • If you want to create a proof directly from a datahash that you computed from a JSON containing all inputs :

POST /proofs/verify -H 'Content-Type: application/json' --data '{ "schema_id": "0aaaaa3b", "data_hash": "<datahash>"}'
Host : "<yourLocalApiInstanceUrl>"

WARNING : If .env file doesn't contain an ISSUER_ID, or a PRIVATE_KEYyou will get a message like this A properly set up identity is required in order to create a proof.

If it doesnโ€™t, the Trust Registry will send you a 202 or response with the details of your proof.

For example, if you want to create a proof with the following .json from the digitalDocument schema of "schema_id" : "c42e2516" , here are the inputs :

{
	"schema_id": "c42e2516",
	"data": {
		"sha256": "0x298d499999f5018b267b703990d8974e54505c69aa16e697a2026205abf3fc85",
		"dateCreated" : "December 24, 2022 23:59:59",
		"expires": "December 24, 2023 23:59:59",
		"creator": "Archipels",
		"category": "PAYSLIP",
		"description": "example"
},
	"secret": "secret_secret_secret"
}

The Trust Registry will return a code 202 response :

{
  "proof": {
    "id": "f9312476003c3bd51a2faefe128ef9affa64ed1e6acd3e35f1d5529651af1e05",
    "commitment": "4eec9aa957ccb0ad3245e04fc61692de43a9d1c02f7b1dabdd7e46466cdae046",
    "commitment_details": {
      "schema_id": "c42e2516",
      "data_hash": "f4303f4da60deebbca059dbda307159c8c6d5d798d8196a2e0a406f09eab2d19",
      "nullifier": "ea3fa1672a240f69a0a0240be9c161f8631d2c5b2a2f9829d68329047bff7051",
      "issuer_id": "17e28cbbde064617391bdac3282c2c50b33f9baba8bb509d60aca557500ab90c",
      "signature": "7e8d405c446a1f982a5b6ebd2f130cc9b35e2675ec79815a69c13c02e327d0132824abc1c944eb4534fa96b0a6653bd1d1ef9a701c49b70ade2004127c458e0e"
    },
    "anchor_id": "0000000000000000000000000000000000000000000000000000000000000001",
    "metadata": {
      "sha256": {
        "value": "298d499999f5018b267b703990d8974e54505c69aa16e697a2026205abf3fc85",
        "inclusion_proof": [
          "51a4fa9b4a39792017db0fe1fa75316741815498106bc515025a78c528a81601",
          "5361724dc6cf58aceba888cd873949d323d30eb7e6a109ddc5b1449c55f4c64e",
          "5850c9cc205646efcc54cc61fa278672f1febac2854e4b1b2cb91acbca7847a3"
        ],
        "publication_flag": "searchable"
      },
      "dateCreated": {
        "value": "2022-12-24T23:59:59",
        "inclusion_proof": [
          "e0f149baa1db0413137dd49ed2ebb4e99086e74fac4d477aedd797f0e594addf",
          "5361724dc6cf58aceba888cd873949d323d30eb7e6a109ddc5b1449c55f4c64e",
          "5850c9cc205646efcc54cc61fa278672f1febac2854e4b1b2cb91acbca7847a3"
        ],
        "publication_flag": "public"
      },
      "expires": {
        "value": "2023-12-24T23:59:59",
        "inclusion_proof": [
          "e15fc0f1e72b93eb4134fafa5a6f81f33c09fc7d95930c51e2cb5cb55f8226df",
          "b2c111f81a0386a62f69cdcee52f782b0720a5a6729148574c3af972ba361111",
          "5850c9cc205646efcc54cc61fa278672f1febac2854e4b1b2cb91acbca7847a3"
        ],
        "publication_flag": "public"
      },
      "creator": {
        "value": "ARCHIPELS",
        "inclusion_proof": [
          "b20d7deaebe7baf78f625ed7b459c99e7ac4721150a97aca327f3ab4af71894d",
          "b2c111f81a0386a62f69cdcee52f782b0720a5a6729148574c3af972ba361111",
          "5850c9cc205646efcc54cc61fa278672f1febac2854e4b1b2cb91acbca7847a3"
        ],
        "publication_flag": "public"
      },
      "category": {
        "value": "PAYSLIP",
        "inclusion_proof": [
          "50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c",
          "2dba5dbc339e7316aea2683faf839c1b7b1ee2313db792112588118df066aa35",
          "f335f8ee2d316e458fc56228318b1d0034580cca9c5447dc3e8f49ce4ec9b1f5"
        ],
        "publication_flag": "public"
      },
      "description": {
        "value": "example",
        "inclusion_proof": [
          "76d74e17240f1c3a5e2dbc56210dbfd5ccb4374be9cafd61cd14aedc9e4a2670",
          "2dba5dbc339e7316aea2683faf839c1b7b1ee2313db792112588118df066aa35",
          "f335f8ee2d316e458fc56228318b1d0034580cca9c5447dc3e8f49ce4ec9b1f5"
        ],
        "publication_flag": "public"
      }
    },
    "accumulator_id": 63793,
    "status": "pending"
  },
  "secret": "secret_secret_secret",
  "qrCodeBase64": "data:image/gif;base64,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"
}

The "status"can be :

  • "pending": Proof saved in the database but is waiting to be registered in our accumulator

  • "registered": Proof saved in our accumulator

  • "included": Proof anchored in the blockchain

The "nullifier" is required along with the "secret" if you choose to revoke a proof.

The "qrCodeBase64"is the url where you can find the QRcode of the proof.

After creating a proof you should verify it. So letโ€™s check the Verify part.

You can aslo revoke it if needed. For that, you can read the next part

3) Revoke proofs

Once revoked, the proof will then be marked as revoked in any future verification. There is the command you need to do it :

POST /proofs/revoke -H 'Content-Type: application/json' --data '{ "nullifier": "<nullifier>", "secret": "<12_characters_optional_secret>", "message": "<reason_for_revocation>"}'
Host : "<yourLocalApiInstanceUrl>"

Note that the "message" is optional, if itโ€™s missing it will automatically be set as "Proof revoked". If it worked, the response will be a code 200 response.

Here is an example of proof revocation and the Trust Registry response:

POST /proofs/revoke -H 'Content-Type: application/json' --data '{"nullifier": "ea3fa1672a240f69a0a0240be9c161f8631d2c5b2a2f9829d68329047bff7051", "secret": "secret_secret_secret" }'
Host : "<yourLocalApiInstanceUrl>"

Response : Code 200

{
  "nullifier": "ea3fa1672a240f69a0a0240be9c161f8631d2c5b2a2f9829d68329047bff7051",
  "secret": "secret_secret_secret",
  "message": "Proof revoked"
}

Derniรจre mise ร  jour