{"id":25944992,"url":"https://github.com/path-check/paper-cred","last_synced_at":"2026-03-07T17:05:07.978Z","repository":{"id":49601401,"uuid":"337247530","full_name":"Path-Check/paper-cred","owner":"Path-Check","description":"Paper-first Verifiable Credentials Specification using QR Codes. ","archived":false,"fork":false,"pushed_at":"2021-10-15T17:31:23.000Z","size":455,"stargazers_count":63,"open_issues_count":0,"forks_count":14,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-03-04T08:22:33.677Z","etag":null,"topics":["qr-codes","uri-formats","verifiable-credentials"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Path-Check.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-09T00:22:47.000Z","updated_at":"2024-07-30T14:43:27.000Z","dependencies_parsed_at":"2022-09-22T00:54:32.022Z","dependency_job_id":null,"html_url":"https://github.com/Path-Check/paper-cred","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Path-Check/paper-cred","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Path-Check%2Fpaper-cred","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Path-Check%2Fpaper-cred/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Path-Check%2Fpaper-cred/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Path-Check%2Fpaper-cred/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Path-Check","download_url":"https://codeload.github.com/Path-Check/paper-cred/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Path-Check%2Fpaper-cred/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30222517,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T17:00:40.062Z","status":"ssl_error","status_checked_at":"2026-03-07T17:00:39.026Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["qr-codes","uri-formats","verifiable-credentials"],"created_at":"2025-03-04T08:20:33.656Z","updated_at":"2026-03-07T17:05:07.962Z","avatar_url":"https://github.com/Path-Check.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Paper-first Verifiable Credentials URI Specification\n[\u003cimg align=\"right\" src=\"demo_qr.png\" data-canonical-src=\"demo_qr.png\" width=\"288px\" title=\"Signed Verifiable Credential\"/\u003e](https://github.pathcheck.org/index.html)\n\n**© 2021 PathCheck Foundation**\u003cbr/\u003e\nAuthors: [Justin Dossey](mailto:justin.dossey@pathcheck.org) and [Vitor Pamplona](vitor.pamplona@pathcheck.org)\u003cbr/\u003e\nStatus: *DRAFT*\u003cbr/\u003e\nDate: Feb 26, 2021\u003cbr/\u003e\n\n# Purpose\n\nThe PathCheck Verifiable QR Specification is an extension of the [W3C Verifiable Credentials Data Model](https://github.com/w3c/vc-data-model) expressed as a URI for the purposes of providing a standardized format of describing Verifiable Credentials within the constraints of the QR specification. This document describes the protocol to create Verifiable Credentials directly as URIs for space-limited alphanumeric-required applications, such as QR Codes, NFC tags and SMS Messages.\n\n## Terms and Definitions\n\nFor the purposes of brevity, this document refers to the following terms which are defined as follows:\n1. **HOLDER**: The **HOLDER** is the party who is receiving the credential from the **ISSUER**\n1. **ISSUER**: The **ISSUER** is the party who delivers the credential to a **HOLDER**.\n1. **VERIFIER**: The **VERIFIER** is the party who reads and verifies the signature of credential.\n\n# General Structure\n\nAll verifiable credentials follow a URI Schema that starts with `CRED:` and a message with: \n\n1. the **type** of the payload, one of the options [here](https://github.com/Path-Check/paper-cred/tree/main/payloads)\n1. the **version** of the payload\n1. the **payload** itself\n1. the **keyId**, a reference to the public key\n1. and a cryptographic **signature** of the payload\n\nThe URI is simply organized in a colon-separated string as:\n```\ncred:type:version:signature:keyId:payload\n```\n\n\nThe **type** field declares the [payload](payloads) type (e.g. `COUPON`, `PASSKEY`, `BADGE` or `STATUS`) and the **version** is a ever-incrementing **NUMERIC** field defining the version of the type of payload. The **payload** block contains the information itself in a pre-defined format. The cryptographic signature is a DER signature in Base32 form, calculated using the private key of the **ISSUER**. \n\n## Payloads\n\nPayload specifications define the syntax and semantic meaning of the fields as well as their order in the serialization process. All payload type specifications must be submitted as pull requests to the [payload](payloads) folder in this repository. The general payload encoding is described in sections below. \n\n## Example\n\nThe example below is a valid credential\n```\nCRED:COUPON:1:GBDAEIIA42QDQ5BDUUXVMSQ4VIMMA7RETIZSXB573OL24M4L67LYB24CZYVQEIIA2EZ5W2QXLR7LUSLQW\n6MLAFV3N7OTT3BDAZCNCRMYBMUYC6WMXMNQ:KEYS.PATHCHECK.ORG:1/5000/SOMERVILLE%20MA%20US/1A/%3E65\n```\n\n# Benefits and Limitations\n\nMain Benefits of this protocol are\n\n1. Extremely small QR Sizes in Alphanumeric (~140 bytes for the average payload)\n    1. Data minimalism by requirements of the application\n    1. Allows for the use of feature phones and low energy chips as scanners. \n    1. It is ideal size and character set to use on SMS, SmartCards and NFC tags\n    1. It's readable by any text file\n1. Freedom of payload specification\n    1. Any new payload can be described and approved in minutes\n    1. Business logic is part of the payload definition as opposed to hidden\n1. Freedom of cryptographic tools to sign for the packages. \n    1. RSA, ECDSA, JWTs and other signature models are supported\n    1. Protocol guarantees easily accessible Public Keys by design\n    1. Public Key files describe the algorithms being used by the issuer\n1. Composability of QRs enable privacy and selective disclosure\n    1. The hash of one QR can be used in another, building a signed chain of QRs\n1. Domain-based trust model\n    1. If users trust `cdc.gov`, they will also trust `keys.cdc.gov` \n    1. There is no need for a centralized issuing authority\n    1. No need to trust app developers or private lists of approved issuers\n1. Enhanced Security\n    1. The signed payload is cryptographically protected and thus impossible to tamper\n1. Freedom of binding\n    1. There's no requirement to bind the credential to a user or proxy models to a user\n    1. Electronic binding with individual wallets is possible when the credential is loaded on an app. \n1. Extremely private  \n    1. The only information online is a public key.\n    1. The protocol does not require centralized servers. \n    1. No exposure to government, no blockchain, no private companies, no trusted lists\n    1. There's no need to manage did's or other private issuing systems\n1. Easy to backup \n    1. A simple picture or a paper copy serves as a backup of the code\n1. Negligible cost per user on all activities\n1. Generalizable: \n    1. Any record/payload can be created and signed in the same format\n1. Free as in beer\n    1. The entire specification is licensed under MIT License\n\nDisadvantages are: \n1. Traceability of the QR Codes is possible by colluding verifiers\n    1. Solutions include generating multiple salted QR Codes to be given away as opposed to one code that is read everywhere\n1. Chance of losing the data if the QR is lost\n    1. The issuer might have a copy of the event record, but it is not a requirement\n    1. Apps and pictures of the card can serve as a backup\n1. No realtime revocation of cards/credentials \n    1. Issuer removes the public key from the domain, invalidating all credentials\n    1. The verifier app needs to wait for the next issuer list (or revocation list) update\n1. The information in the QR itself is not encrypted by design\n    1. Payload specifications can include password-protected fields\n1. Fields are case insensitive by design\n    1. Payloads are encoraged to encode each field in Base32 if case sensitivity is required\n\n# Signing and Hashing\n\nData to be used for signing and hashes is **uppercased**, **percent encoded** and then serialized with a slash-separated (`/`) string in the specified order the payload spec describes. Cryptographic signatures and hashes **MUST** be calculated against encoded versions of the underlying payload, as they appear in the final URI. This permits signature verification before any decoding. \n\nCryptographic tools must sign and verify a SHA256 hash of the UTF-8 byte array of the **uppercased**, **percent-encoded**, slash-separated payload. The resulting signature in Distinguished Encoding Rules (DER - as per ASN.1 encoding rules defined in the [ITU-T X.690, 2002, specification](https://itu.int/itu-t/recommendations/rec.aspx?rec=X.690)) format must be then encoded in Base32URL, a Base32 ([RFC4648](https://tools.ietf.org/html/rfc4648)) without added padding (`=`). The removal of the padding is due to the fact that `=` is not a supported character on both URI and alphanumeric QR codes. \n\n# Public Key Download and Verifing\n\nPublic Keys can be generated using any cryptographic method. Verifiers must implement the cryptographic protocol included in the Public Key PEM File. Any verifier must be able to download a public key of the signer and maintain an indexed local key-value store of approved public keys in PEM format. \n\nThe keyID of the public key can be: \n1. a FQDN to a DNS TXT Record containing the key for download.\n1. a database and key ID to facilitate trusted lists of issuers.\n1. a URL address to download keys from. \n\nBefore validating a signature, verifiers must compute the SHA256 of the payload (as is from the URI) and decode the Base32URL signature. \n\n## 1. DNS TXT Record\n\nWhen the key is placed into DNS TXT records, issuers need to convert their PEM files to remove: \n1. -----BEGIN PUBLIC KEY-----\n1. -----END PUBLIC KEY-----\n2. new line chars or `\\n`, as new line is not a valid character for TXT Records. \n\nIssuers should replace `\\n` with `\\\\n`. Verifiers must convert back from `\\\\n` to `\\n`\n\nMake sure the remaining PEM includes an Object Identifier (OID) in the base64 format. \n\nFor example, the keyId `keys.pathcheck.org` needs a DNS Lookup and has: (`$ dig -t txt keys.pathcheck.org`):\n```\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE6DeIun4EgMBLUmbtjQw7DilMJ82YIvOR\\\\n2jz/IK0R/F7/zXY1z+gqvFXfDcJqR5clbAYlO9lHmvb4lsPLZHjugQ==\n```\n\nVerifiers must then return the content to it's original format by replacing `\\\\n` by the new line character. \n\n## 2. Trusted List of Issuers\n\nThe PathCheck Foundation will keep a list of trusted issuers on this [repository](https://github.com/Path-Check/paper-cred/tree/main/keys). References to this list use the period character (`.`) to separate the id of the public key from the name of the database/folder in this order: `id.folder`\n\nAs an example, the keyId `1a9.pcf` refers to the database at the [PCF](https://github.com/Path-Check/paper-cred/tree/main/keys/PCF) folder and the file name in that database is [1a9.pem](https://github.com/Path-Check/paper-cred/blob/main/keys/PCF/1A9.pem). Each ID must contain the raw PEM file of the issuer. \n\n## 3. Downloadable PEM file\n\nThis keyId is a direct URL reference with the raw PEM file of the public key inside the issuer's website, but without the URL Schema component (`https://`). Host must result the link in **uppercase** format. Verifiers must add `https://` to the URL, download and parse the key.  \n\nFor example, the keyId ```www.pathcheck.org/hubfs/pub``` downloads a file that contains the public key of a ECDSA keypair. \n\n# Payload Encodings\n\nThe payload should be represented as a series of **uppercased**, **percent-encoded** values delimited by the slash (`/`) character. The serialization order is defined in each type of payload specification and key names are omitted. Percent encoding of the upcased payload is used to address QR code character set limitations, while supporting the URI spec. \n\n## Global Data Types\n\nThis document will use the following terms to define data types.\n1. **NUMERIC**: The **NUMERIC** data type is a sequence of integers between 0 and 99999999, inclusive.\n2. **STRING**: The **STRING** data type is a sequence of UTF-8, [NFC Normalized](https://www.unicode.org/faq/normalization.html) characters, up to 255 bytes after encoding.\n3. **HASH**: The **HASH** data type is a sequence of 52 alphanumeric characters containing a base32-encoded hash.\n3. **SIGNATUREBASE32**: The **SIGNATUREBASE32** data type is a sequence of up-to-102 alphanumeric characters containing a base32url-encoded digest.\n4. **DATE**: a date, in [ISO 8601 (YYYYMMDD) Basic Notation](https://en.wikipedia.org/wiki/ISO_8601). Example: `20200201` is 1 February, 2020.\n4. **TIMESTAMP**: a date time, in seconds from Epoch. Example: `1607745600` is `2020-12-12T12:00:00+08:00`.\n5. **SHORTSTRING**: a sequence of US-ASCII characters which is limited to 8 bytes in length.\n6. **SHORTNUMERIC**: a **NUMERIC** with a maximum value of 9.\n7. **PHONE**: a E.164 formatted phone number as string. US-ASCII, maximum 15 characters.\n\n## Percent Encoding\n\nPayload Values are encoded per the standard using [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding). Note that all characters not present in the Alphanumeric QR scheme must be percent encoded. The Alphanumeric QR Code type imposes significant limitations on the data which can be represented, but allows for the generation of a lower-resolution QR code. Smaller QR codes will be scannable with older hardware and lower-resolution scanners, and smaller data sets allow for more aggressive error correction. This promotes usability and equity.\n\n## Case Insensitivity\n\nAll fields (keys as well as values) are case-insensitive in both JSON and URI format. When performing operations such as hash comparison, a case-insensitive comparison function MUST be used. Additionally, the Alphanumeric QR Code character set does not include lowercase characters, so implementations MUST encode output in uppercase only.\n\nFor clarity and ease of reading, examples in this document are given in mixed case. \n\n## Optional Fields\n\nUnfilled fields MUST be submitted as empty between slash (`/`) characters. Only add empty delimiters if there is data after. Given fields A (required), B (optional), C (optional) the implementation MUST follow the following example:\n\n| A | B | C | Output        |\n|-----|-----|-----|---------|\n| `1` |     |     | `1`     |\n| `1` | `2` |     | `1/2`   |\n| `1` | `2` | `3` | `1/2/3` |\n| `1` |     | `3` | `1//3`  |\n\n## Additional Percent Encoding for the  Alphanumeric QR character set\n\nAll characters not present in the Alphanumeric QR scheme must be percent\nencoded when presented in data fields. RFC 2936 requires percent encoding a\nnumber of characters, but some of the characters not required to be encoded are\nnot included in the Alphanumeric QR character set. As a result, those characters\nMUST also be percent encoded. \n\n\u003cdetails\u003e\n  \u003csummary\u003eShow me which characters need encoding\u003c/summary\u003e\n\n### Which Characters Need Encoding?\n\nThe columns in the table below indicate encoding requirements for each\nrepresentable character. Any non-listed characters MUST be percent-encoded. The\n\"URI Requires\" column indicates whether the URI format rules (RFC 2396) requires encoding the character.\nThe \"Alphanumeric QR Requires\" column indicates whether the character is missing from the\nAlphanumeric QR character set (thus, requiring encoding). The \"Must Encode?\" column indicates whether this\nspecification requires percent-encoding of the character. The \"Output Value\"\ncolumn indicates the expected output from processing the listed character.\n\n| Character | URI Requires | Alphanumeric QR Requires | Must Encode? | Output Value |\n| --------- | -------- | --------------- | ---- | ------------ |\n| ` ` | YES | NO  | YES | `%20` |\n| `!` | YES | YES | YES | `%21` |\n| `\"` | YES | YES | YES | `%22` |\n| `#` | YES | YES | YES | `%23` |\n| `$` | YES | NO  | YES | `%24` |\n| `%` | YES | NO  | YES | `%25` |\n| `\u0026` | YES | YES | YES | `%26` |\n| `'` | YES | YES | YES | `%27` |\n| `(` | YES | YES | YES | `%28` |\n| `)` | YES | YES | YES | `%29` |\n| `*` | YES | NO  | YES | `%2A` |\n| `+` | YES | NO  | YES | `%2B` |\n| `,` | YES | YES | YES | `%2C` |\n| `-` | YES | NO  | YES | `%2D` |\n| `.` | YES | NO  | YES | `%2E` |\n| `/` | YES | NO  | YES | `%2F` |\n| `0` | NO  | NO  | NO  | `0`   |\n| `1` | NO  | NO  | NO  | `1`   |\n| `2` | NO  | NO  | NO  | `2`   |\n| `3` | NO  | NO  | NO  | `3`   |\n| `4` | NO  | NO  | NO  | `4`   |\n| `5` | NO  | NO  | NO  | `5`   |\n| `6` | NO  | NO  | NO  | `6`   |\n| `7` | NO  | NO  | NO  | `7`   |\n| `8` | NO  | NO  | NO  | `8`   |\n| `9` | NO  | NO  | NO  | `9`   |\n| `:` | YES | NO  | YES | `%3A` |\n| `;` | YES | YES | YES | `%3B` |\n| `\u003c` | YES | YES | YES | `%3C` |\n| `=` | YES | YES | YES | `%3D` |\n| `\u003e` | YES | YES | YES | `%3E` |\n| `?` | YES | YES | YES | `%3F` |\n| `@` | YES | YES | YES | `%40` |\n| `A` | NO  | NO  | NO  | `A`   |\n| `B` | NO  | NO  | NO  | `B`   |\n| `C` | NO  | NO  | NO  | `C`   |\n| `D` | NO  | NO  | NO  | `D`   |\n| `E` | NO  | NO  | NO  | `E`   |\n| `F` | NO  | NO  | NO  | `F`   |\n| `G` | NO  | NO  | NO  | `G`   |\n| `H` | NO  | NO  | NO  | `H`   |\n| `I` | NO  | NO  | NO  | `I`   |\n| `J` | NO  | NO  | NO  | `J`   |\n| `K` | NO  | NO  | NO  | `K`   |\n| `L` | NO  | NO  | NO  | `L`   |\n| `M` | NO  | NO  | NO  | `M`   |\n| `N` | NO  | NO  | NO  | `N`   |\n| `O` | NO  | NO  | NO  | `O`   |\n| `P` | NO  | NO  | NO  | `P`   |\n| `Q` | NO  | NO  | NO  | `Q`   |\n| `R` | NO  | NO  | NO  | `R`   |\n| `S` | NO  | NO  | NO  | `S`   |\n| `T` | NO  | NO  | NO  | `T`   |\n| `U` | NO  | NO  | NO  | `U`   |\n| `V` | NO  | NO  | NO  | `V`   |\n| `W` | NO  | NO  | NO  | `W`   |\n| `X` | NO  | NO  | NO  | `X`   |\n| `Y` | NO  | NO  | NO  | `Y`   |\n| `Z` | NO  | NO  | NO  | `Z`   |\n| `[` | YES | YES | YES | `%5B` |\n| `\\` | YES | YES | YES | `%5C` |\n| `]` | YES | YES | YES | `%5D` |\n| `^` | YES | YES | YES | `%5E` |\n| `_` | NO  | YES | YES | `%5F` |\n| `{` | YES | YES | YES | `%7C` |\n| `}` | YES | YES | YES | `%7D` |\n| `~` | NO  | YES | YES | `%7E` |\n\u003c/details\u003e\n\n# Implementation Guidance\n\n## Pseudo-Code describing signing and assembling of the URI:\n\nTo sign and assemble URI:\n```js\n$payload = [$number, $total, $city, $phase, $indicator];\nfor ($i = 0; $i \u003c length($payload); $i += 1) do\n  $upcasedValue = upcase($payload[$i]);\n  $encodedValue = percentEncode($payload[$i]);\n  $payload[$i] = $encodedValue;\nend\n\n$payloadString = join('/', $payload);\n$payloadHash = sha256($payloadString.to('utf-8'));\n\n$keyId = $DNS_TXT_FQDN || $URL_TO_PEM_FILE || $REF_TO_DATABASE\n$signatureDER = ecdsaSign($payloadHash);\n\n$signature = b32toB32URL(b32encode($signatureDER))\n$base = join(':', [\"cred\", $type, $version, $signature, $keyId]);\n$upcasedBase = upcase($base);\n\n$uri = $upcasedBase + \":\" + $payloadString;\n```\n\n## Pseudo-Code describing parsing and verifying of the URI:\n\nTo parse and verify a URI:\n```js\n[$schema, $type, $version, $signature, $keyId, $payloadString] = qr.split(':')\n$payload = $payloadString.split('/')\n\n$publicKeyPem = localDB($keyId) || download($keyId)\n$payloadHash = sha256($payloadString.to('utf-8')))\n$signatureDER = b32decode(b32URLtoB32($signature))\n\n$valid = ecdsaVerify($signatureDER, $payloadHash, $publicKeyPem)\n\nfor ($i = 0; $i \u003c length($payload); $i += 1) do\n  $payload[$i] = percentDecode($payload[$i]);  \nend\n```\n\n## Pseudo-Code describing Base32 to Base32URL Mapping\n\nTo remove padding from Base32-encoded strings do: \n```js\n$base32URL = $base32.replaceAll(\"=\", \"\");\n```\n\nTo add padding back to Base32-encoded strings do:\n```js\nswitch ($base32URL.length % 8) {\n    case 2: $base32 = $base32URL + \"======\"; break;\n    case 4: $base32 = $base32URL + \"====\";  break;\n    case 5: $base32 = $base32URL + \"===\"; break;\n    case 7: $base32 = $base32URL + \"=\"; break;\n    default: $base32 = $base32URL;\n}\n```   \n\n## Pseudo-Code to download a list of valid payloads from the GitHub Repo\n```js\n$gitHubTree = \"https://api.github.com/repos/Path-Check/paper-cred/git/trees/\"\n\n$rootDir = JSON.parse(fetch($gitHubTree)).tree\n$payloadsDir = $rootDir.find(element =\u003e element.path === 'payloads');\n\n$payloadDir = JSON.parse(fetch($gitHubTree + $payloadsDir.sha)).tree\n\n$payloadNames = $payloadDir.map(x =\u003e x.path.replaceAll(\".md\",\"\").replaceAll(\".\",\":\"));\n```\n\n## Pseudo-Code to download a list of keys from the GitHub Repo\n```js\n[$id, $database] = $keyId.split('.')\n$gitHubTree = \"https://api.github.com/repos/Path-Check/paper-cred/git/trees/\"\n\n$rootDir = JSON.parse(fetch($gitHubTree + \"main\")).tree\n$keysDir = $rootDir.find(element =\u003e element.path === 'keys')\n\n$databasesDir = JSON.parse(fetch($gitHubTree + $keysDir.sha)).tree\n$databaseDir = $databasesDir.find(element =\u003e element.path === $database)\n\n$pemFiles = JSON.parse(fetch($gitHubTree + $databaseDir.sha)).tree\n$pemFile = $pemFiles.find(element =\u003e element.path === $id+\".pem\")\n\n$publicKeyPem = fetch($gitHubTree + $pemFile.sha)\n```\n\n\n# OpenSource Demos and Snippet files. \n\n* [Signer and Verifiers in HTML/JavaScript](https://github.pathcheck.org/index.html)\n* [Signer and Verifier Snippet in Python](https://github.com/Path-Check/paper-cred-demo/blob/main/verify.py)\n* [Signer and Verifier Snippet in Ruby](https://github.com/Path-Check/paper-cred-demo/blob/main/verify.rb)\n* [Signer and Verifier Snippet in Java](https://github.com/Path-Check/paper-cred-demo/blob/main/verify.java)\n* [Signer and Verifier Snippet in zSh Script](https://github.com/Path-Check/paper-cred-demo/blob/main/verify.sh)\n\n# Contributing\n\n[Issues](https://github.com/Path-Check/paper-cred/issues) and [pull requests](https://github.com/Path-Check/paper-cred/pulls) are very welcome! :)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpath-check%2Fpaper-cred","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpath-check%2Fpaper-cred","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpath-check%2Fpaper-cred/lists"}