Skip to content
Decentralized Identity with Github
Branch: master
Clone or download
Latest commit 9daf4d4 Mar 15, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
dids ensure all did documents are verfied by ci Jan 15, 2019
firebase use lerna more Jan 18, 2019
packages Merge pull request #18 from transmute-industries/feat/did-auth Mar 15, 2019
.firebaserc use lerna more Jan 18, 2019
.gitignore use lerna more Jan 18, 2019
.travis.yml use lerna more Jan 18, 2019
LICENSE use lerna more Jan 18, 2019 test Feb 15, 2019
firebase.json cleanup Jan 19, 2019
lerna.json use lerna more Jan 18, 2019
package-lock.json Revert "Add eslint" Mar 14, 2019

Github DID

Build Status codecov License GitHub forks GitHub stars

Website · Swagger

🚧 This is experimental, not endorsed by Github, and under development. 🚧

Decentralized Identifiers (DIDs) are a new type of identifier for verifiable, "self-sovereign" digital identity. DIDs are fully under the control of the DID subject, independent from any centralized registry, identity provider, or certificate authority. DIDs are URLs that relate a DID subject to means for trustable interactions with that subject. DIDs resolve to DID Documents — simple documents that describe how to use that specific DID. Each DID Document contains at least three things: cryptographic material, authentication suites, and service endpoints. Cryptographic material combined with authentication suites provide a set of mechanisms to authenticate as the DID subject (e.g., public keys, pseudonymous biometric protocols, etc.). Service endpoints enable trusted interactions with the DID subject.

Install CLI

npm i -g @github-did/cli

Install Library

npm i @github-did/lib --save


The ghdid method is meant to make working with DIDs very simple at the cost of trusting for assisting in resolving DID Documents.

Many developers are familar with Github, and its 2 supported public key cryptosystems, GPG and SSH.

Linked Data Signatures are difficult to work with when operating a server or running a local node of some distributed system / blockchain is a requirement.

The objective of Github DID is to encourage contribution to the DID Spec and Linked Data Signatures, and allow rapid development of extensions to these without requiring the use of slow, or complicated more trustless infrastructure, such as blockchains or other distributed systems.

Getting Started

ghdid init yolo
ghdid addKey yolo

The email goes in your OpenPGP key, the password is used to protect your private key.

This will clone the repo into ~/.github-did/${repo}, where repo is specified by package.json repository (github-did). Your wallet will be created, encrypted and stored:


Your DID Document will be:


Use git to commit your new DID Before proceeding.

cd ~/.github-did/github-did
git add ./dids
git commit -m "add did for"
git push origin master

If you wish to use our repo, you must open a pull request instead.

Now that your DID Document is on Github in the correct repo, you can use the ghdid did method resolver, and linked data signature verification libraries.

ghdid resolve did:ghdid:transmute-industries~github-did~1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a

This will resolve the DID to a DID Document by using Github and https.

The signature for the DID Document will be checked.

What is a DID Method?

const createDID = (method, user, repo, kid) => {
  return `did:${method}:${user}~${repo}~${kid}`;

The method is always ghdid for identifiers of the form ${user}~${repo}~${kid}. If you wish to create your own, please use a different method name, for example ghdid-${ext}, then you can decide how you want to map the github username and repo to a did document. Technically you don't need the kid, you could use the repo as the identifer, for example: did:gh:username~repo, but then you would need a new repo for every new DID. Regardless of your choices, a DID Method links a structured identier to a json-ld document, so if you decide you want to do that in a different way, then you must create a new did method.

How does the DID Resolver work?

A DID Resolver is a simple async function which takes a DID and returns a promise for a DID Document.

This one works, by converting the DID to a path in a git repo and then requesting the json-ld document at that path.

const didToDIDDocumentURL = did => {
  const didToDIDDocumentURL = did => {
  const [_, method, identifier] = did.split(":");
  if (_ !== "did") {
    throw new Error("Invalid DID");
  if (method !== "ghdid") {
    throw new Error("Invalid ghdid");
  const [username, repo, kid] = identifier.split("~");
  const base = "";
  const didRepoDir = "/master/dids";
  return `${base}${username}/${repo}${didRepoDir}/${kid}.jsonld`;

Notice there is nothing here about this repo (, this is because the ghdid method works with any github repo that is public, the identifier includes the details needed to get the did document from dids folder. If you want to create a new folder structure, you must create a new DID method.

What can I do with my DID?

Use your DIDs to test Linked Data Signatures, such OpenPgpSignature2019 which is currently being developed. When DID Documents are signed, they include a proof attribute, which is used to provide proof that someone controlled the private key associated with the public key listed in the did document at the created datetime.

For example:

  "@context": "",
  "id": "did:ghdid:transmute-industries~github-did~1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a",
  "publicKey": [
      "id": "did:ghdid:transmute-industries~github-did~1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a#kid=1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a",
      "type": "OpenPgpSignature2019",
      "owner": "did:ghdid:transmute-industries~github-did~1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a",
      "publicKeyPem": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: OpenPGP.js v4.4.3\r\nComment:\r\n\r\nxk8EXDqOxhMFK4EEAAoCAwQ22JuKLOw0REjgH3KPldvpQLyPbevO6nd/vs/h\r\nUyBgRDFhB66eam0Kg0K/bFspd7EqBQf5sg4MjtW2g+UlMNuAzRMiYWxpY2VA\r\nZXhhbXBsZS5jb20iwncEEBMIAB8FAlw6jsYGCwkHCAMCBBUICgIDFgIBAhkB\r\nAhsDAh4BAAoJEPwxTLocb2BmC2YA+gONpQ3zIBtHR5uxFGwLTVliYwxz5CcD\r\nNfHPz7q+Z+WzAQCuCyYtkwu3y28HhT6YWVm2EQuVnUw6PRgsITeMUTTsWs5T\r\nBFw6jsYSBSuBBAAKAgMENtibiizsNERI4B9yj5Xb6UC8j23rzup3f77P4VMg\r\nYEQxYQeunmptCoNCv2xbKXexKgUH+bIODI7VtoPlJTDbgAMBCAfCYQQYEwgA\r\nCQUCXDqOxgIbDAAKCRD8MUy6HG9gZlq4AQCV3m/C5VI6meml0AHpWCFd9Rlj\r\nwsosaak1gsd+aawnGgEA95414FwaqMWVVbq7hWBHtBOHJiL5ezHxKmEhL7K9\r\nrf8=\r\n=ViJn\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"
  "authentication": [
      "publicKey": "did:ghdid:transmute-industries~github-did~1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a#kid=1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a",
      "type": "OpenPgpSignature2019"
  "proof": {
    "type": "OpenPgpSignature2019",
    "creator": "did:ghdid:transmute-industries~github-did~1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a#kid=1bed11140547b8407478bdf2650db50a5a0c18ef2ae4caf20e818a9433923c2a",
    "domain": "github-did",
    "nonce": "2102e5883aa896c49d205405808a184f",
    "created": "2019-01-13T01:05:11.774Z",
    "signatureValue": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.4.3\r\nComment:\r\n\r\nwl4EARMIAAYFAlw6jsgACgkQ/DFMuhxvYGZGLwEAoSZjSgX9QRBscjHNNpR0\r\nGiIrIrF3W+ixFlCTUCIBqlABAJHApKcMekuQrsq7SNY4vlH2W3vklp9lW7S7\r\nHpLvULmp\r\n=BHgj\r\n-----END PGP SIGNATURE-----\r\n"

How do Linked Data Signatures work?

They provide authentication for JSON-LD Documents, prooving that a DID has signed the document, by attaching a signature which can be verified by resolving the DID Document. Linked Data Signatures are currently being developed and standardized, here's how they typically work:

When a user wants to sign a json-ld document, they ensure that the public key corrosponding to their private key is listed in their did document. In the document above, the public key is in publicKeyPem format and has an id which will become the creator attribute on the signed linked data. In other systems, such as ActivityPub used by Mastodon, DIDs are URLs, but the principle of retrieving cryptographic material from a downloaded json document is the same.

Next a string that will be signed is created from the document and the signatureOptions, which can include properties like nonce, domain, type, creator, etc... This step is called createVerifyData.

Create Verify Data ensures that a json document can be converted to the same hash regardless of the language (python, haskell, go, javascript, etc...). The most common cannonization algorithm is URDNA2015.

You can see how it is used in Mastodon.

Here is the method used in the OpenPgpSignature2019 Proposal.

The final string to be signed is of the following format: ${optionsHash}${documentHash}. Sometimes a signature algorithm will hash this again, be careful to ensure your implementation can verify and generate signatures that are compatible with existing implementations.

When verifying a linked data signature, first the signing key is retrieved from the creator attribute, either over https or using a DID Resolver. Once the key is available the signatureValue in the proof or signature can be verified. Often some encoding transforms are required before the signature can be verified, for example RsaSignature2017 and EcdsaKoblitzSignature2016 use base64 encoding of the result of the signature algorithm. Beware that base64 != base64url, which is commonly used with JWTs.

Danger / Fun

The Linked Data Signature Spec is still evolving, and you may find cases where a signature type such as EcdsaKoblitzSignature2016 is claimed to be used, but where the signatures cannot be verified with libraries such as jsonld-signatures. This is often due to a lack of understanding regarding Linked Data Signature type field. This field should match a value in the ld-cryptosuite-registry. Unfortunatly, this registry is very out of date and does not even contain RsaSignature2017 used by Mastodon, which is probably the mostly widely used signature suite. This can cause developers to make up their own signature type and that will work fine so long as they are the only system verifying and signing. Doing this weakens the JSON-LD Signature spec, making it harder for developers to know what EcdsaKoblitzSignature2016 means, please don't make this worse.

If you would like to develop a new signature suite, like the ones we propose such as OpenPgpSignature2019 and EcdsaKoblitzSignature2019, make sure to make it clear that it is a PROPOSAL, and get it registered once its clearly documented, has test coverage, and supports at least the fields described in terminology.

Help Wanted

The DID Spec is long, and this project does not fully support a DID implementation. If you would like to contribute, or have questions about DIDs, please feel free to open an issue or a PR.


See .travis.yml.

npm i
npm run bootstrap
npm run lint
npm run test
Local API Docs
npm i -g firebase-tools lerna
firebase login
firebase init
lerna init

Commercial Support

Commercial support for this library is available upon request from Transmute:

Related Work

You can’t perform that action at this time.