{"_attachments":{},"_id":"blockchain-profile","_rev":"1576806-61f420bbbd98d8676f68f179","author":{"name":"Halfmoon Labs, Inc."},"description":"Blockchain ID Profile Generator","dist-tags":{"latest":"0.3.2"},"license":"MIT","maintainers":[{"name":"shea256","email":"ryan@shea.io"},{"name":"ablankstein","email":"aaron@blockstack.com"}],"name":"blockchain-profile","readme":"# Blockchain Profile JS\n\n[![CircleCI](https://img.shields.io/circleci/project/blockstack/blockchain-profile-js.svg)](https://circleci.com/gh/blockstack/blockchain-profile-js)\n[![npm](https://img.shields.io/npm/l/blockchain-profile.svg)](https://www.npmjs.com/package/blockchain-profile)\n[![npm](https://img.shields.io/npm/v/blockchain-profile.svg)](https://www.npmjs.com/package/blockchain-profile)\n[![npm](https://img.shields.io/npm/dm/blockchain-profile.svg)](https://www.npmjs.com/package/blockchain-profile)\n[![Slack](http://slack.blockstack.org/badge.svg)](http://slack.blockstack.org/)\n\n## Contents\n\n* [Types](#types)\n * [Person](#person)\n * [Organization](#organization)\n * [CreativeWork](#creative-work)\n* [Registration](#registration)\n * [Create a Profile Object](#create-a-profile-object)\n * [Create a Token File](#create-a-token-file)\n * [Create a Zone File](#create-a-zone-file)\n * [Reconstruct a Profile](#reconstruct-a-profile)\n* [Overview](#Overview)\n * [Usernames](#usernames)\n * [Profiles](#profiles)\n - [Example Profile](#example-profile) \n * [Profile Storage](#profile-storage)\n * [Lookups](#lookups)\n * [Zone Files](#zone-files)\n - [Example Zone File](#example-zone-file) \n * [Token Files](#token-files)\n - [Example Token File](#example-token-file)\n\n## Types\n\n### Person\n\n```js\nvar person = new Person()\nperson.setName(\"Naval\", \"Ravikant\")\nperson.setDescription(\"Co-founder of AngelList\")\nperson.setImage(\"avatar\", \"https://pbs.twimg.com/profile_images/3696617328/667874c5936764d93d56ccc76a2bcc13.jpeg\")\nperson.setSocialAccount(\"facebook\", \"navalr\", \"https://facebook.com/navalr/posts/10152190734077261\")\nperson.setSocialAccount(\"twitter\", \"naval\", \"https://twitter.com/naval/status/486609266212499456\")\nperson.setEmployer(\"angellist.id\", \"Angel List\")\nperson.setFriend(\"muneeb.id\", \"Muneeb Ali\")\nperson.setFriend(\"ryan.id\", \"Ryan Shea\")\nconsole.log(person.profile)\n{\n \"@type\": \"Person\",\n \"name\": \"Naval Ravikant\",\n \"image\": [\n {\n \"@type\": \"ImageObject\",\n \"name\": \"avatar\",\n \"contentUrl\": \"https://pbs.twimg.com/profile_images/3696617328/667874c5936764d93d56ccc76a2bcc13.jpeg\"\n }\n ]\n \"account\": [\n {\n \"@type\": \"Account\",\n \"service\": \"facebook\",\n \"identifier\": \"navalr\",\n \"proofType\": \"http\",\n \"proofUrl\": \"https://facebook.com/navalr/posts/10152190734077261\"\n },\n {\n \"@type\": \"Account\",\n \"service\": \"twitter\",\n \"identifier\": \"naval\",\n \"proofType\": \"http\",\n \"proofUrl\": \"https://twitter.com/naval/status/486609266212499456\"\n }\n ],\n \"worksFor\": [\n {\n \"@type\": \"Organization\",\n \"name\": \"AngelList\",\n \"id\": \"angellist.id\"\n }\n ],\n \"knows\": [\n {\n \"@type\": \"Person\",\n \"name\": \"Muneeb Ali\",\n \"id\": \"muneeb.id\"\n },\n {\n \"@type\": \"Person\",\n \"name\": \"Ryan Shea\",\n \"id\": \"ryan.id\"\n }\n ]\n}\n```\n\n### Organization\n\n```js\nvar organization = new Organization()\norganization.setName(\"AngelList\")\norganization.setEmployee(\"naval.id\", \"Naval Ravikant\")\nconsole.log(organization.profile)\n{\n \"@type\": \"Organization\",\n \"name\": \"AngelList\",\n \"employee\": [\n {\n \"@type\": \"Person\",\n \"name\": \"Naval Ravikant\",\n \"id\": \"naval.id\"\n }\n ]\n}\n```\n\n### Creative Work\n\n```js\nvar creativeWork = new CreativeWork()\ncreativeWork.setName(\"Balloon Dog\")\ncreativeWork.setCreator(\"therealjeffkoons.id\", \"Jeff Koons\")\ncreativeWork.setDateCreated(\"May 9 1994\")\ncreativeWork.setDatePublished(new Date())\nconsole.log(creativeWork.profile)\n{\n \"@type\": \"CreativeWork\",\n \"name\": \"Balloon Dog\",\n \"creator\": [\n {\n \"@type\": \"Person\",\n \"name\": \"Jeff Koons\",\n \"id\": \"therealjeffkoons.id\"\n }\n ],\n \"dateCreated\": \"1994-05-09T00:00:00-0400\",\n \"datePublished\": \"2015-12-10T14:44:26-0500\"\n}\n```\n\n## Registration\n\nFollow these steps to create and register a profile for a Blockchain ID:\n\n1. Create a JSON profile object\n2. Convert the profile object into tokens\n3. Create a zone file that points to the web location of the profile object\n\nBut first, import the required modules:\n\n```js\nvar BlockchainProfile = require('blockchain-profile').BlockchainProfile,\n PrivateKeychain = require('keychain-manager').PrivateKeychain\n```\n\n### Create a Profile Object\n\nThe format for profile objects is based on the formatting found at schema.org.\n\n```js\nvar person = new Person()\nperson.setName(\"Satoshi\", \"Nakamoto\")\nperson.setFriend(\"gavinandresen.id\")\nconsole.log(person.profile)\n{\n \"@type\": \"Person\",\n \"givenName\": \"Satoshi\",\n \"familyName\": \"Nakamoto\",\n \"knows\": [\n {\n \"@type\": \"Person\",\n \"id\": \"gavinandresen.id\"\n }\n ]\n}\n```\n\n### Create a Token File\n\n```js\nvar privateKeychain = new PrivateKeychain()\nvar tokenFile = signProfileTokens(profile, privateKeychain)\n```\n\n### Create a Zone File\n\n```js\nvar publicKeychain = privateKeychain.publicKeychain()\nvar hostUrls = ['https://s3.amazonaws.com/mq9/users/satoshi-nakamoto.json']\nvar checksums = [{ field: 'pgp[0].publicKey', hash: 'e508f0c2c455ab79a4fabc4b51aa537e123c08abee40a87c47e6705a2bbae4ae', algorithm: 'SHA256' }]\nvar zoneFile = createZoneFile('satoshi.id', publicKeychain, hostUrls, checksums)\n```\n\n### Reconstruct a Profile\n\n```js\nvar profile = getProfileFromTokens(tokenFile, publicKeychain)\nconsole.log(profile)\n{\n \"@type\": \"Person\",\n \"givenName\": \"Satoshi\",\n \"familyName\": \"Nakamoto\",\n \"knows\": [\n {\n \"@type\": \"Person\",\n \"id\": \"gavinandresen.id\"\n }\n ]\n}\n```\n\n## Overview\n\n### Usernames\n\nA blockchain ID = a name + a profile, registered on a blockchain.\n\nLet's say you register the username 'alice' within the 'id' namespace, the default namespace for usernames. Then your username would be expressed as `alice.id`.\n\n### Profiles\n\nProfile schema is taken from schema.org. The schema for a person record can be found at http://schema.org/Person. There are some fields that have yet to be included, like the \"account\", \"key\", \"policy\", \"id\", and \"publicKey\" fields. An updated schema definition will be published to a different location that superclasses the schema.org Person definition and adds these fields.\n\n#### Example Profile\n\n```json\n{\n \"name\": \"Naval Ravikant\",\n \"accounts\": []\n}\n```\n\n[](/docs/Person/profile.md)\n\n### Profile Storage\n\nBlockchain ID profiles are stored in two files: a token file and a zone file:\n\n+ **token file** - contains signed tokens with profile data\n+ **zone file** - describes where to find the token file\n\n### Lookups\n\nAn identity lookup is performed as follows:\n\n1. lookup the name in blockstore's name records and get back the data hash associated with the name\n2. lookup the data hash in the blockstore DHT and get back the zone file\n3. scan the zone file for \"zone origin\" records and get the URL found in the \"data\" field - the token file URL\n4. issue a request to the token file URL and get back the token file\n5. parse through the token file for tokens and verify that all the tokens have valid signatures and that they can be tied back to the user's name (by using the public keychain)\n6. grab all of the claims in the tokens and merge them into a single JSON object, which is the user's profile\n\n### Zone Files\n\nA zone file contains an origin (the name registered), a TTL (not yet supported), and a list of records.\n\nEach record has a name, class, type, data, and checksums.\n\nIf the value of the \"name\" field is \"@\", that means the record corresponds to the \"zone origin\" of the name.\n\nThe \"class\" field corresponds to the namespace of the record's information. In ICANN DNS, this is traditionally \"IN\" for Internet, but this field could be changed to something else to indicate that the names are registered in a parallel DNS universe.\n\nThe \"type\" field indicates how the record should be resolved. Only \"CNAME\" is currently supported. This means that the name record should be interpreted as an alias of the URL that is provided in the \"data\" field.\n\nThe \"data\" field is interpretted in different ways, depending on the value in the \"type\" field. As mentioned previously, though, the only supported type at the moment is \"CNAME\", so the \"data\" field will contain a URL until that changes.\n\nThe \"checksums\" field indicates values in the parsed profile that should be considered \"immutable\" fields. One can be certain that the values of these fields cannot change because the values of their hashes must correspond to the corresponding values in the checksum records.\n\nThe \"publicKeychain\" field indicates the keychain that was used to sign the tokens found in the token file.\n\n#### Example Zone File\n\n```json\n{\n \"origin\": \"alice.id\",\n \"ttl\": \"1h\",\n \"records\": [\n ]\n}\n```\n\n[](/docs/Person/zone-file.md)\n\n### Token Files\n\nThe token file contains a list of token records.\n\nEach record contains the encoded token, a \"data\" field with the decoded token, a \"chainPath\" that indicates how to get from the master public keychain to the signing public key, and an \"encrypted\" field that indicates whether or not the token is encrypted.\n\nTo validate each identity token, first decode the token and grab the public key of the issuer. Then, verify the token's signature with the public key. Then check to make sure you can derive the public key from the master public keychain using the chain path. If these checks pass, the token is valid.\n\nEach token in the token file has a header, a payload, and a signature. The payload is the important part. Each payload contains a \"claim\", a \"subject\", and an \"issuer\". The claim is the signed bit of information that goes into the construction of the profile. The subject references the identity that the claim is about. The issuer is the identity that is signing the token (and thus making a claim about the subject).\n\nIn the case of self-attested profile information, the subject and the issuer are the same person (one is making a statement about one's self).\n\nHowever, this can be extended to any statement made by any issuer about any other subject. For example, you can sign a statement attesting to your own birth date, and then your state DMV or bank can sign a statement making the same attestation about your birth date. Then, you can present those two signed statements to any other party and present proof of your birth date.\n\nThe cool part is that the identities referenced are public keys, not usernames. That means that you can present signed tokens to a party that show proof of your birth date, all without revealing your username and thus your identity. This process is known as selective disclosure of identity information.\n\n#### Example Token File\n\n```json\n[\n {\n \"token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjbGFpbSI6eyJuYW1lIjoiUnlhbiBTaGVhIiwiZ2l2ZW5OYW1lIjoiUnlhbiIsImZhbWlseU5hbWUiOiJTaGVhIn0sInN1YmplY3QiOnsiQHR5cGUiOiJQZXJzb24iLCJwdWJsaWNLZXkiOiIwM2QzOWI2YzM5NzEwOWFmYTNhZTE4NDRiMjEzMjE1NmE0YmYyMzYxN2ZlOTEzMmYwZmFjYzM4Y2NmOTQ1MmVhODYifSwiaXNzdWVyIjp7IkB0eXBlIjoiUGVyc29uIiwicHVibGljS2V5IjoiMDNkMzliNmMzOTcxMDlhZmEzYWUxODQ0YjIxMzIxNTZhNGJmMjM2MTdmZTkxMzJmMGZhY2MzOGNjZjk0NTJlYTg2In19.Wqo7GlyisTMRm7xQz98XBp4y_QDTTEQwhtnnoBxsXODupYJlj758rMQEFom2mU5p-WzJwWY8leHgWhoyKa4mXA\",\n \"data\": {\n },\n \"chainPath\": \"9eace0988a7583d45c99ea0058b2687282ebbe4a2862c86aa0e2ed576cd1b49f\",\n \"encrypted\": false\n },\n]\n```\n\n[](/docs/Person/token-file.md)\n\n","time":{"created":"2022-01-28T16:58:35.920Z","modified":"2022-01-28T16:58:35.920Z","0.1.0":"2015-11-26T00:03:46.377Z","0.1.1":"2015-11-26T05:14:00.883Z","0.2.0":"2015-11-27T20:15:49.412Z","0.3.0":"2015-11-27T23:30:17.457Z","0.3.2":"2016-01-19T23:49:49.847Z"},"versions":{"0.1.0":{"name":"blockchain-profile","version":"0.1.0","description":"Blockchain ID Profile Generator","main":"index.js","scripts":{"test":"node test.js"},"repository":{"type":"git","url":"git+https://github.com/blockstack/blockchain-profile-js.git"},"keywords":["blockchain","id","blockchainid","blockchain id","profile","generate","generator","token","identity","blockchain identity","blockchain profile"],"author":{"name":"Halfmoon Labs, Inc."},"license":"MIT","dependencies":{"elliptic-curve":"0.0.1","hasprop":"0.0.3","jwt-js":"^0.5.0","keychain-manager":"^1.3.0","merge-objects":"^1.0.5"},"devDependencies":{"tape":"^4.2.0"},"gitHead":"d69e2c480da8896baab477d7d8d173f05fbcc522","bugs":{"url":"https://github.com/blockstack/blockchain-profile-js/issues"},"homepage":"https://github.com/blockstack/blockchain-profile-js#readme","_id":"blockchain-profile@0.1.0","_shasum":"87d10eff4e443d2bee93349aeb12c9bd039874b1","_from":".","_npmVersion":"3.3.6","_nodeVersion":"5.0.0","_npmUser":{"name":"shea256","email":"ryan@shea.io"},"dist":{"shasum":"87d10eff4e443d2bee93349aeb12c9bd039874b1","tarball":"https://registry.npmmirror.com/blockchain-profile/-/blockchain-profile-0.1.0.tgz","size":39600,"integrity":"sha512-5NYIsdDZ+6rlagutY9DZFZMWddHzWYVOrC30LiIQE/xGQCfA4Tyu4chtacocVPlJdKppScfZ9ziYbg34M1osOg=="},"maintainers":[{"name":"shea256","email":"ryan@shea.io"}],"directories":{},"_cnpmcore_publish_time":"2021-12-23T07:28:13.567Z"},"0.1.1":{"name":"blockchain-profile","version":"0.1.1","description":"Blockchain ID Profile Generator","main":"index.js","scripts":{"test":"node test.js"},"repository":{"type":"git","url":"git+https://github.com/blockstack/blockchain-profile-js"},"keywords":["blockchain","id","blockchainid","blockchain id","profile","generate","generator","token","identity","blockchain identity","blockchain profile"],"author":{"name":"Halfmoon Labs, Inc."},"license":"MIT","dependencies":{"elliptic-curve":"0.0.1","hasprop":"0.0.3","jwt-js":"^0.5.0","keychain-manager":"^1.3.0","merge-objects":"^1.0.5"},"devDependencies":{"tape":"^4.2.0"},"gitHead":"367251f2c1b862e24c9095d824e1e7f491d33140","bugs":{"url":"https://github.com/blockstack/blockchain-profile-js/issues"},"homepage":"https://github.com/blockstack/blockchain-profile-js","_id":"blockchain-profile@0.1.1","_shasum":"b671b8736bffb774d19164f130eb02733400c9c0","_from":".","_npmVersion":"2.1.2","_nodeVersion":"0.10.32","_npmUser":{"name":"shea256","email":"ryan@shea.io"},"dist":{"shasum":"b671b8736bffb774d19164f130eb02733400c9c0","tarball":"https://registry.npmmirror.com/blockchain-profile/-/blockchain-profile-0.1.1.tgz","size":40035,"integrity":"sha512-V5tAoeOhYh0R3sFdzRasEi6u04HhgBdEw2SL62hhrGQdmPds42y43hOmObnJ8r1Ev4jJbW1Njv2QB3pMNNBXsA=="},"maintainers":[{"name":"shea256","email":"ryan@shea.io"}],"directories":{},"_cnpmcore_publish_time":"2021-12-23T07:28:14.654Z"},"0.2.0":{"name":"blockchain-profile","version":"0.2.0","description":"Blockchain ID Profile Generator","main":"index.js","scripts":{"test":"node test.js"},"repository":{"type":"git","url":"git+https://github.com/blockstack/blockchain-profile-js.git"},"keywords":["blockchain","id","blockchainid","blockchain id","profile","generate","generator","token","identity","blockchain identity","blockchain profile"],"author":{"name":"Halfmoon Labs, Inc."},"license":"MIT","dependencies":{"elliptic-curve":"0.0.1","hasprop":"0.0.3","jwt-js":"^0.5.0","keychain-manager":"^1.3.0","merge-objects":"^1.0.5"},"devDependencies":{"tape":"^4.2.0"},"gitHead":"c576a83c85213bf12971032024ba92c0ee2f525c","bugs":{"url":"https://github.com/blockstack/blockchain-profile-js/issues"},"homepage":"https://github.com/blockstack/blockchain-profile-js#readme","_id":"blockchain-profile@0.2.0","_shasum":"855b72f2ef379fc219050b3c5217e82c039690c9","_from":".","_npmVersion":"3.3.6","_nodeVersion":"5.0.0","_npmUser":{"name":"shea256","email":"ryan@shea.io"},"dist":{"shasum":"855b72f2ef379fc219050b3c5217e82c039690c9","tarball":"https://registry.npmmirror.com/blockchain-profile/-/blockchain-profile-0.2.0.tgz","size":41471,"integrity":"sha512-o6/t5iPnrpvRLXwXmazhncXoZb5VJVbOoxBdYjCY6zncAVmGBrLoyy+CFNCM6BTBshFD5dLKoG7V/wII5jGTFg=="},"maintainers":[{"name":"shea256","email":"ryan@shea.io"}],"directories":{},"_cnpmcore_publish_time":"2021-12-23T07:28:15.692Z"},"0.3.0":{"name":"blockchain-profile","version":"0.3.0","description":"Blockchain ID Profile Generator","main":"index.js","scripts":{"test":"node test.js"},"repository":{"type":"git","url":"git+https://github.com/blockstack/blockchain-profile-js.git"},"keywords":["blockchain","id","blockchainid","blockchain id","profile","generate","generator","token","identity","blockchain identity","blockchain profile"],"author":{"name":"Halfmoon Labs, Inc."},"license":"MIT","dependencies":{"elliptic-curve":"0.0.1","hasprop":"0.0.3","jwt-js":"^0.5.0","keychain-manager":"^1.3.0","merge-objects":"^1.0.5"},"devDependencies":{"tape":"^4.2.0"},"gitHead":"42b328f8247db4a6eb863ff53bf9dcea549b9179","bugs":{"url":"https://github.com/blockstack/blockchain-profile-js/issues"},"homepage":"https://github.com/blockstack/blockchain-profile-js#readme","_id":"blockchain-profile@0.3.0","_shasum":"4938299a2af6b8e026a001fed96b597b98e3c875","_from":".","_npmVersion":"3.3.6","_nodeVersion":"5.0.0","_npmUser":{"name":"shea256","email":"ryan@shea.io"},"dist":{"shasum":"4938299a2af6b8e026a001fed96b597b98e3c875","tarball":"https://registry.npmmirror.com/blockchain-profile/-/blockchain-profile-0.3.0.tgz","size":41669,"integrity":"sha512-E+2Tc0gFv5il5DVmYXHOso2AG0IKqAtoSEGDWDIodWZ3NDhlkLOKtLuxFgX7pOoPALi40ZudNrIc0iynoLVpYA=="},"maintainers":[{"name":"shea256","email":"ryan@shea.io"}],"directories":{},"_cnpmcore_publish_time":"2021-12-23T07:28:16.725Z"},"0.3.2":{"name":"blockchain-profile","version":"0.3.2","description":"Blockchain ID Profile Generator","main":"index.js","scripts":{"test":"node test.js"},"repository":{"type":"git","url":"git+https://github.com/blockstack/blockchain-profile-js.git"},"keywords":["blockchain","id","blockchainid","blockchain id","profile","generate","generator","token","identity","blockchain identity","blockchain profile"],"author":{"name":"Halfmoon Labs, Inc."},"license":"MIT","dependencies":{"dateformat":"^1.0.12","elliptic-curve":"0.0.1","hasprop":"0.0.3","jwt-js":"^0.5.0","keychain-manager":"^1.3.0","merge-objects":"^1.0.5"},"devDependencies":{"tape":"^4.2.0"},"gitHead":"d449ed3f23aa42cc0d31b866140a2510083ace2b","bugs":{"url":"https://github.com/blockstack/blockchain-profile-js/issues"},"homepage":"https://github.com/blockstack/blockchain-profile-js#readme","_id":"blockchain-profile@0.3.2","_shasum":"3ced6407b498b5627b6e41976792de1df78ec0dd","_from":".","_npmVersion":"3.3.6","_nodeVersion":"5.0.0","_npmUser":{"name":"shea256","email":"ryan@shea.io"},"dist":{"shasum":"3ced6407b498b5627b6e41976792de1df78ec0dd","tarball":"https://registry.npmmirror.com/blockchain-profile/-/blockchain-profile-0.3.2.tgz","size":44110,"integrity":"sha512-LJHvrePbUDiSAp5WcgoYsxKEWnAEM56dd7GholNaWsj7yphciok1oJZoZNPYWNMyFMkpuDYuKgCGEmQq+GdXEg=="},"maintainers":[{"name":"shea256","email":"ryan@shea.io"}],"directories":{},"_cnpmcore_publish_time":"2021-12-23T07:28:17.770Z"}},"_source_registry_name":"default"}