├── .env.example Sample Environment Variables ├── .gitignore for Node.js Project ├── Basic Test for Identity Management Smart Contract ├── IPFS Helper for Document Storage ├── Identity Management Smart Contract ├── Node.js API for Identity Management System ├── README.md for Blockchain Identity Management System ├── config.json Sample Configuration ├── package.json Configuration └── truffle-config.js for Smart Contract Deployment /.env.example Sample Environment Variables: -------------------------------------------------------------------------------- 1 | # Ethereum Network Configuration 2 | ETHEREUM_NODE=https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID 3 | NETWORK_ID=1 4 | 5 | # Contract Configuration 6 | CONTRACT_ADDRESS=0x123456789...YOUR_DEPLOYED_CONTRACT_ADDRESS 7 | 8 | # IPFS Configuration 9 | IPFS_HOST=ipfs.infura.io 10 | IPFS_PORT=5001 11 | IPFS_PROTOCOL=https 12 | IPFS_PROJECT_ID=YOUR_INFURA_IPFS_PROJECT_ID 13 | IPFS_PROJECT_SECRET=YOUR_INFURA_IPFS_PROJECT_SECRET 14 | 15 | # Server Configuration 16 | PORT=3000 17 | NODE_ENV=development 18 | 19 | # Security 20 | JWT_SECRET=your_jwt_secret_key_here 21 | -------------------------------------------------------------------------------- /.gitignore for Node.js Project: -------------------------------------------------------------------------------- 1 | # Dependency directories 2 | node_modules/ 3 | jspm_packages/ 4 | 5 | # Build outputs 6 | build/ 7 | dist/ 8 | 9 | # Environment variables 10 | .env 11 | .env.local 12 | .env.development.local 13 | .env.test.local 14 | .env.production.local 15 | 16 | # Config with sensitive information 17 | config.json 18 | 19 | # Logs 20 | logs 21 | *.log 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | # Runtime data 27 | pids 28 | *.pid 29 | *.seed 30 | *.pid.lock 31 | 32 | # Directory for uploaded documents (temporary storage) 33 | uploads/ 34 | 35 | # Directory for instrumented libs generated by jscoverage/JSCover 36 | lib-cov 37 | 38 | # Coverage directory used by tools like istanbul 39 | coverage 40 | 41 | # nyc test coverage 42 | .nyc_output 43 | 44 | # Truffle build directory 45 | .coverage_artifacts 46 | .coverage_contracts 47 | 48 | # Hardhat build directory 49 | artifacts 50 | cache 51 | 52 | # Editor directories and files 53 | .idea 54 | .vscode 55 | *.suo 56 | *.ntvs* 57 | *.njsproj 58 | *.sln 59 | *.sw? 60 | 61 | # Mac OS 62 | .DS_Store 63 | 64 | # Compiled smart contracts (these should be generated) 65 | contracts/**/*.json 66 | !contracts/migrations/*.json 67 | 68 | # Keys and secrets 69 | *.pem 70 | keys/ 71 | -------------------------------------------------------------------------------- /Basic Test for Identity Management Smart Contract: -------------------------------------------------------------------------------- 1 | const IdentityManagement = artifacts.require("IdentityManagement"); 2 | const { expectRevert } = require('@openzeppelin/test-helpers'); 3 | 4 | contract("IdentityManagement", accounts => { 5 | const owner = accounts[0]; 6 | const verifier = accounts[1]; 7 | const user1 = accounts[2]; 8 | const user2 = accounts[3]; 9 | 10 | let identityContract; 11 | const testIpfsHash = "QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o"; 12 | 13 | before(async () => { 14 | identityContract = await IdentityManagement.deployed(); 15 | }); 16 | 17 | describe("Contract Initialization", () => { 18 | it("should set the owner correctly", async () => { 19 | const contractOwner = await identityContract.owner(); 20 | assert.equal(contractOwner, owner, "Owner is not set correctly"); 21 | }); 22 | 23 | it("should set the owner as a verifier", async () => { 24 | const isVerifier = await identityContract.verifiers(owner); 25 | assert.equal(isVerifier, true, "Owner should be a verifier"); 26 | }); 27 | }); 28 | 29 | describe("Verifier Management", () => { 30 | it("should allow the owner to add a verifier", async () => { 31 | await identityContract.addVerifier(verifier, { from: owner }); 32 | const isVerifier = await identityContract.verifiers(verifier); 33 | assert.equal(isVerifier, true, "Verifier should be added"); 34 | }); 35 | 36 | it("should prevent non-owners from adding verifiers", async () => { 37 | await expectRevert( 38 | identityContract.addVerifier(user1, { from: verifier }), 39 | "Only the owner can call this function" 40 | ); 41 | }); 42 | 43 | it("should allow the owner to remove a verifier", async () => { 44 | await identityContract.removeVerifier(verifier, { from: owner }); 45 | const isVerifier = await identityContract.verifiers(verifier); 46 | assert.equal(isVerifier, false, "Verifier should be removed"); 47 | }); 48 | 49 | it("should prevent removing the owner as a verifier", async () => { 50 | await expectRevert( 51 | identityContract.removeVerifier(owner, { from: owner }), 52 | "Cannot remove owner as verifier" 53 | ); 54 | }); 55 | }); 56 | 57 | describe("Identity Registration", () => { 58 | it("should register a new identity", async () => { 59 | await identityContract.registerIdentity(testIpfsHash, { from: user1 }); 60 | 61 | const status = await identityContract.getIdentityStatus(user1); 62 | assert.equal(status, 1, "Status should be Pending"); 63 | 64 | const ipfsHash = await identityContract.getIdentityHash(user1); 65 | assert.equal(ipfsHash, testIpfsHash, "IPFS hash should be stored"); 66 | }); 67 | 68 | it("should prevent registering an identity twice", async () => { 69 | await expectRevert( 70 | identityContract.registerIdentity(testIpfsHash, { from: user1 }), 71 | "Identity already registered" 72 | ); 73 | }); 74 | 75 | it("should not allow empty IPFS hash", async () => { 76 | await expectRevert( 77 | identityContract.registerIdentity("", { from: user2 }), 78 | "IPFS hash cannot be empty" 79 | ); 80 | }); 81 | }); 82 | 83 | describe("Identity Verification", () => { 84 | before(async () => { 85 | // Re-add verifier for testing 86 | await identityContract.addVerifier(verifier, { from: owner }); 87 | }); 88 | 89 | it("should verify an identity by an authorized verifier", async () => { 90 | await identityContract.verifyIdentity(user1, { from: verifier }); 91 | 92 | const status = await identityContract.getIdentityStatus(user1); 93 | assert.equal(status, 2, "Status should be Verified"); 94 | 95 | const isVerified = await identityContract.isVerified(user1); 96 | assert.equal(isVerified, true, "Identity should be verified"); 97 | }); 98 | 99 | it("should add the verifier to the list of verifiers for the identity", async () => { 100 | const identityVerifiers = await identityContract.getIdentityVerifiers(user1); 101 | assert.equal(identityVerifiers.length, 1, "Should have one verifier"); 102 | assert.equal(identityVerifiers[0], verifier, "Verifier should be recorded"); 103 | }); 104 | 105 | it("should prevent non-verifiers from verifying identities", async () => { 106 | await identityContract.registerIdentity(testIpfsHash, { from: user2 }); 107 | 108 | await expectRevert( 109 | identityContract.verifyIdentity(user2, { from: user1 }), 110 | "Only authorized verifiers can call this function" 111 | ); 112 | }); 113 | 114 | it("should not verify identities that are not pending", async () => { 115 | await expectRevert( 116 | identityContract.verifyIdentity(user1, { from: verifier }), 117 | "Identity not pending verification" 118 | ); 119 | }); 120 | }); 121 | 122 | describe("Identity Rejection", () => { 123 | it("should reject an identity by an authorized verifier", async () => { 124 | await identityContract.rejectIdentity(user2, { from: verifier }); 125 | 126 | const status = await identityContract.getIdentityStatus(user2); 127 | assert.equal(status, 3, "Status should be Rejected"); 128 | 129 | const isVerified = await identityContract.isVerified(user2); 130 | assert.equal(isVerified, false, "Identity should not be verified"); 131 | }); 132 | 133 | it("should not reject identities that are not pending", async () => { 134 | await expectRevert( 135 | identityContract.rejectIdentity(user2, { from: verifier }), 136 | "Identity not pending verification" 137 | ); 138 | }); 139 | }); 140 | }); 141 | -------------------------------------------------------------------------------- /IPFS Helper for Document Storage: -------------------------------------------------------------------------------- 1 | // ipfsService.js 2 | const { create } = require('ipfs-http-client'); 3 | const fs = require('fs'); 4 | const crypto = require('crypto'); 5 | 6 | /** 7 | * IPFS Helper Service for Identity Document Storage 8 | * This service handles the storage and retrieval of identity documents on IPFS 9 | */ 10 | class IPFSService { 11 | constructor(ipfsConfig = { host: 'ipfs.infura.io', port: 5001, protocol: 'https' }) { 12 | // Initialize IPFS client 13 | this.ipfs = create(ipfsConfig); 14 | this.encryption = new EncryptionService(); 15 | } 16 | 17 | /** 18 | * Upload and encrypt a document to IPFS 19 | * @param {Buffer|string} document - The document to upload 20 | * @param {string} userPublicKey - The user's public key for encryption 21 | * @returns {Promise} - The IPFS hash of the uploaded document 22 | */ 23 | async uploadDocument(document, userPublicKey) { 24 | try { 25 | // Convert to buffer if it's a file path 26 | if (typeof document === 'string' && fs.existsSync(document)) { 27 | document = fs.readFileSync(document); 28 | } 29 | 30 | // Encrypt the document 31 | const encryptedDocument = this.encryption.encrypt(document, userPublicKey); 32 | 33 | // Add the document to IPFS 34 | const result = await this.ipfs.add(encryptedDocument); 35 | return result.path; 36 | } catch (error) { 37 | console.error('Error uploading document to IPFS:', error); 38 | throw error; 39 | } 40 | } 41 | 42 | /** 43 | * Retrieve and decrypt a document from IPFS 44 | * @param {string} ipfsHash - The IPFS hash of the document 45 | * @param {string} privateKey - The private key to decrypt the document 46 | * @returns {Promise} - The decrypted document 47 | */ 48 | async retrieveDocument(ipfsHash, privateKey) { 49 | try { 50 | const chunks = []; 51 | 52 | // Get the document from IPFS 53 | for await (const chunk of this.ipfs.cat(ipfsHash)) { 54 | chunks.push(chunk); 55 | } 56 | 57 | // Combine chunks and decrypt 58 | const encryptedDocument = Buffer.concat(chunks); 59 | return this.encryption.decrypt(encryptedDocument, privateKey); 60 | } catch (error) { 61 | console.error('Error retrieving document from IPFS:', error); 62 | throw error; 63 | } 64 | } 65 | 66 | /** 67 | * Validate a document hash against the stored IPFS document 68 | * @param {string} ipfsHash - The IPFS hash of the document 69 | * @param {Buffer} document - The document to validate 70 | * @param {string} privateKey - The private key to decrypt the document 71 | * @returns {Promise} - True if the document matches the stored one 72 | */ 73 | async validateDocument(ipfsHash, document, privateKey) { 74 | try { 75 | const storedDocument = await this.retrieveDocument(ipfsHash, privateKey); 76 | const storedHash = crypto.createHash('sha256').update(storedDocument).digest('hex'); 77 | const documentHash = crypto.createHash('sha256').update(document).digest('hex'); 78 | 79 | return storedHash === documentHash; 80 | } catch (error) { 81 | console.error('Error validating document:', error); 82 | return false; 83 | } 84 | } 85 | } 86 | 87 | /** 88 | * Encryption Service for secure document storage 89 | */ 90 | class EncryptionService { 91 | /** 92 | * Encrypt data with a public key 93 | * @param {Buffer} data - Data to encrypt 94 | * @param {string} publicKey - Public key 95 | * @returns {Buffer} - Encrypted data 96 | */ 97 | encrypt(data, publicKey) { 98 | // Implementation would use asymmetric encryption 99 | // This is a simplified version for demonstration 100 | const encryptedData = crypto.publicEncrypt( 101 | { 102 | key: publicKey, 103 | padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, 104 | oaepHash: 'sha256' 105 | }, 106 | Buffer.from(data) 107 | ); 108 | 109 | return encryptedData; 110 | } 111 | 112 | /** 113 | * Decrypt data with a private key 114 | * @param {Buffer} encryptedData - Data to decrypt 115 | * @param {string} privateKey - Private key 116 | * @returns {Buffer} - Decrypted data 117 | */ 118 | decrypt(encryptedData, privateKey) { 119 | // Implementation would use asymmetric decryption 120 | const decryptedData = crypto.privateDecrypt( 121 | { 122 | key: privateKey, 123 | padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, 124 | oaepHash: 'sha256' 125 | }, 126 | encryptedData 127 | ); 128 | 129 | return decryptedData; 130 | } 131 | } 132 | 133 | module.exports = IPFSService; 134 | -------------------------------------------------------------------------------- /Identity Management Smart Contract: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | /** 5 | * @title IdentityManagement 6 | * @dev A decentralized identity verification system for financial transactions 7 | */ 8 | contract IdentityManagement { 9 | // Identity status enum 10 | enum IdentityStatus { NotRegistered, Pending, Verified, Rejected } 11 | 12 | // Identity data structure 13 | struct Identity { 14 | address owner; 15 | string ipfsHash; // Hash of the identity documents stored on IPFS 16 | uint256 timestamp; // Time when the identity was registered 17 | IdentityStatus status; 18 | address[] verifiers; // List of addresses that verified this identity 19 | } 20 | 21 | // Mapping from address to identity data 22 | mapping(address => Identity) public identities; 23 | 24 | // List of authorized verifiers 25 | mapping(address => bool) public verifiers; 26 | 27 | // Owner of the contract 28 | address public owner; 29 | 30 | // Events 31 | event IdentityRegistered(address indexed user, string ipfsHash, uint256 timestamp); 32 | event IdentityVerified(address indexed user, address indexed verifier, uint256 timestamp); 33 | event IdentityRejected(address indexed user, address indexed verifier, uint256 timestamp); 34 | event VerifierAdded(address indexed verifier); 35 | event VerifierRemoved(address indexed verifier); 36 | 37 | // Modifiers 38 | modifier onlyOwner() { 39 | require(msg.sender == owner, "Only the owner can call this function"); 40 | _; 41 | } 42 | 43 | modifier onlyVerifier() { 44 | require(verifiers[msg.sender], "Only authorized verifiers can call this function"); 45 | _; 46 | } 47 | 48 | /** 49 | * @dev Constructor sets the owner of the contract 50 | */ 51 | constructor() { 52 | owner = msg.sender; 53 | verifiers[msg.sender] = true; // Owner is also a verifier by default 54 | emit VerifierAdded(msg.sender); 55 | } 56 | 57 | /** 58 | * @dev Add a new verifier 59 | * @param _verifier Address of the verifier to add 60 | */ 61 | function addVerifier(address _verifier) external onlyOwner { 62 | require(_verifier != address(0), "Invalid address"); 63 | require(!verifiers[_verifier], "Verifier already exists"); 64 | 65 | verifiers[_verifier] = true; 66 | emit VerifierAdded(_verifier); 67 | } 68 | 69 | /** 70 | * @dev Remove a verifier 71 | * @param _verifier Address of the verifier to remove 72 | */ 73 | function removeVerifier(address _verifier) external onlyOwner { 74 | require(verifiers[_verifier], "Not a verifier"); 75 | require(_verifier != owner, "Cannot remove owner as verifier"); 76 | 77 | verifiers[_verifier] = false; 78 | emit VerifierRemoved(_verifier); 79 | } 80 | 81 | /** 82 | * @dev Register a new identity 83 | * @param _ipfsHash IPFS hash of the identity documents 84 | */ 85 | function registerIdentity(string calldata _ipfsHash) external { 86 | require(identities[msg.sender].status == IdentityStatus.NotRegistered, "Identity already registered"); 87 | require(bytes(_ipfsHash).length > 0, "IPFS hash cannot be empty"); 88 | 89 | identities[msg.sender] = Identity({ 90 | owner: msg.sender, 91 | ipfsHash: _ipfsHash, 92 | timestamp: block.timestamp, 93 | status: IdentityStatus.Pending, 94 | verifiers: new address[](0) 95 | }); 96 | 97 | emit IdentityRegistered(msg.sender, _ipfsHash, block.timestamp); 98 | } 99 | 100 | /** 101 | * @dev Verify an identity 102 | * @param _user Address of the user to verify 103 | */ 104 | function verifyIdentity(address _user) external onlyVerifier { 105 | require(identities[_user].status == IdentityStatus.Pending, "Identity not pending verification"); 106 | 107 | identities[_user].status = IdentityStatus.Verified; 108 | identities[_user].verifiers.push(msg.sender); 109 | 110 | emit IdentityVerified(_user, msg.sender, block.timestamp); 111 | } 112 | 113 | /** 114 | * @dev Reject an identity 115 | * @param _user Address of the user to reject 116 | */ 117 | function rejectIdentity(address _user) external onlyVerifier { 118 | require(identities[_user].status == IdentityStatus.Pending, "Identity not pending verification"); 119 | 120 | identities[_user].status = IdentityStatus.Rejected; 121 | 122 | emit IdentityRejected(_user, msg.sender, block.timestamp); 123 | } 124 | 125 | /** 126 | * @dev Check if an identity is verified 127 | * @param _user Address of the user to check 128 | * @return bool True if the identity is verified 129 | */ 130 | function isVerified(address _user) external view returns (bool) { 131 | return identities[_user].status == IdentityStatus.Verified; 132 | } 133 | 134 | /** 135 | * @dev Get the verification status of an identity 136 | * @param _user Address of the user to check 137 | * @return status The status of the identity 138 | */ 139 | function getIdentityStatus(address _user) external view returns (IdentityStatus) { 140 | return identities[_user].status; 141 | } 142 | 143 | /** 144 | * @dev Get the IPFS hash of an identity 145 | * @param _user Address of the user to check 146 | * @return string The IPFS hash of the identity documents 147 | */ 148 | function getIdentityHash(address _user) external view returns (string memory) { 149 | return identities[_user].ipfsHash; 150 | } 151 | 152 | /** 153 | * @dev Get the verifiers of an identity 154 | * @param _user Address of the user to check 155 | * @return address[] The list of verifiers 156 | */ 157 | function getIdentityVerifiers(address _user) external view returns (address[] memory) { 158 | return identities[_user].verifiers; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Node.js API for Identity Management System: -------------------------------------------------------------------------------- 1 | // server.js 2 | const express = require('express'); 3 | const bodyParser = require('body-parser'); 4 | const cors = require('cors'); 5 | const Web3 = require('web3'); 6 | const multer = require('multer'); 7 | const path = require('path'); 8 | const fs = require('fs'); 9 | const crypto = require('crypto'); 10 | const IPFSService = require('./services/ipfsService'); 11 | 12 | // Import contract ABI and configuration 13 | const contractABI = require('./contracts/IdentityManagement.json').abi; 14 | const config = require('./config.json'); 15 | 16 | // Initialize Express app 17 | const app = express(); 18 | const PORT = process.env.PORT || 3000; 19 | 20 | // Middleware 21 | app.use(cors()); 22 | app.use(bodyParser.json()); 23 | app.use(bodyParser.urlencoded({ extended: true })); 24 | 25 | // Set up file storage for identity documents 26 | const storage = multer.diskStorage({ 27 | destination: (req, file, cb) => { 28 | const uploadDir = path.join(__dirname, 'uploads'); 29 | if (!fs.existsSync(uploadDir)) { 30 | fs.mkdirSync(uploadDir); 31 | } 32 | cb(null, uploadDir); 33 | }, 34 | filename: (req, file, cb) => { 35 | // Create a unique filename 36 | const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); 37 | cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname)); 38 | } 39 | }); 40 | const upload = multer({ storage }); 41 | 42 | // Initialize Web3 and IPFS 43 | const web3 = new Web3(new Web3.providers.HttpProvider(config.ethereumNode)); 44 | const ipfsService = new IPFSService(config.ipfs); 45 | 46 | // Load contract instance 47 | const contract = new web3.eth.Contract(contractABI, config.contractAddress); 48 | 49 | // Set up API routes 50 | /** 51 | * @route POST /api/identity/register 52 | * @desc Register a new identity 53 | * @access Public 54 | */ 55 | app.post('/api/identity/register', upload.array('documents', 5), async (req, res) => { 56 | try { 57 | const { address, publicKey } = req.body; 58 | 59 | if (!address || !publicKey || !req.files || req.files.length === 0) { 60 | return res.status(400).json({ error: 'Missing required fields' }); 61 | } 62 | 63 | // Generate key pair for the user if not provided 64 | const userAddress = web3.utils.toChecksumAddress(address); 65 | 66 | // Upload all documents to IPFS 67 | const documentHashes = []; 68 | for (const file of req.files) { 69 | const ipfsHash = await ipfsService.uploadDocument(file.path, publicKey); 70 | documentHashes.push(ipfsHash); 71 | 72 | // Remove temporary file after upload 73 | fs.unlinkSync(file.path); 74 | } 75 | 76 | // Create metadata with document references 77 | const metadata = { 78 | documents: documentHashes, 79 | timestamp: Date.now(), 80 | version: '1.0' 81 | }; 82 | 83 | // Upload metadata to IPFS 84 | const metadataBuffer = Buffer.from(JSON.stringify(metadata)); 85 | const metadataHash = await ipfsService.uploadDocument(metadataBuffer, publicKey); 86 | 87 | // Get the account that will send the transaction 88 | const accounts = await web3.eth.getAccounts(); 89 | const senderAccount = accounts[0]; 90 | 91 | // Register identity on the blockchain 92 | const tx = await contract.methods.registerIdentity(metadataHash).send({ 93 | from: senderAccount, 94 | gas: 3000000 95 | }); 96 | 97 | return res.status(201).json({ 98 | success: true, 99 | address: userAddress, 100 | ipfsHash: metadataHash, 101 | transactionHash: tx.transactionHash 102 | }); 103 | } catch (error) { 104 | console.error('Error registering identity:', error); 105 | return res.status(500).json({ error: 'Failed to register identity' }); 106 | } 107 | }); 108 | 109 | /** 110 | * @route GET /api/identity/:address 111 | * @desc Get identity information 112 | * @access Public 113 | */ 114 | app.get('/api/identity/:address', async (req, res) => { 115 | try { 116 | const address = web3.utils.toChecksumAddress(req.params.address); 117 | 118 | // Get identity status from blockchain 119 | const status = await contract.methods.getIdentityStatus(address).call(); 120 | const ipfsHash = await contract.methods.getIdentityHash(address).call(); 121 | 122 | // Map numeric status to string 123 | const statusMap = ['NotRegistered', 'Pending', 'Verified', 'Rejected']; 124 | 125 | return res.status(200).json({ 126 | address, 127 | ipfsHash, 128 | status: statusMap[status], 129 | isVerified: status === '2' 130 | }); 131 | } catch (error) { 132 | console.error('Error retrieving identity:', error); 133 | return res.status(500).json({ error: 'Failed to retrieve identity' }); 134 | } 135 | }); 136 | 137 | /** 138 | * @route POST /api/identity/verify 139 | * @desc Verify an identity 140 | * @access Private (verifiers only) 141 | */ 142 | app.post('/api/identity/verify', async (req, res) => { 143 | try { 144 | const { address, verifierAddress, verifierPrivateKey } = req.body; 145 | 146 | if (!address || !verifierAddress) { 147 | return res.status(400).json({ error: 'Missing required fields' }); 148 | } 149 | 150 | const userAddress = web3.utils.toChecksumAddress(address); 151 | 152 | // Check if the verifier is authorized 153 | const isVerifier = await contract.methods.verifiers(verifierAddress).call(); 154 | if (!isVerifier) { 155 | return res.status(403).json({ error: 'Not authorized as a verifier' }); 156 | } 157 | 158 | // Create and sign the transaction 159 | const tx = await contract.methods.verifyIdentity(userAddress).send({ 160 | from: verifierAddress, 161 | gas: 300000 162 | }); 163 | 164 | return res.status(200).json({ 165 | success: true, 166 | address: userAddress, 167 | verifier: verifierAddress, 168 | transactionHash: tx.transactionHash 169 | }); 170 | } catch (error) { 171 | console.error('Error verifying identity:', error); 172 | return res.status(500).json({ error: 'Failed to verify identity' }); 173 | } 174 | }); 175 | 176 | /** 177 | * @route POST /api/identity/reject 178 | * @desc Reject an identity 179 | * @access Private (verifiers only) 180 | */ 181 | app.post('/api/identity/reject', async (req, res) => { 182 | try { 183 | const { address, verifierAddress, verifierPrivateKey } = req.body; 184 | 185 | if (!address || !verifierAddress) { 186 | return res.status(400).json({ error: 'Missing required fields' }); 187 | } 188 | 189 | const userAddress = web3.utils.toChecksumAddress(address); 190 | 191 | // Check if the verifier is authorized 192 | const isVerifier = await contract.methods.verifiers(verifierAddress).call(); 193 | if (!isVerifier) { 194 | return res.status(403).json({ error: 'Not authorized as a verifier' }); 195 | } 196 | 197 | // Create and sign the transaction 198 | const tx = await contract.methods.rejectIdentity(userAddress).send({ 199 | from: verifierAddress, 200 | gas: 300000 201 | }); 202 | 203 | return res.status(200).json({ 204 | success: true, 205 | address: userAddress, 206 | verifier: verifierAddress, 207 | transactionHash: tx.transactionHash 208 | }); 209 | } catch (error) { 210 | console.error('Error rejecting identity:', error); 211 | return res.status(500).json({ error: 'Failed to reject identity' }); 212 | } 213 | }); 214 | 215 | // Start the server 216 | app.listen(PORT, () => { 217 | console.log(`Server running on port ${PORT}`); 218 | }); 219 | 220 | module.exports = app; 221 | -------------------------------------------------------------------------------- /README.md for Blockchain Identity Management System: -------------------------------------------------------------------------------- 1 | # Blockchain-Based Identity Management System 2 | 3 | A decentralized identity verification system using blockchain technology to enhance security in financial transactions. 4 | 5 | ## Technology Stack 6 | 7 | - **Ethereum** - Blockchain platform for smart contracts 8 | - **Solidity** - Smart contract programming language 9 | - **IPFS** - Decentralized storage for identity documents 10 | - **Node.js** - Backend API and service integration 11 | 12 | ## Overview 13 | 14 | This project implements a decentralized identity management system that allows users to: 15 | 16 | 1. Register their identity documents securely on IPFS 17 | 2. Link document hashes to their Ethereum address 18 | 3. Get their identity verified by authorized verifiers 19 | 4. Use their verified identity for secure financial transactions 20 | 21 | The system uses blockchain to ensure immutability and transparency while keeping sensitive documents securely encrypted in IPFS. 22 | 23 | ## Features 24 | 25 | - **Decentralized Storage**: All documents are stored on IPFS, not on centralized servers 26 | - **Encrypted Documents**: All identity documents are encrypted with the user's public key 27 | - **Verifiable Identities**: Authorized verifiers can confirm the authenticity of identities 28 | - **Smart Contract Control**: Ethereum smart contracts manage the identity lifecycle 29 | - **Privacy-Preserving**: Only hash references stored on-chain, not the actual documents 30 | - **Financial Integration**: Verified identities can be used for secure financial transactions 31 | 32 | ## Architecture 33 | 34 | ![Architecture Diagram](https://via.placeholder.com/800x400?text=Identity+Management+Architecture) 35 | 36 | The system consists of three main components: 37 | 38 | 1. **Smart Contracts**: Ethereum smart contracts that manage identity verification status 39 | 2. **IPFS Storage**: Decentralized storage for encrypted identity documents 40 | 3. **Node.js API**: Backend services for document processing and blockchain interaction 41 | 42 | ## Smart Contract 43 | 44 | The `IdentityManagement` smart contract handles: 45 | 46 | - Identity registration 47 | - Verification status tracking 48 | - Authorized verifier management 49 | - Identity status queries 50 | 51 | ## Installation 52 | 53 | ### Prerequisites 54 | 55 | - Node.js (v14+) 56 | - npm (v6+) 57 | - Truffle (for smart contract deployment) 58 | - IPFS node (or Infura IPFS account) 59 | - Ethereum node (or Infura Ethereum account) 60 | 61 | ### Setup 62 | 63 | 1. Clone the repository: 64 | ```bash 65 | git clone https://github.com/yourusername/blockchain-identity-management.git 66 | cd blockchain-identity-management 67 | ``` 68 | 69 | 2. Install dependencies: 70 | ```bash 71 | npm install 72 | ``` 73 | 74 | 3. Configure environment: 75 | ```bash 76 | cp .env.example .env 77 | # Edit .env with your configuration settings 78 | ``` 79 | 80 | 4. Deploy smart contracts: 81 | ```bash 82 | truffle migrate --network 83 | ``` 84 | 85 | 5. Start the server: 86 | ```bash 87 | npm start 88 | ``` 89 | 90 | ## API Endpoints 91 | 92 | | Endpoint | Method | Description | 93 | |----------|--------|-------------| 94 | | `/api/identity/register` | POST | Register a new identity | 95 | | `/api/identity/:address` | GET | Get identity information | 96 | | `/api/identity/verify` | POST | Verify an identity (verifiers only) | 97 | | `/api/identity/reject` | POST | Reject an identity (verifiers only) | 98 | 99 | ## Usage Examples 100 | 101 | ### Register an Identity 102 | 103 | ```javascript 104 | const axios = require('axios'); 105 | const FormData = require('form-data'); 106 | const fs = require('fs'); 107 | 108 | async function registerIdentity() { 109 | const form = new FormData(); 110 | form.append('address', '0x123...'); // User's Ethereum address 111 | form.append('publicKey', '-----BEGIN PUBLIC KEY-----...'); // User's public key 112 | form.append('documents', fs.createReadStream('passport.jpg')); 113 | form.append('documents', fs.createReadStream('license.pdf')); 114 | 115 | const response = await axios.post('http://localhost:3000/api/identity/register', form, { 116 | headers: { 117 | ...form.getHeaders(), 118 | } 119 | }); 120 | 121 | console.log(response.data); 122 | } 123 | 124 | registerIdentity(); 125 | ``` 126 | 127 | ### Check Identity Status 128 | 129 | ```javascript 130 | const axios = require('axios'); 131 | 132 | async function checkIdentity(address) { 133 | const response = await axios.get(`http://localhost:3000/api/identity/${address}`); 134 | console.log(response.data); 135 | } 136 | 137 | checkIdentity('0x123...'); 138 | ``` 139 | 140 | ## Security Considerations 141 | 142 | - All documents are encrypted before being stored on IPFS 143 | - Only hash references are stored on the blockchain, not the actual documents 144 | - Private keys never leave the client 145 | - Multi-factor authentication is recommended for verifiers 146 | - Smart contract follows security best practices 147 | 148 | ## Future Enhancements 149 | 150 | - Support for Decentralized Identifiers (DIDs) 151 | - Integration with other blockchain networks 152 | - Mobile application for identity verification 153 | - Enhanced privacy features using Zero-Knowledge Proofs 154 | - Integration with DeFi protocols for secure financial transactions 155 | 156 | ## License 157 | 158 | MIT License 159 | 160 | ## Contributing 161 | 162 | Contributions are welcome! Please feel free to submit a Pull Request. 163 | -------------------------------------------------------------------------------- /config.json Sample Configuration: -------------------------------------------------------------------------------- 1 | { 2 | "ethereumNode": "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID", 3 | "ipfs": { 4 | "host": "ipfs.infura.io", 5 | "port": 5001, 6 | "protocol": "https" 7 | }, 8 | "contractAddress": "0x123456789...YOUR_DEPLOYED_CONTRACT_ADDRESS", 9 | "gas": 3000000, 10 | "gasPrice": "20000000000" 11 | } 12 | -------------------------------------------------------------------------------- /package.json Configuration: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blockchain-identity-management", 3 | "version": "1.0.0", 4 | "description": "A decentralized identity verification system using blockchain technology", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "node server.js", 8 | "dev": "nodemon server.js", 9 | "test": "mocha tests/**/*.test.js", 10 | "deploy-contracts": "truffle migrate --network development" 11 | }, 12 | "keywords": [ 13 | "blockchain", 14 | "ethereum", 15 | "identity", 16 | "verification", 17 | "ipfs", 18 | "decentralized" 19 | ], 20 | "author": "Your Name", 21 | "license": "MIT", 22 | "dependencies": { 23 | "body-parser": "^1.19.0", 24 | "cors": "^2.8.5", 25 | "dotenv": "^10.0.0", 26 | "express": "^4.17.1", 27 | "ipfs-http-client": "^50.1.2", 28 | "multer": "^1.4.3", 29 | "web3": "^1.6.0" 30 | }, 31 | "devDependencies": { 32 | "chai": "^4.3.4", 33 | "mocha": "^9.1.3", 34 | "nodemon": "^2.0.15", 35 | "truffle": "^5.4.29" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /truffle-config.js for Smart Contract Deployment: -------------------------------------------------------------------------------- 1 | /** 2 | * Truffle configuration file for Ethereum smart contract deployment 3 | */ 4 | require('dotenv').config(); 5 | const HDWalletProvider = require('@truffle/hdwallet-provider'); 6 | 7 | // Use environment variables for sensitive information 8 | const MNEMONIC = process.env.MNEMONIC || ""; 9 | const INFURA_PROJECT_ID = process.env.INFURA_PROJECT_ID || ""; 10 | 11 | module.exports = { 12 | networks: { 13 | // For local development using Ganache 14 | development: { 15 | host: "127.0.0.1", 16 | port: 7545, 17 | network_id: "*" // Match any network id 18 | }, 19 | 20 | // Ethereum test networks 21 | ropsten: { 22 | provider: () => new HDWalletProvider( 23 | MNEMONIC, 24 | `https://ropsten.infura.io/v3/${INFURA_PROJECT_ID}` 25 | ), 26 | network_id: 3, 27 | gas: 5500000, 28 | confirmations: 2, 29 | timeoutBlocks: 200, 30 | skipDryRun: true 31 | }, 32 | 33 | rinkeby: { 34 | provider: () => new HDWalletProvider( 35 | MNEMONIC, 36 | `https://rinkeby.infura.io/v3/${INFURA_PROJECT_ID}` 37 | ), 38 | network_id: 4, 39 | gas: 5500000, 40 | confirmations: 2, 41 | timeoutBlocks: 200, 42 | skipDryRun: true 43 | }, 44 | 45 | // Ethereum main network 46 | mainnet: { 47 | provider: () => new HDWalletProvider( 48 | MNEMONIC, 49 | `https://mainnet.infura.io/v3/${INFURA_PROJECT_ID}` 50 | ), 51 | network_id: 1, 52 | gas: 5500000, 53 | gasPrice: 120000000000, // 120 gwei 54 | confirmations: 2, 55 | timeoutBlocks: 200, 56 | skipDryRun: false 57 | } 58 | }, 59 | 60 | // Configure your compilers 61 | compilers: { 62 | solc: { 63 | version: "0.8.9", 64 | settings: { 65 | optimizer: { 66 | enabled: true, 67 | runs: 200 68 | } 69 | } 70 | } 71 | }, 72 | 73 | // Plugins for additional functionality 74 | plugins: [ 75 | 'truffle-plugin-verify' 76 | ], 77 | 78 | // Configure plugin settings 79 | api_keys: { 80 | etherscan: process.env.ETHERSCAN_API_KEY 81 | } 82 | }; 83 | --------------------------------------------------------------------------------