npm i -g github-did-cli
^ This means don't trust signatures, messages or software related to this project AND don't import keys that are used for anything else.
github-did-library@ github-did-cli@
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.
npm i -g @github-did/cli
npm i @github-did/lib --save
The github
method is meant to make working with DIDs very simple at the cost
of trusting Github.com 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.
- Go to Github.com and create a new public repo called
ghdid
. - When complete, you should end on a page like https://github.com/USERNAME/ghdid.
Next, you will need to install the cli to complete creating your GitHub DID.
npm i -g @github-did/cli
ghdid init "my-password" https://github.com/USERNAME/ghdid
If you mess up, you can overwrite everything with:
ghdid init "my-password" https://github.com/USERNAME/ghdid --force
Don't worry about this, its all experimental for now (which means be careful!)... This will automatically revoke (according to the DID Spec, not PGP!) all keys associated with your GitHub DID.
This will clone the repo into ~/.github-did/${repo}
. Your wallet will be
created, encrypted and stored:
~/.github-did/wallet.enc
and ~/.github-did/web.wallet.enc
Your DID Document will be:
~/.github-did/${repo}/index.jsonld
;
It will be commited and push automatically by init
.
The auto signer Github action will check the proof
property of the did
document for every commit on master
, verify the validity of the signature, and
automatically commit a valid proof
property if necessary.
In order to use it, you need to set your wallet and password in the Github secrets of your repo: Settings -> Secrets Add a new secret and add two secrets:
- DID_WALLET:
cat ~/.github-did/web.wallet.enc | pbcopy
in order to copy the valud - DID_WALLET_PASSWORD: the password you passed in the init command
Now that your DID Document
is on Github in the correct repo, you can use the
github
did method resolver, and linked data signature verification libraries.
ghdid resolve did:github:OR13
This will resolve the DID to a DID Document by using Github and https.
The signature for the DID Document will be checked.
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 [_, method, identifier] = did.split(':');
if (_ !== 'did') {
throw new Error('Invalid DID');
}
if (method !== 'github') {
throw new Error('Invalid DID, should look like did:github:USERNAME');
}
if (method === 'github') {
const base = 'https://raw.githubusercontent.com/';
const didRepoDir = '/master/index.jsonld';
const url = `${base}${identifier}/ghdid${didRepoDir}`;
return url;
}
};
Notice there is nothing here about this repo
(https://github.com/decentralized-identity/github-did
), this is because the
github
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, or
convince us to change this one. Since this is all highly experimental, expect
this to maybe change in the future.
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": "https://w3id.org/did/v1",
"id": "did:github:OR13",
"publicKey": [
{
"encoding": "application/pgp-keys",
"type": "OpenPgpVerificationKey2019",
"id": "did:github:OR13#kid=ibHP1ksrJp5FQjP7hhmTXV7YE5o5bB6YFoODu9n_82E",
"controller": "did:github:OR13",
"publicKeyPem": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: OpenPGP.js v4.4.7\r\nComment: https://openpgpjs.org\r\n\r\nxk8EXNhPhBMFK4EEAAoCAwSTAb5KPYRzxaQoplpY8olodfbG3OxFqm6ULA6p\r\nvaCxZLKVwd4XCwSL8XcMMrPb78kmDEk0H5/Jl0qpRteRoy8CzRdhbm9uIDxh\r\nbm9uQGV4YW1wbGUuY29tPsJ3BBATCAAfBQJc2E+EBgsJBwgDAgQVCAoCAxYC\r\nAQIZAQIbAwIeAQAKCRAeL9f86407tSxDAP4/dXtxQKQxAsURQmNxwwlD03YM\r\n778dcM753Y4f96jW7QEAkLEDur/hKPLKKdFAi/9TCKNQvr7GVk1wYeYeiHMi\r\nJ/fOUwRc2E+EEgUrgQQACgIDBA7fIkmeQmvaG6a5B3X808pdFStePh7+uevf\r\njWpXbDYYTsxARpBT/xb34m0wrXGo7DEG6pAknQ6NBWiXSWX7qTkDAQgHwmEE\r\nGBMIAAkFAlzYT4QCGwwACgkQHi/X/OuNO7U8gQEAn3/lFx3C7iqzVG2BJgtH\r\n08Oc3h0YPwYnZjM9NXDsvEgA/3v5C28Jhx10RFKi9NDxAPjilwBDOZqYPK/s\r\nW3qWhGNU\r\n=RgYO\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"
},
{
"encoding": "application/pgp-keys",
"type": "OpenPgpVerificationKey2019",
"id": "did:github:OR13#kid=jNeDDagaBn466F-wH26YdQ5_NiabBvOlXTv5xItQakU",
"controller": "did:github:OR13",
"publicKeyPem": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: OpenPGP.js v4.4.7\r\nComment: https://openpgpjs.org\r\n\r\nxk8EXNhPhBMFK4EEAAoCAwRzQtkzDYQJy7xfHE0ld/Yoznx0q5bfVrx51FPG\r\nXzjd28wktnePW+3Riq0+3YUa09mZJWEuGPwrrGGXEqobjlVBzRdhbm9uIDxh\r\nbm9uQGV4YW1wbGUuY29tPsJ3BBATCAAfBQJc2E+EBgsJBwgDAgQVCAoCAxYC\r\nAQIZAQIbAwIeAQAKCRC0BtN9z0XDqWsSAQCso31Utz8xji2B7WUBX+2798ae\r\ncqxSxMPWnOQKenBA0gD+N9Qiq6sQ/sDipXuG7xIg4NH4qpf96xvPwC4hX9Jv\r\n3FzOUwRc2E+EEgUrgQQACgIDBIPkRAFeFOrFMXa4XoZ8+aZb4iXLhce6N0LE\r\nCh3YZNJLwxWVKVCxr8niWq3Fa8RTkLA+F7PvIHjnpgx5UGeqPzgDAQgHwmEE\r\nGBMIAAkFAlzYT4QCGwwACgkQtAbTfc9Fw6nomAEAl+1tioF0BlbTNm3c879W\r\nadI46tXfqHt8T6TGdIsKbmoA/RjOfCUvMT277p+v3aYjROI3M7ygh24jbjzx\r\nKBQj/GIJ\r\n=UGd9\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"
}
],
"authentication": [],
"service": [],
"proof": {
"type": "OpenPgpSignature2019",
"creator": "did:github:OR13#kid=ibHP1ksrJp5FQjP7hhmTXV7YE5o5bB6YFoODu9n_82E",
"domain": "GitHubDID",
"nonce": "9c28424e440806718a5165670f79bbc2",
"created": "2019-05-12T16:53:25.038Z",
"signatureValue": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.4.7\r\nComment: https://openpgpjs.org\r\n\r\nwl0EARMIAAYFAlzYT4UACgkQHi/X/OuNO7WZQAD47BbeS2pgFW/WwPbHvC8I\r\nMfsOFhSJEywkED7uz0E4RwD/RRrsmPPb4S4Z+7D2skjiFtnd2nWd+BXcxvhm\r\nGzKk1FU=\r\n=W/tu\r\n-----END PGP SIGNATURE-----\r\n"
}
}
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.
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.
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
npm i -g firebase-tools lerna
firebase login
firebase init
lerna init
-
Update firebase.json to support lerna folder structure.
Commercial support for this library is available upon request from Transmute: [email protected].