diff --git a/Metadata/CIP-Certification-Metadata.md b/Metadata/CIP-Certification-Metadata.md index f30b356..d795e4b 100644 --- a/Metadata/CIP-Certification-Metadata.md +++ b/Metadata/CIP-Certification-Metadata.md @@ -44,88 +44,369 @@ End-user will interact with a DApp through a wallet and will be able to check th ## Specification -### Certification providers -Certification providers will present which level of certification was reached and present evidence of the work done. Certification providers will sign the certificate to attest that they have done the work and prevent certificate forgeries. - ### Definitions +- **anchor** - A hash written on-chain that can be used to verify the integrity (by way of a cryptographic hash) of the data that is found off-chain. - **dApp** - A decentralised application that is described by the combination of metadata, certificate and a set of used scripts. - **dApp Store** - A dApp aggregator application which follows on-chain data looking for and verifying dApp metadata claims, serving their users linked dApp metadata. +- **Certification providers** - A company that issues certification certificates on-chain. + +### Certification providers +Certification providers will broadcast on-chain certificates that will represent th level of certification reached and present evidence of the work done. +Certification providers will sign the certificate to attest that they have done the work and prevent certificate forgeries. +### Suggested validations +- `integrity`: The DApp's metadata off-chain shall match the metadata **anchored** on-chain. +- `trust`: The DApp's certification metadata shall be signed by a trusted certfication provider. This means a list of public keys of certification providers needs to be known. It will then be up to the DApp store to decide which certification providers are really trusted and publish a list of their own certification provider. + +### On-chain DApp Certification Certificate +```json +{ + "subject": "d684512ccb313191dd08563fd8d737312f7f104a70d9c72018f6b0621ea738c5b8213c8365b980f2d8c48d5fbb2ec3ce642725a20351dbff9861ce9695ac5db8", + "rootHash": "f08ccc1ee08d034d8317d1d84cab76d3cac48a8466ca9e54a291bb998c49a1732e93280bf04a11293c73195affe4fcaa41f7b27c067396f97f701dd96f72665e", + "metadata": [ + "https://audithouse.io/certification/report.pdf", + "https://greatdapp.com/certification/AuditHouse_report.pdf" + ] + + "schema_version": "1.0", + "type": { + "action": "CERTIFY", + "certificationLevel": "1", + "certificateIssuer": "Audit House LLC" + }, + + "signature": { + "r": "5114674f1ce8a2615f2b15138944e5c58511804d72a96260ce8c587e7220daa90b9e65b450ff49563744d7633b43a78b8dc6ec3e3397b50080", + "s": "a15f06ce8005ad817a1681a4e96ee6b4831679ef448d7c283b188ed64d399d6bac420fadf33964b2f2e0f2d1abd401e8eb09ab29e3ff280600", + "algo": "Ed25519−EdDSA", + "pub": "b7a3c12dc0c8c748ab07525b701122b88bd78f600c76342d27f25e5f92444cde"// Audit House LLC public key + } + + +``` ### Properties -**subject**, an UTF-8 encoded string, is a mandatory field which is an identifier of the claim subject. +`subject`: Identifier of the claim subject (i.e dApp). A UTF-8 encoded string. + +`type`: The type of the claim. This is a JSON object that contains the following properties: + +- `action`: The action that the certificate is asserting. It can take the following values: + - `CERTIFY`: The certificate is asserting that the dApp is being registered for the first time. + [IDEA: Revoke? Update?] + - `certificationLevel`: The certification level, between 1 and 3, in accordance with the Certification Working Group standards for certification level. + - `certificationIssuer`: The name of the certification issuer. -**certLevel**, an integer between 1 and 3, is a mandatory field that represents the level of certification reached in a certificate. -**certificateIssuer**, a string, is a mandatory field that represents the company that has issued the certificate. It will be used with a public list of public keys to ensure that the certificate originates from a trusted certification provider. -**reportURLs**, an array of URLs, is a mandatory field that link to the actual certification report for anyone to read. This ensures transparency in the findings, what was and was not considered in the certification process. +`rootHash`: The hash of the metadata entire tree object. This hash is used by clients to verify the integrity of the metadata tree object. When reading a metadata tree object, the client should calculate the hash of the object and compare it with the rootHash property. If the two hashes don't match, the client should discard the object. The metadata tree object is a JSON object that contains the dApp's metadata. The metadata tree object is described in the next section. -**reportHash**, a string, is a mandatory field that is the blake2b-256 hash of the audit file pointed by the links in **reportURLs**. +This hash is calculated by taking the entire metadata tree object, ordering the keys in the object alphanumerically, and then hashing the resulting JSON string using the **blake2b-256** hashing algorithm. The hash is encoded as a hex string. -**summaryURLs**, an array of URLs, is a mandatory field that link to the actual certification summary for anyone to read. +`metadata`: An array of links to the dApp's metadata. The metadata is a JSON object that contains the dApp's metadata in accordance with [CIP 26](https://cips.cardano.org/cips/cip26/) + +`signature`: The signature of the certificate. The signature is done over the blake2b-256 hash of the certificate. The client should use the public key to verify the signature of the certificate. + + +### Certificate JSON Schema +[TODO: Fully understand the spec for JSON Schema, this is currently taken from CIP72 with some rewritting to fit Certification but I am not fully sure if everything is correctly filled] +```json +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", // [TODO: Not sure about this one] + "$id": "YYY", // [TODO: Not sure about this one] + "title": "Certification", // [TODO: Not sure about this one] + "type": "object", // [TODO: Not sure about this one] + "properties": { + "subject": { + "type": "string", + "description": "Can be anything. Subject of the certification.", + }, + "type": { + "type": "object", + "description": "Describes the certification certificate.", + "properties": { + "action": { + "type": "string", + "description": "Describes the action this certification certificate is claiming. For the moment, only 'CERTIFY' is possible but we want to leave the possibility for new actions in the future" + }, + "certificatioNlevel": { + "type": "integer", + "description": "Integer between 1 and 3 to describe the level of certification this certificate refers to" + }, + "certificateIssuer": { + "type": "string", + "description": "Certification provider name" + } + } + }, + "rootHash": { + "type": "string", + "description": "blake2b hash of the metadata describing the dApp" + }, + "signature": { + "description": "The signature of the certification certificate by the certification provider", + "type": "object", + "properties": { + "r": { + "type": "string", + "description": "hex representation of the R component of the signature" + }, + "s": { + "type": "string", + "description": "hex representation of the S component of the signature" + }, + + }, + "required": ["r", "s", "algo", "pub"] + } + }, + "required": ["subject", "rootHash","type", "signature"] +} +``` + + +### Metadata Label +When submitting the transaction metadata pick the following value for `transaction_metadatum_label`: + + +- `1304`: DApp Certification +[TODO: Pick a number and register it in accordance to [CIP10](https://cips.cardano.org/cips/cip10/)] + +### Off-chain Metadata Format +The Dapp Certification certificate is complemented by off-chain metadata that can be fetched from off-chain metadata servers. + +### Properties -**summaryHash**, a string, is a mandatory field that is the blake2b-256 hash of the summary file pointed by the links in **summaryURLs**. -**disclaimerURLs**, an array of URLs, is a mandatory field that link to the legal disclaimer about the content of the report pointed by **reportURLs** links. +**certificateIssuer**, a string, is a mandatory field that represents the party that has issued the certificate. It will be used with a public list of public keys to ensure that the certificate originates from a trusted certification provider. -**disclaimerHash**, a string, is a mandatory field that is the blake2b-256 hash of the summary file pointed by the links in **disclaimerURLs**. +**report**, an object that contains: +- **reportURLs**, an array of URLs, is a field where each link points to the same actual certification report for anyone to read. This ensures transparency in the findings, what was and was not considered in the certification process.. -**scriptHashes**, containing an ordered list of all scripts that make the DApp, is a mandatory field which can be used as a link to the actual DApp running on-chain. +- **reportHash**, a string, is a field that is the blake2b-256 hash of the report pointed by the links in **reportURLs**. -[TODO: A non example version of the metadata] -[TO ADD: A link to off-chain metadata, with a corresponding blake2b-256 hash] -[TO ADD: A signature of the certificate] -[TO ADD: a schema version so we allow for new schemas without relying on parsers to differentiate them] +**summary**, an object that contains: +- **summaryURLs**, an array of URLs, is a mandatory field that link to the actual certification summary for anyone to read. + +- **summaryHash**, a string, is a mandatory field that is the blake2b-256 hash of the summary file pointed by the links in **summaryURLs**. + +**disclaimer**, an object that contains: +- **disclaimerURLs**, an array of URLs, is a mandatory field that link to the legal disclaimer about the content of the report pointed by **reportURLs** links. + +- **disclaimerHash**, a string, is a mandatory field that is the blake2b-256 hash of the summary file pointed by the links in **disclaimerURLs**. + +**script** an array of objects that represents the whole DApp's on-chain script. Each object is comprised of: +- **fullScriptHash**, a string, is the prefix and script hash or script hash+staking key +- **scriptHash**, a string, is the script hash or script hash+staking key +- **contractAddress**, a string, the script address + + +The off-chain metadata should follow the following schema: + +```json +{ + "$schema": "http://json-schema.org/draft-04/schema#", // [TODO: Not sure about this one] + + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "schemeVersion": { + "type": "string" + }, + "certificationLevel": { + "type": "integer" + }, + "certificateIssuer": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "social": { + "type": "object", + "properties": { + "twitter": { + "type": "string" + }, + "github": { + "type": "string" + }, + "website": { + "type": "string" + } + }, + "required": [ + "website" + ] + }, + }, + "required": [ + "name", + "email", + "social" + ] + }, + "report": { + "type": "object", + "properties": { + "reportURLs": { + "type": "array", + "items": [ + "type": "string" + ] + }, + "reportHash": { + "type": "string" + } + }, + "required": [ + "reportURLs", + "reportHash" + ] + } + "summary": { + "type": "object", + "properties": { + "summaryURLs": { + "type": "array", + "items": [ + "type": "string" + ] + }, + "summaryHash": { + "type": "string" + } + }, + "required": [ + "summaryURLs", + "summaryHash" + ] + } + "disclaimer": { + "type": "object", + "properties": { + "disclaimerURLs": { + "type": "array", + "items": [ + "type": "string" + ] + }, + "disclaimerHash": { + "type": "string" + } + }, + "required": [ + "disclaimerURLs", + "disclaimerHash" + ] + } + "scripts": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "fullScriptHash": { + "type": "string" + }, + "scriptHash": { + "type": "string" + }, + "contractAddress": { + "type": "string" + } + }, + "required": [ + "fullScriptHash", + "scriptHash", + "contractAddress" + ] + } + ] + } + }, + + "required": [ + "subject", + "schemeVersion", + "certificationLevel", + "certificateIssuer", + "report", + "summary", + "disclaimer", + "scripts" + ] +} +``` ### Example + ```json { - "subject": "ABCDEFG1234ABCD", // DApp store needs to ensure the uniqueness of this subject - "certLevel": 1, - "certificateIssuer": "Audit House", + "subject": "d684512ccb313191dd08563fd8d737312f7f104a70d9c72018f6b0621ea738c5b8213c8365b980f2d8c48d5fbb2ec3ce642725a20351dbff9861ce9695ac5db8", + "schemeVersion": "1.0.0", + "certificationLevel": 1, + "certificateIssuer": { + "name": "Audit House LLC", + "email": "contact@audithouse.com" + "link": "https://audithouse.com", + "social": { + "twitter": "twiterHandle", + "github": "githubHandle", + "website": "https://website" + }, + "report": { "reportURLs": [ "https://audithouse.io/certificate.pdf", "ipfs://bafybeiemxfal3jsgpdr4cjr3oz3evfyavhwq" - ] + ], "reportHash": "c6bb42780a9c57a54220c856c1e947539bd15eeddfcbf3c0ddd6230e53db5fdd" - + }, + "summary": { "summaryURLs": [ "https://audithouse.io/summary.pdf", "ipfs://jdke788dejknfezio793029ozoekd707d609478ff65bd8501ab9e68dd98" - ] - + ], "summaryHash": "c57a54220c856c1e947ddd6230e53db5fdd539bd15eec6bb42780a9ddfcbf3c0" - + }, + "disclaimer": { "disclaimerURLs": [ "https://audithouse.io/disclaimer.pdf", "ipfs://ezio5abjwjbikoz4mc3a3dla6ujknf01ab9e68dd98kd707d609478ff6" - ] - - "disclaimerHash": "c57a54220c856c1e947ddd6230e53db5fdd539bd15eec6bb42780a9ddfcbf3c0" - - - "scriptHashes": [ - "0ac61bc5d90aff9dbbc3b1fdeb3650067bf9a6c33598501ab9e68721", - "67bfced3e447c368779ba07d609478f6598aeb6bc1b719bc4e405ea7", - "a5bff83524f65bd0f7a2efffbc5afc476abf51f362dc1f541a4233fa", - "f0acbc5ceeff9fa55634b159494d63980f25134b6a0b90c96fb8c7ed", - "f22349b7611cda615a9b166aef01634a63fc40fdd98fbd1eca2b54e3", ], + "disclaimerHash": "c57a54220c856c1e947ddd6230e53db5fdd539bd15eec6bb42780a9ddfcbf3c0" + } + "scripts": [ + { + "plutusVersion": 1, + "compiler": "plutusTX" + "fullScriptHash": "711dcb4e80d7cd0ed384da5375661cb1e074e7feebd73eea236cd68192", + "scriptHash": "1dcb4e80d7cd0ed384da5375661cb1e074e7feebd73eea236cd68192", + "contractAddress": "addr1wywukn5q6lxsa5uymffh2esuk8s8fel7a0tna63rdntgrysv0f3ms" + }, + { + "plutusVersion": 1, + "compiler": "plutusTX" + "fullScriptHash": "384da5375661cb1e07713eea236cd681921dcb4e80d7cd0ed4e7feebd7", + "scriptHash": "6cd68191dcb4e80d7c5661cb1e074e7feebd73eea232d0ed384da537", + "contractAddress": "addr1wywukn5q6lrdntgrysv0f7a0tna63ymffh23ms5uxsaesuk8s8fel" + } + ] } ``` -[TBD: on/off chain, even useful?] - [TO ADD: Compilation chain, how do we represent that? with versions, compilation options] [TO ADD: Verification tools, how do we represent that? with versions, compilation options] ```json { "compiler": "", // compiler + version + options, compilation options? - "auditSummary": "" // A summary (max 100 words) that can be displayed by the stores "certificationArtifacts": ["", ""] // links to all the certification artifacts test runs, formal proof objects, certification compilation proof object etc. "verificationTools": "", "repository": "", @@ -133,19 +414,16 @@ Certification providers will present which level of certification was reached an } ``` -Certification metadata should be signed by the certification provider. It is assumed that certification providers make available their public keys for signature verification. - The metadata should be discoverable by all certification stakeholders, including end-users, DApp developers, and ecosystem components, such as light wallets and DApp stores. Information should be indexable by certification provider, DApp developer, DApp and DApp version. It should be possible for there to be multiple versions of metadata published by the same certification provider for the same version of a DApp, particularly when a (minor) update of the evidence is necessary. In such a case it should be possible to identify the most recent version of the report for that DApp version. It will also be the case that the same DApp may have certification metadata provided by multiple different certification providers. It should be possible for wallets to identify to users the certification status of a DApp when they are signing a transaction that is being submitted to a deployed DApp. -## Rationale: how does this CIP achieve its goals? - +## Rationale: how does this CIP achieve its goals? An on-chain solution is preferred as it allows for it to be checkable by any stakeholder and immutable.