The Decentralized Exam Integrity System (DEIS) is a blockchain-based solution designed to eliminate exam paper leaks through decentralized access control and cryptographic key management. This MVP demonstrates a complete end-to-end workflow for secure exam distribution using Ethereum smart contracts, client-side encryption, Filebase IPFS-based decentralized storage, and time-locked access control.
| Component | Technology | Purpose |
|---|---|---|
| Blockchain | Solidity 0.8.x, Ethereum Sepolia Testnet | Smart contract execution and audit trail |
| Frontend | React 18, Tailwind CSS | Modern, responsive UI |
| Web3 | Ethers.js v5 | Blockchain interaction |
| Encryption | CryptoJS (AES-256) | Client-side file encryption |
| Key Management | Shamir's Secret Sharing | Distributed key storage |
| Storage | Filebase IPFS (via config.js) |
Decentralized encrypted file storage |
β
Time-Locked Access Control - Exams cannot be accessed before release time
β
Role-Based Authorization - Admin, Principal, and Proctor roles
β
Cryptographic Encryption - AES-256 encryption for exam content
β
Secret Sharing - Shamir's Secret Sharing for key distribution
β
Immutable Audit Trail - All actions logged on blockchain
β
Decentralized Storage - Encrypted files stored off-chain
dapp-papers/
βββ index.html # MAIN production DApp (React + Ethers + Filebase IPFS)
βββ ExamManager.sol # Full-featured ExamManager contract with time-locked access control
βββ ExamManagerOptimized.sol # Gas-optimized contract used by index.html
βββ ExamManagerSimple.sol # Ultra-minimal, gas-efficient variant
βββ config.js # Network, storage (Filebase/IPFS) and UI configuration
βββ filebase-storage.js # Standalone Filebase S3/IPFS helper used by test utilities
βββ App.jsx # React component version (for bundler-based development)
βββ README.md # This file
βββ *.md # Additional guides (architecture, deployment, quick start, visual guide, etc.)
βββ sample-exam.txt # Sample exam file for testing upload/decrypt flow
config.js- Defines supported networks (
sepolia,mainnet) and RPC URLs. - Optional pre-filled contract addresses per network.
- Configures the storage provider (Filebase IPFS by default), gateways, and UI/security settings.
- Defines supported networks (
- Filebase IPFS integration (see
FILEBASE_IMPLEMENTATION.md)- Encrypted exam files are uploaded via a
ProductionFilebaseStorageclass. - The smart contract stores only the resulting IPFS hash (CID).
- During retrieval, the DApp downloads the encrypted file from IPFS and decrypts it client-side.
- Encrypted exam files are uploaded via a
- Node.js (v16+) - Download
- MetaMask - Install Extension
- Ganache - Download
- Remix IDE - Open Online
By default the bundled index.html expects Ethereum Sepolia Testnet (chainId 11155111), but you can also use a local chain (e.g., Hardhat or Ganache) if you adjust the network checks in index.html.
Option A β Recommended: Sepolia Testnet
- Open MetaMask
- Click network dropdown β Add Network
- Configure:
- Network Name: Sepolia Testnet
- RPC URL:
https://rpc.sepolia.org(or any Sepolia RPC endpoint) - Chain ID:
11155111 - Currency Symbol: SepoliaETH
- Block Explorer:
https://sepolia.etherscan.io
- Get Sepolia test ETH from a faucet (see
GET_FREE_ETH.md).
Option B β Local Development Network (Ganache/Hardhat)
- Launch Ganache or a local Hardhat node
- Note the RPC Server URL (e.g.,
http://127.0.0.1:7545) - In MetaMask, add a custom network (e.g., Ganache Local) with that RPC URL and matching chain ID
- Import one of the local accounts using its private key
- Open MetaMask extension
- Click network dropdown β Add Network
- Configure:
- Network Name: Sepolia Testnet (or your local dev network name)
- RPC URL: The RPC endpoint you chose (e.g.,
https://rpc.sepolia.org) - Chain ID:
11155111for Sepolia, or your local chain ID - Currency Symbol: ETH / SepoliaETH
- Import your funded account (Sepolia address or local test account)
- Open Remix IDE
- Create new file:
ExamManager.sol - Copy contents from
ExamManager.sol - Go to Solidity Compiler tab
- Select compiler version:
0.8.0+ - Click Compile ExamManager.sol
- Select compiler version:
- Go to Deploy & Run Transactions tab
- Environment: Injected Provider - MetaMask
- Ensure MetaMask is connected to your target network (Sepolia recommended)
- Click Deploy
- Confirm transaction in MetaMask
- Copy the deployed contract address (you'll need this!)
π Note: The default
index.htmlchecks that MetaMask is on Sepolia (chainId === 11155111). If you deploy to a different network (e.g., Ganache), update those checks in theconnectWalletandconnectContractfunctions.
# Install dependencies
npm install --save-dev hardhat @nomiclabs/hardhat-ethers ethers
# Initialize Hardhat project
npx hardhat
# Deploy script (scripts/deploy.js)
npx hardhat run scripts/deploy.js --network localhost- Open
index.htmlin a modern browser (Chrome/Firefox) - The DApp will load automatically
# Using Python
python -m http.server 8000
# Using Node.js
npx http-server -p 8000
# Open browser to http://localhost:8000- Click "Connect Wallet" button
- Approve MetaMask connection
- Paste the deployed contract address in the input field
- Click "Connect" button
- Wait for confirmation notification
Purpose: Upload and register new exams
Workflow:
- Switch to Admin tab
- Fill in exam details:
- Exam Title: e.g., "Mathematics Final 2025"
- Select File: Choose exam paper (PDF/TXT)
- Release Time: Set future date/time
- Click "Upload & Secure Exam"
- Confirm transaction in MetaMask
- Wait for blockchain confirmation
What Happens:
- File is encrypted with AES-256 using random key
- Encryption key is split using Shamir's Secret Sharing (3 shares, 2 threshold)
- Encrypted file uploaded to Filebase IPFS via the configured storage provider
- File hash and key shares stored on blockchain
ExamRegisteredevent emitted
Purpose: Authorize proctors to access specific exams
Workflow:
- Switch to Principal tab
- Select exam from dropdown
- Enter proctor's Ethereum address
- Click "Authorize Proctor"
- Confirm transaction
What Happens:
- Proctor address added to authorized list for exam
ProctorAuthorizedevent emitted- Proctor can now retrieve exam after release time
Purpose: Retrieve and decrypt exam papers
Workflow:
- Switch to Proctor tab
- View list of authorized exams with status:
- π‘ Pending: Not yet released (button disabled)
- π’ Ready: Available for retrieval
- π΄ Expired: Past retrieval window
- Click "Decrypt & Display" on ready exam
- Confirm transaction to retrieve key parts
- View decrypted content
What Happens:
- Smart contract verifies:
- β Proctor is authorized
- β Current time β₯ release time
- β Key not already retrieved
- Key parts returned from blockchain
- Encrypted file fetched from storage
- Key reconstructed using Shamir's Secret Sharing
- File decrypted and displayed
KeyRevealedevent emitted
Original File β AES-256 Encryption β Encrypted File β Filebase IPFS (or configured storage)
β
Random Key
β
Shamir's Secret Sharing
β
[Share 1, Share 2, Share 3]
β
Smart Contract Storage
The smart contract enforces time-based access control:
require(block.timestamp >= exam.releaseTimestamp, "Exam not yet released");This ensures that even authorized proctors cannot access the exam before the scheduled release time.
Concept: Split encryption key into N shares where any K shares can reconstruct the original key.
Implementation (Simplified for MVP):
- N = 3 total shares
- K = 2 threshold (any 2 shares can reconstruct key)
- N-1 shares stored on-chain
- Reconstruction happens client-side
Production Note: Use a robust SSS library like secrets.js-grempe for production deployments.
All critical actions are logged as blockchain events:
| Event | Triggered When | Data Logged |
|---|---|---|
ExamRegistered |
Admin uploads exam | Exam ID, title, hash, release time, creator |
ProctorAuthorized |
Principal authorizes proctor | Exam ID, proctor address, authorizer |
KeyRevealed |
Proctor retrieves key | Exam ID, proctor address, timestamp, block number |
PrincipalAdded |
Admin adds principal | Principal address, admin address |
ExamDeactivated |
Admin deactivates exam | Exam ID, admin address |
View the Audit Trail section in the DApp to see real-time event logs.
- Admin: Upload exam with release time 5 minutes in future
- Principal: Authorize proctor address
- Proctor: Attempt early access (should fail)
- Wait: Until release time passes
- Proctor: Successfully retrieve and decrypt exam
- Verify: Audit trail shows all events
- Admin: Upload exam
- Proctor: Try to access without authorization (should fail)
- Principal: Authorize different address
- Original Proctor: Still cannot access
- Admin: Upload exam with future release time
- Principal: Authorize proctor
- Proctor: Attempt immediate access
- Expected: Transaction reverts with "Exam not yet released"
DEIS ships three compatible contract variants:
ExamManagerβ full-featured reference implementation used throughout the docs.ExamManagerOptimizedβ gas-optimized variant used by the bundledindex.htmlUI.ExamManagerSimpleβ ultra-minimal, gas-efficient compatibility version.
The function signatures below describe the full ExamManager interface; the optimized variants expose equivalent behavior with slightly different types (e.g., uint32 IDs) and helper methods (e.g., getKeys, getAllExams).
// Register new exam
function registerExam(
string memory _examTitle,
string memory _encryptedFileHash,
uint256 _releaseTimestamp,
string[] memory _encryptedKeyParts
) public onlyAdmin returns (uint256)
// Add principal role
function addPrincipal(address _principal) public onlyAdmin
// Deactivate exam
function deactivateExam(uint256 _examId) public onlyAdmin// Authorize proctor for exam
function authorizeProctor(
uint256 _examId,
address _proctor
) public onlyAdminOrPrincipal
// Revoke proctor authorization
function revokeProctor(
uint256 _examId,
address _proctor
) public onlyAdminOrPrincipal// Retrieve encrypted key parts (time-locked)
function getEncryptedKeyParts(uint256 _examId)
public returns (string[] memory)// Get exam information
function getExamInfo(uint256 _examId)
public view returns (ExamInfo memory)
// Check if exam is released
function isExamReleased(uint256 _examId)
public view returns (bool)
// Check proctor authorization
function isProctorAuthorized(uint256 _examId, address _proctor)
public view returns (bool)
// Get all exam IDs
function getAllExamIds()
public view returns (uint256[] memory)Problem: "Please install MetaMask!" error
Solution: Install MetaMask extension and refresh page
Problem: Wrong network
Solution: Switch MetaMask to Ganache Local network
Problem: "Contract connection failed"
Solution:
- Verify contract address is correct
- Ensure contract is deployed on current network
- Check Ganache is running
Problem: "Exam not yet released"
Solution: Wait until release time passes
Problem: "Not authorized for this exam"
Solution: Principal must authorize your address first
Problem: "Insufficient funds"
Solution: Ensure Ganache account has ETH
Problem: Upload fails silently
Solution:
- Check file size (keep under 1MB for testing)
- Ensure file is text-based (TXT, PDF)
- Check browser console for errors
- Add native Arweave/permaweb storage in addition to Filebase IPFS
- Implement robust SSS library (secrets.js-grempe)
- Add multi-signature admin controls
- Implement exam expiration logic
- Add encrypted metadata support
- Create mobile-responsive PWA
- Add comprehensive test suite
- Implement gas optimization
- Add event indexing (The Graph)
- Create admin dashboard analytics
- Multi-exam batch operations
- Proctor reputation system
- Exam versioning and updates
- Automated time-zone handling
- Email/SMS notifications
- PDF viewer integration
- Watermarking for retrieved exams
- Access analytics and reporting
- Integration with LMS platforms
- Compliance reporting tools
MIT License - See LICENSE file for details
This is an MVP demonstration project. For production use, conduct thorough security audits and testing.
For issues or questions:
- Check the Troubleshooting section
- Review Ganache and MetaMask logs
- Inspect browser console for errors
- Verify smart contract deployment
This project demonstrates:
- Smart contract development with Solidity
- Web3 integration with Ethers.js
- Client-side cryptography
- Decentralized application architecture
- Time-locked access control patterns
- Event-driven blockchain applications
- Role-based access control (RBAC)
Built with β€οΈ for secure, decentralized education systems