├── .eslintrc.yml ├── package.json ├── permissions.acl ├── models └── org.example.blockchain.cto ├── README.md └── lib └── logic.js /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | node: true 3 | mocha: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 8 7 | sourceType: 8 | - script 9 | globals: 10 | getFactory: true 11 | getSerializer: true 12 | getAssetRegistry: true 13 | getParticipantRegistry: true 14 | getCurrentParticipant: true 15 | post: true 16 | emit: true 17 | rules: 18 | indent: 19 | - error 20 | - 4 21 | linebreak-style: 22 | - error 23 | - unix 24 | quotes: 25 | - error 26 | - single 27 | semi: 28 | - error 29 | - always 30 | no-unused-vars: 31 | - 0 32 | - args: none 33 | no-console: off 34 | curly: error 35 | eqeqeq: error 36 | no-throw-literal: error 37 | strict: error 38 | dot-notation: error 39 | no-tabs: error 40 | no-trailing-spaces: error 41 | no-useless-call: error 42 | no-with: error 43 | operator-linebreak: error 44 | require-jsdoc: 45 | - error 46 | - require: 47 | ClassDeclaration: true 48 | MethodDefinition: true 49 | FunctionDeclaration: true 50 | yoda: error 51 | no-confusing-arrow: 2 52 | no-constant-condition: 2 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "engines": { 3 | "composer": "^0.20.7" 4 | }, 5 | "name": "file-sharing-system", 6 | "version": "1.0.1", 7 | "description": "Hyperledger Fabric Network for file sharing using Multi-Authority Attribute Based Encryption as the encryption scheme and IPFS as the decentralised storage network", 8 | "scripts": { 9 | "prepublish": "mkdirp ./dist && composer archive create --sourceType dir --sourceName . -a ./dist/file-sharing-system.bna", 10 | "pretest": "npm run lint", 11 | "lint": "eslint .", 12 | "test": "nyc mocha -t 0 test/*.js && cucumber-js" 13 | }, 14 | "keywords": [ 15 | "composer", 16 | "composer-network" 17 | ], 18 | "author": "Jai Tatia", 19 | "email": "jatjai40@gmail.com", 20 | "license": "Apache-2.0", 21 | "devDependencies": { 22 | "composer-admin": "^0.20.7", 23 | "composer-cli": "^0.20.7", 24 | "composer-client": "^0.20.7", 25 | "composer-common": "^0.20.7", 26 | "composer-connector-embedded": "^0.20.7", 27 | "composer-cucumber-steps": "^0.20.7", 28 | "chai": "latest", 29 | "chai-as-promised": "latest", 30 | "cucumber": "^2.2.0", 31 | "eslint": "latest", 32 | "nyc": "latest", 33 | "mkdirp": "latest", 34 | "mocha": "latest" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /permissions.acl: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | rule NetworkAdminUser { 16 | description: "Grant business network administrators full access to user resources" 17 | participant: "org.hyperledger.composer.system.NetworkAdmin" 18 | operation: ALL 19 | resource: "**" 20 | action: ALLOW 21 | } 22 | 23 | rule NetworkAdminSystem { 24 | description: "Grant business network administrators full access to system resources" 25 | participant: "org.hyperledger.composer.system.NetworkAdmin" 26 | operation: ALL 27 | resource: "org.hyperledger.composer.system.**" 28 | action: ALLOW 29 | } 30 | 31 | rule AllParticipantsHaveAccessToAllResources { 32 | description: "Allow all participants to have access to all resources and make transactions" 33 | participant: "ANY" 34 | operation: ALL 35 | resource: "org.example.blockchain.*" 36 | action: ALLOW 37 | } 38 | 39 | rule ReadRessources { 40 | description: "Grant ALL participant full access to system resources" 41 | participant: "org.example.blockchain.**" 42 | operation: ALL 43 | resource: "org.hyperledger.composer.system.**" 44 | action: ALLOW 45 | } 46 | 47 | rule ReadNetwork { 48 | description: "Allow all participants to read network" 49 | participant: "org.hyperledger.composer.system.Participant" 50 | operation: READ 51 | resource: "org.hyperledger.composer.system.Network" 52 | action: ALLOW 53 | } 54 | -------------------------------------------------------------------------------- /models/org.example.blockchain.cto: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | 16 | namespace org.example.blockchain 17 | 18 | asset FileN identified by fileId { 19 | o String fileId 20 | o String encryptedHash 21 | o String encryptedKey 22 | o String serializedAccessPolicy 23 | o String version 24 | --> Node owner 25 | } 26 | 27 | asset Attribute identified by attrName { 28 | o String attrName 29 | o String pKey 30 | } 31 | 32 | /** 33 | * The participant model of a Node 34 | */ 35 | 36 | participant Node identified by nodeId { 37 | o String nodeId 38 | o String nodeName 39 | o String[] attributeList 40 | o String[] attributeKeyList 41 | } 42 | 43 | /** 44 | * The participant model of an Attribute Authority 45 | */ 46 | 47 | participant AttributeAuthority identified by aId { 48 | o String aId 49 | -->Attribute[] attributes 50 | } 51 | 52 | /** 53 | * A transaction which allows Node's to 54 | add/edit files in the network 55 | */ 56 | 57 | transaction FileTransaction { 58 | --> FileN fileN 59 | --> Node node 60 | o String newEncryptedHash 61 | o String newEncryptedKey 62 | o String newSerializedAccessPolicy 63 | } 64 | 65 | /** 66 | * A transaction which lets a data owner obtain 67 | decrypted data of a file if he has the appropriate attributes 68 | */ 69 | 70 | transaction GetFileTransaction { 71 | --> Node node 72 | o String fileId 73 | } 74 | 75 | /** 76 | * A transaction whick takes place between an Attribute Authority 77 | and a Node. 78 | */ 79 | 80 | transaction RequestAttributeTransaction { 81 | -->AttributeAuthority aAuthority 82 | -->Node node 83 | -->Attribute attribute 84 | } 85 | 86 | /** 87 | * Transaction executed by AA for granting attribute key to Node 88 | */ 89 | 90 | transaction GrantAttributeTransaction { 91 | -->AttributeAuthority aAuthority 92 | -->Node node 93 | o String attribute 94 | o String attributeSecretKey 95 | } 96 | 97 | 98 | /** 99 | * A notification event to be emitted whenever 100 | * any file is added 101 | */ 102 | event FileNotification { 103 | --> FileN fileN 104 | } 105 | 106 | 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # file-sharing-system 2 | 3 | Hyperledger Fabric Network for file sharing using Multi-Authority Attribute Based Encryption as the encryption scheme and IPFS as the decentralised storage network 4 | 5 | #### Table of Contents 6 | 7 | 1. [Build](#build) 8 | 1. [Prerequisites](#prerequisites) 9 | 2. [Local Development Tools](#dev-Tools) 10 | 3. [Local Hyperledger Fabric runtime](#fabric-Runtime) 11 | 2. [Setup](#setup) 12 | ## Build 13 | ### Prerequisites 14 | Check [this](https://hyperledger.github.io/composer/latest/installing/installing-prereqs.html) to get the updated list of pre-requisites. They are :- 15 | 1. Docker Engine and Docker Compose 16 | 2. Nodejs and NPM 17 | 3. Git 18 | 4. Python 2.7.x 19 | 20 | For ubuntu you can use:- 21 | ```bash 22 | curl -O https://hyperledger.github.io/composer/latest/prereqs-ubuntu.sh 23 | chmod u+x prereqs-ubuntu.sh 24 | ./prereqs-ubuntu.sh 25 | ``` 26 | ###Dev-Tools 27 | Run the following commands to setup dev-tools:- 28 | ```bash 29 | npm install -g composer-cli 30 | npm install -g composer-rest-server 31 | npm install -g composer-playground 32 | npm install -g yo generator-hyperledger-composer 33 | ``` 34 | ###Fabric-Runtime 35 | Run the following commands to Setup Local Hyperledger fabric Runtime:- 36 | ```bash 37 | mkdir ~/fabric-dev-servers 38 | cd ~/fabric-dev-servers 39 | curl -O https://raw.githubusercontent.com/hyperledger/composer-tools/master/packages/fabric-dev-servers/fabric-dev-servers.tar.gz 40 | tar -xvf fabric-dev-servers.tar.gz 41 | export FABRIC_VERSION=hlfv12 42 | ./downloadFabric.sh 43 | ./startFabric.sh 44 | ./createPeerAdminCard.sh 45 | ``` 46 | ##Setup 47 | 1. Generating a Business Network Archive (BNA) 48 | ```bash 49 | composer archive create --sourceType dir --sourceName . 50 | ``` 51 | 2. Install and Deploy the BNA file 52 | To install execute:- 53 | ```bash 54 | composer network install --archiveFile file-sharing-system@0.0.1.bna --card PeerAdmin@hlfv1 55 | ``` 56 | To deploy:- 57 | ```bash 58 | composer network start --networkName file-sharing-system --networkVersion 0.0.1 --networkAdmin admin --networkAdminEnrollSecret adminpw --card PeerAdmin@hlfv1 --file file-sharing-admin.card 59 | ``` 60 | It then needs to be imported using:- 61 | ```bash 62 | composer card import --file file-sharing-admin.card 63 | ``` 64 | You can check whether the network has been setup using:- 65 | ```bash 66 | composer network ping --card admin@file-sharing-system 67 | ``` 68 | 69 | 3.Setting up a Composer-Rest-Server 70 | To setup a composer rest server run:- 71 | ```bash 72 | composer-rest-server 73 | ``` 74 | specify ``admin@file-sharing-system`` , select ``never use namespaces``, and continue with the default options for the rest. 75 | 76 | The File-Sharing-System network and rest server are up and running. 77 | 78 | ###References 79 | 1. https://medium.freecodecamp.org/how-to-build-a-blockchain-network-using-hyperledger-fabric-and-composer-e06644ff801d 80 | -------------------------------------------------------------------------------- /lib/logic.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Edit file transaction 3 | * @param {org.example.blockchain.FileTransaction} trade 4 | * @transaction 5 | */ 6 | async function editfile(trade) { 7 | if (trade.node.nodeId == trade.fileN.owner.nodeId) { 8 | trade.fileN.encryptedHash = trade.newEncryptedHash 9 | trade.fileN.encryptedKey = trade.newEncryptedKey 10 | trade.fileN.serializedAccessPolicy = trade.newSerializedAccessPolicy 11 | trade.fileN.version = trade.fileN.version + 1 12 | return getAssetRegistry("org.example.blockchain.fileN") 13 | .then(assetRegistry => { 14 | return assetRegistry.update(trade.fileN); // Update the network registry 15 | }) 16 | .then(() => { 17 | let event = getFactory().newEvent( 18 | "org.example.blockchain", 19 | "fileNotification" 20 | ); // Get a reference to the event specified in the modeling language 21 | event.fileN = trade.fileN; 22 | emit(event); // Fire off the event 23 | }); 24 | } 25 | } 26 | 27 | /** 28 | * ModifyAccessPolicy transaction 29 | * @param {org.example.blockchain.FileTransaction} trade 30 | * @transaction 31 | */ 32 | async function modifyAccessPolicy(trade) { 33 | if (trade.node.nodeId == trade.fileN.owner.nodeId) { 34 | trade.fileN.encryptedHash = trade.newEncryptedHash 35 | trade.fileN.encryptedKey = trade.newEncryptedKey 36 | trade.fileN.serializedAccessPolicy = trade.newSerializedAccessPolicy 37 | trade.fileN.version = trade.fileN.version + 1 38 | return getAssetRegistry("org.example.blockchain.fileN") 39 | .then(assetRegistry => { 40 | return assetRegistry.update(trade.fileN); // Update the network registry 41 | }) 42 | .then(() => { 43 | let event = getFactory().newEvent( 44 | "org.example.blockchain", 45 | "fileNotification" 46 | ); // Get a reference to the event specified in the modeling language 47 | event.fileN = trade.fileN; 48 | emit(event); // Fire off the event 49 | }); 50 | } 51 | } 52 | 53 | /** 54 | * Request Attribute transaction 55 | * @param {org.example.blockchain.RequestAttributeTransaction} trade 56 | * @transaction 57 | */ 58 | async function requestAttribute(trade) { 59 | if (true) { //will eventually contain logic for validating whether a node should be granted 60 | //an attribute 61 | } 62 | } 63 | 64 | /** 65 | * Grant Attribute transaction 66 | * @param {org.example.blockchain.GrantAttributeTransaction} trade 67 | * @transaction 68 | */ 69 | async function grantAttribute(trade) { 70 | if (true) { 71 | if (typeof trade.node.attributeKeyList == 'undefined') { 72 | trade.node.attributeKeyList = new Array(); 73 | trade.node.attributeKeyList[0] = trade.attributeSecretKey; 74 | } 75 | else { 76 | trade.node.attributeKeyList.push(trade.attributeSecretKey); 77 | } 78 | if (typeof trade.node.attributeList == 'undefined') { 79 | trade.node.attributeList = new Array(); 80 | trade.node.attributeList[0] = trade.attribute; 81 | } 82 | else { 83 | trade.node.attributeList.push(trade.attribute); 84 | } 85 | return getParticipantRegistry("org.example.blockchain.Node") 86 | .then(participantRegistry => { 87 | return participantRegistry.update(trade.node); // Update the network registry 88 | }); 89 | } 90 | //Updating Attribute. removing requesters 91 | 92 | } 93 | 94 | /** 95 | * Obtain File Data transaction 96 | * @param {org.example.blockchain.GetFileTransaction} trade 97 | * @transaction 98 | */ 99 | 100 | async function obtainFileData(trade) { 101 | return getAssetRegistry('org.example.blockchain.FileN') 102 | .then(function (assetRegistry) { 103 | return assetRegistry.get(trade.fileId); 104 | }) 105 | .then(function (fileN) { 106 | console.log(fileN); 107 | }) 108 | .catch(function (error) { 109 | }); 110 | //Logic To obtain data from IPFS, decrypt it and return it. 111 | } 112 | 113 | 114 | --------------------------------------------------------------------------------