{"id":20182196,"url":"https://github.com/nichoth/fission-did","last_synced_at":"2025-09-21T17:32:23.398Z","repository":{"id":77400024,"uuid":"402300647","full_name":"nichoth/fission-did","owner":"nichoth","description":"What is UCAN?","archived":false,"fork":false,"pushed_at":"2025-08-24T20:01:40.000Z","size":1819,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-24T23:47:03.292Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/nichoth/fission-did#readme","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nichoth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-09-02T05:27:44.000Z","updated_at":"2025-08-24T20:01:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"cd76adc2-9d18-422a-9808-0a2ff8264fac","html_url":"https://github.com/nichoth/fission-did","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nichoth/fission-did","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Ffission-did","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Ffission-did/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Ffission-did/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Ffission-did/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nichoth","download_url":"https://codeload.github.com/nichoth/fission-did/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Ffission-did/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276274700,"owners_count":25614478,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-21T02:00:07.055Z","response_time":72,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-14T02:37:54.675Z","updated_at":"2025-09-21T17:32:23.092Z","avatar_url":"https://github.com/nichoth.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fission did\n\n--------------------------------------------\n\nDID is *who you are*. UCAN is *what you can do*.\n\n\n**how do you create/store DIDs for users?** Maybe a metamask-like extension for key mgmt.\n\n\u003e The idea is to avoid needing an external wallet\n\nhttps://whitepaper.fission.codes/authorization/did-doc\n\nThe DID here is stored by the webnative library. (It will return the same value in any window that calls it). Even more than you might want it to -- the keys are the same in 'incognito' windows and regular windows.\n\nCreate a DID from a public key:\n```js\npublicKeyToDid(publicKey: string, type: KeyType): string\n\nwn.did.publicKeyToDid(state.alicePK.n, \"rsa\"))}\n```\n\n```js\nconst wn = window.webnative\nvar ourDID = await wn.did.ucan()\n\n/**\n* This can be another UCAN which has a bigger, or equal,\n* set of permissions than the UCAN we're building.\n*/\nconst possibleProof = null // or, other UCAN.\n\n// how to get a new DID for testing? The scope of the DID is so global\n// i'm not sure how to make a new one\nconst otherDID = \"did:key:EXAMPLE\"\n\n/**\n* The UCAN, encoded as a string.\n*/\nwn.ucan.build({\n    // audience should be a DID\n    // (audience is a publicKey)\n    audience: otherDID,\n    issuer: ourDID,\n    // facts: [],\n    lifetimeInSeconds: 60 * 60 * 24, // UCAN expires in 24 hours\n    potency: 'APPEND_ONLY',\n    proof: possibleProof\n})\n```\n\n\nSo what about temporary browsers? The use case where you are in a public library and you want to login with a computer that you do not own.\n\n\u003e it's so unlikely that you won't have your phone with you that we've put that out of scope for now. You'd link from your phone to the library computer, and log out (delete the local WebCrypto key \u0026 wipe indexedDB) afterwards\n\n\n----------------------------------------------\n\n\n**How do you associate it with a username?** Any number of ways to do this. \n\nThe public key can be a key in a DB for a user record, because it is universally unique.\n\n```js\nvar pk = wn.did.didToPublicKey(ourDID)\n// =\u003e\n// {\n//    \"publicKey\": \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqT8Zp028N0MQxNVs77P/4cgIjGZdrZSn5hd1lkvFpxooSKDgTeBRoC6nVyyJW6aPJUqkXSJhXWN6V1ftFwPhzL+6aOP/8yRatZ9rmDC8GRv08PD+uvQEInEuJ0/TpI6pKB+qwW+JgdyErk8MRDBJ/JQ58XI/wnzFpgVsEti8Ql8t2XK6ol+CBoZIFHTIM8avbGu7hJX0uHNA8dEfk/fQhM2k3VnnHtS2/cgM6EVO7pp6nDkxW7JqU5LpiPj27uPm/UPOhF4jv9QnYmHUC/P8jF7E0FuFtRfENM09i8eGVl7nZwzB0KToQ1DWtwpZEK6LNc1xMCMvv9mLoSYiEFr6XQIDAQAB\",\n//    \"type\": \"rsa\"\n// }\n```\n\n\n-------------------------------------------\n\n\n**How do you set the permissions in a UCAN appropriately for different sessions?**\n\nUse [wn.ucan.build](https://webnative.fission.app/modules/ucan.html#build) to\ncreate a new UCAN that can be used just for a session. Add the originating\nUCAN as the `proof` field in the call to `wn.ucan.build`. This can be another\nUCAN which has a bigger, or equal, set of permissions than the UCAN we're\nbuilding.\n\nYou can set an expiration for a UCAN also. This is an absolute timestamp --\n`wn.ucan.build({ expiration: timestamp })`\n\nOr set `lifetimeInSeconds: 60 * 60 * 24, // UCAN expires in 24 hours`, for a relative expiration.\n\n\n-----------------------------------------------\n\n\n## permissions\n\nhttps://fission.codes/blog/auth-without-backend/\n\n\u003e What if you want to grant another user or service the ability to perform some action on your behalf? As long as they have a valid UCAN, they can wrap it in another with equal or lesser rights and include the original in the prf field.\n\n'equal or lesser rights' in this context means that your application would need to read both UCANs, and would interpret the 'potency' field and see if a things are allowed according to your own application logic.\n\n----------------------------------------------------------------\n\n## facts\n\nhttps://webnative.fission.app/modules/ucan.html#build\n\n\u003e The facts field gives a UCAN the ability to embed arbitrary data. The only purpose of this data is to be signed with the UCAN chain. This does the authentication of \"a user that can do X, Y, and Z is signing this data\". You can use it for really any signing purpose, including signing challenge text, hash preimages, associating URLs, and so on\n\n\nIn the tests it says 'session key fact' -- https://github.com/fission-suite/webnative/blob/ce2b50fb70a31db1081d8f1655f02b251164c826/tests/ucan/ucan.browser.test.ts#L64\n\nWhat is a session key?\n\n\u003e When we do device linking, we bootstrap a secure authenticated session over WebSockets. The session key is the symmetric key that gets negotiated in the handshake, and we need to authenticate the source of that key. We include it in the facts section of a UCAN (which delegates no permissions) to prove that you have the capabilities of that the linking device wants, and that the symmetric key originated with you. This is all happening inside messages encrypted with that key. Here's the full protocol if you're interested: https://whitepaper.fission.codes/accounts/login/awake\n\n\n\n\n\n---------------------------------------------------\n\n\n\n## pubicKeyToDID\nCreate a DID from a given public key\n\nThis is a typescript file\n\n```\n$ npm test\n\n  public key to DID\n\n    ✔ should create a did from a public key\n    ✔ should create the right did\n\n\n  total:     2\n  passing:   2\n  duration:  4.4s\n```\n\n```ts\nimport * as tape from 'tape'\nimport { KeyType } from '../src/types'\nimport { publicKeyToDid } from '../src'\n\nvar pk = 'w9uL--6pG7GsOGiNF_OE7lulZUn6UJN0j6n4m1V3e12_-vtWE6RW3xPNECkUGy0SI4TYOtxLQA7fO6wgEGKpw1YqmxoAIEGp3CUUNcAEnHIyy7dOyroT0qqjSRHZtkiS3LmJEgggSsWGa7G66t9ahBBZF99giuVEowpu7Lr8fPRTlZrrs06R_Xlp1aM2EN-bSkhW1BAWXpvBJ97ng3_CnseLSxJv98bSI_XbCZdrlVKSSW891wTRzQLHcx3v1AsKp3OTzq-5g4pi7T9Otk_N1gklp1t8uEsg3UInO8kjNu2hTsUNQ6l8vE2OKe7jNH752sqz6sCUcrXEH7DwjcU9nQ'\n\ntape('public key to DID', function (t: tape.Test) {\n    var did = publicKeyToDid(pk, KeyType.RSA)\n    t.ok(did, 'should create a public key')\n    t.equal(did, 'did:key:z14ocYEZPM1ghUVA9SvBRLc2YLnA44wy1k3ExUVwkNSKFSG3FLCf9Fu3fNEZNRdp721h17sxkBagDLUv9u3nbsHhv69mha1zMd857HM5bDh1VdrhDQ1tGmRx7xhCg7pWY1FUQcVWg424emLKVtYt54PGBSvGzcunG4QnWUKcVhgnCD8fUGyc3pZYh4BhCTYJnkAXvikDmQafioqBymXWZ24GnMaWQaCb1o88XBNDrEt1yu6Jh7Qvo5TKJn42VYBEbWMGnumqGHMA9G89yR43sifPsmbtfV1517biu29N7Hskta4WshQ78XEaRMkAcQsV8MVmD9aXHzZfA9nrCMzeJHmYUHP6exfGUXn',\n        'should create the right did')\n    // console.log('did', did)\n    t.end()\n})\n```\n\n\n-------------------------------------------------------\n## make a UCAN\n'User Controlled Authorization Networks'\n\nWe are using the pre-built JS file from fission:\n\n```html\n\u003cscript src=\"https://unpkg.com/webnative@0.26.1/dist/index.umd.min.js\"\u003e\u003c/script\u003e\n```\n\nIn our application code, we want to create a UCAN token:\n```js\nconst wn = window.webnative\n\nwn.did.ucan()\n    .then(ourDID =\u003e {\n    })\n```\n\nThis UCAN/DID is your identity. It is created with the webCrypto API, which\nmeans that the public key is visible to us, but we have no way to access the \nrelated private key. You can sign and verify messages by using an API.\n\nThe DID is an easy to serialize string so it can be moved easily to \ndifferent backends.\n\n## sign messages with the DID\nTo sign or verify messages, you can use the keystore API. This uses the same\nkey pair that was created for the UCAN above. It is the same keypair used\nin your DID.\n\n```js\nwn.keystore.create()\n    .then(async ks =\u003e {\n        // this is the same public key that is used in your DID\n        const writeKey = await ks.publicWriteKey()\n\n        var sig = await ks.sign('my message')\n\n        // ks.verify requires a public key and a signature to tell if\n        // a given signature is valid for a given message\n        var isValid = await ks.verify('my message', sig, writeKey)\n        console.log('is valid signature?', isValid)\n    })\n```\n\n--------------------------------\n\nAt this point you have an identity (a public/private key pair), and you\ncan use your ID to sign messages. That's everything you need to create\na signed merkle list, for example.\n\n\n\n-------------------------------------------------------\n\n\n\n## vvvvv some notes vvv\n\nWhat is UCAN?\n\n'User Controlled Authorization Networks'\n\nsee\n* [blog](https://fission.codes/blog/auth-without-backend/)\n* [https://talk.fission.codes/](https://talk.fission.codes/t/user-controlled-authorization-networks-ucan-resources/1122)\n* [the fission guide](https://guide.fission.codes/ucan)\n* [whitepaper](https://whitepaper.fission.codes/authorization/id-overview)\n* [API docs](https://webnative.fission.app/)\n* [w3c did:key method](https://w3c-ccg.github.io/did-method-key/)\n* [w3c did docs](https://www.w3.org/TR/did-core/)\n* [fission webnative repo](https://github.com/fission-suite/webnative)\n* [Lightweight Credentials for Offers with UCAN](https://fission.codes/blog/lightweight-credentials-ucan/)\n* [UCAN (do) secure key management in the browser, with Ben Bollen](https://talk.fission.codes/t/ucan-do-secure-key-management-in-the-browser-with-ben-bollen/1214)\n* [AWAKE](https://whitepaper.fission.codes/accounts/login/awake)\n\n--------------------------------\n\n\u003e What is the API for working with the private key (as opposed to the UCAN API)?\nThere's the WebCrypto API (which is a standard browser API). We also have a wrapper for key management called keystore-idb.\n\n------------------------------------------\n\n\u003e Everything that a users is allowed to do is captured directly in a key or token, and can be sent to anyone that knows how to interpret this format.\n\n## start\nThis will use budo/browserify to build a local JS file, and it links via `\u003cscript\u003e` tag to the `webnative` library.\n```\n$ npm start\n```\n\nVisit the web page on **localhost**, not the given IP address. It's necessary to use localhost for the webCrypto API.\n\n## rollup\n\n```\n$ npm run roll\n\n[!] Error: 'CryptoSystem' is not exported by node_modules/keystore-idb/types.js, imported by node_modules/webnative/lib/keystore.js\n```\n\n\n----------------------------------------------------\n\n\n## using \u003cscript\u003e in html\n\n**this one seems to work**\n\npublic/index.html\n```\n\u003cscript src=\"https://unpkg.com/webnative@0.26.1/dist/index.umd.min.js\"\u003e\u003c/script\u003e\n```\n\n`/example.js`\n```\nconst wn = window.webnative\n```\n\nStart a local server\n```\n$ npm start\n```\n\n\n-------------------------------------------------------\n\n\n## browserify\n\n```\n$ npm run build-js-br\n\nSyntaxError: /Users/nick/code/fission-did/node_modules/webnative/lib/index.js: Export namespace should be first transformed by `@babel/plugin-proposal-export-namespace-from`.\n  132 | export * from \"./common/version.js\";\n  133 | export const fs = FileSystem;\n\u003e 134 | export * as apps from \"./apps/index.js\";\n      |        ^^^^^^^^^\n\n```\n\nBut we already are using `@babel/plugin-proposal-export-namespace-from`\n\n\n----------------------------------------------------------\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichoth%2Ffission-did","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnichoth%2Ffission-did","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichoth%2Ffission-did/lists"}