diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01f0d42..15d3a5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,9 @@ jobs: pip install -r requirements.txt - name: Run tests + env: + INITIAL_ADMIN_PASSWORD: testadmin123 + SESSION_SECRET: ci-session-secret run: | python -m pytest tests/ -v --tb=short @@ -58,8 +61,14 @@ jobs: docker run -d -p 5000:5000 --name test-app \ -e DATABASE_URL=sqlite:////tmp/credify.db \ -e INITIAL_ADMIN_PASSWORD=testadmin123 \ + -e SESSION_SECRET=ci-session-secret \ credify:${{ github.sha }} - sleep 15 + for i in {1..30}; do + if curl -fsS http://localhost:5000/ > /dev/null; then + break + fi + sleep 2 + done curl -f http://localhost:5000/ || exit 1 docker stop test-app docker rm test-app diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index b5b042a..399194a 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -35,7 +35,7 @@ jobs: push: true tags: | udaycodespace/credify:latest - udaycodespace/credify:v2.1.0 + udaycodespace/credify:v2 udaycodespace/credify:sha-${{ github.sha }} cache-from: type=registry,ref=udaycodespace/credify:buildcache cache-to: type=registry,ref=udaycodespace/credify:buildcache,mode=max diff --git a/.gitignore b/.gitignore index 299e702..ccbbd98 100644 --- a/.gitignore +++ b/.gitignore @@ -182,4 +182,5 @@ htmlcov/ .coverage dist/ build/ -*.egg-info/ \ No newline at end of file +*.egg-info/ +credify-verify/ diff --git a/README.md b/README.md index e9c277e..ea30579 100644 --- a/README.md +++ b/README.md @@ -1,892 +1,393 @@ -๏ปฟ# ๐ŸŽ“ Blockchain-Based Verifiable Credential System for Academic Transcripts +๏ปฟ# Credify v2: Permissioned Private Blockchain for Academic Credential Verification -**Version 2.2.0** | A custom private-blockchain credential system for issuing, storing, and verifying academic records with IPFS-integrated storage and cryptographic validation. +A permissioned private blockchain implementing deterministic consensus, validator-based participation, and finalized tamper-evident blocks for credential verification. -[![Docker Pulls](https://img.shields.io/docker/pulls/udaycodespace/credify?style=flat-square&logo=docker)](https://hub.docker.com/r/udaycodespace/credify) -[![Docker Image Size](https://img.shields.io/docker/image-size/udaycodespace/credify?style=flat-square&logo=docker)](https://hub.docker.com/r/udaycodespace/credify) -[![Docker Build](https://github.com/udaycodespace/credify/workflows/Docker%20Build%20and%20Push/badge.svg)](https://github.com/udaycodespace/credify/actions) -[![CI/CD Pipeline](https://github.com/udaycodespace/credify/workflows/CI%2FCD%20Pipeline/badge.svg)](https://github.com/udaycodespace/credify/actions) - -> โš ๏ธ **IMPORTANT SECURITY NOTICE - EDUCATIONAL PROJECT** -> -> This is an **academic demonstration project** developed for educational purposes only. -> -> **๐Ÿ” Security Disclaimers:** -> - All credentials, passwords, and user data shown are **fictitious and for demonstration only** -> - Default passwords in code are **hashed** and used only for local development -> - **DO NOT** use default credentials in production environments -> - This system is designed for educational assessment and portfolio demonstration -> -> **๐Ÿ“ง For Production Deployment or Questions:** -> - Contact: [@udaycodespace](https://github.com/udaycodespace) | [@shashikiran47](https://github.com/shashikiran47) | [@tejavarshith](https://github.com/tejavarshith) -> - All passwords must be set via environment variables in real deployments -> - See `.env.example` for secure configuration guidelines - -*** - -## ๐Ÿ“Œ Overview - -Academic credential verification faces significant challenges in traditional systems: centralized control, slow processing times, susceptibility to forgery, and minimal privacy protection for students. This project addresses these issues with a **practical, tamper-evident, privacy-aware credential verification workflow**. - -Our system leverages **a custom private blockchain layer, IPFS-integrated storage, RSA signatures, and W3C-inspired credential modeling** to create a robust platform where: - -- ๐Ÿ›๏ธ **Universities** issue cryptographically signed, tamper-proof digital credentials -- ๐Ÿ‘จโ€๐ŸŽ“ **Students** maintain complete ownership and control over their academic data -- ๐Ÿ’ผ **Employers** verify credentials quickly with cryptographic integrity checks and signed metadata -- ๐Ÿ”’ **Privacy** is preserved through selective disclosure mechanisms -- ๐ŸŽ“ **Elite Presentation** Professional institutional-grade certificate viewer and 10/10 PDF generator - -**Current Status:** Refactored architecture with blueprints/services, end-to-end credential workflows, and active security hardening (Updated March 2026) - -*** - -## ๐Ÿš€ Quick Start - -### ๐Ÿณ Docker Deployment: 3-Node Simulation (Recommended) - -```bash -# Clone the repository -git clone https://github.com/udaycodespace/credify.git -cd credify - -# Launch the custom 3-node private blockchain cluster -docker-compose up -d - -# Access the isolated nodes -open http://localhost:5001 # Institutional Node 1 -open http://localhost:5002 # Institutional Node 2 -open http://localhost:5003 # Institutional Node 3 -``` - -**Docker Hub Repository:** [udaycodespace/credify](https://hub.docker.com/r/udaycodespace/credify) - -### ๐Ÿ”ง Local Development +--- -```bash -# Clone repository -git clone https://github.com/udaycodespace/credify.git -cd credify +## Security Notice -# Create virtual environment -python -m venv venv -source venv/bin/activate # On Windows: venv\Scripts\activate +This is an academic engineering project built for educational evaluation and portfolio demonstration. -# Install dependencies -pip install -r requirements.txt +- All sample data in documentation is illustrative. +- Secrets must be provided through environment variables. +- Do not deploy with default local-development settings. +- Use HTTPS/TLS and secure secret management for internet-facing deployments. -# Set environment variables (REQUIRED for security) -cp .env.example .env -# Edit .env with your secure passwords +--- -# Run application -python main.py -``` +## Overview -*** +Credify v2 addresses credential forgery, verification delay, and privacy exposure in traditional academic verification systems. -## ๐ŸŽฏ Project Aims & Objectives - -### Primary Goals - -- **Eliminate Academic Fraud:** Prevent certificate forgery through cryptographic verification -- **Privacy Preservation:** Enable selective disclosure of academic information via Zero-Knowledge Proofs -- **Decentralization:** Remove single points of failure in credential storage and verification -- **Instant Verification:** Provide real-time, cryptographically verifiable proof of authenticity -- **Student Empowerment:** Give students complete control over their credentials - -### Key Outcomes +The platform combines: +- permissioned private blockchain state anchoring +- deterministic validator consensus +- finalized tamper-evident blocks +- IPFS-integrated storage with local fallback +- RSA-based signature verification +- ZKP-inspired selective disclosure -- Immutable academic credential records -- Sub-second verification times -- Privacy-preserving data sharing -- Elimination of intermediary verification costs -- Enhanced trust in academic credentials globally - -*** - -## โœจ Core Features - -### ๐Ÿ” Security & Cryptography +Stakeholder outcomes: +- Universities issue signed, verifiable credentials. +- Students retain controlled data sharing. +- Verifiers validate authenticity quickly without manual paperwork. -- **RSA-2048 Digital Signatures** for credential authenticity -- **SHA-256 Hashing** for data integrity verification -- **Merkle Tree Proofs** for efficient batch verification -- **Zero-Knowledge Proofs** for privacy-preserving verification -- **Multi-layer Encryption** for sensitive data protection +Extended documentation was consolidated into the main README and core engineering documents to improve clarity and reduce redundancy. -### โ›“๏ธ Blockchain Infrastructure +--- -- Custom permissioned blockchain with proof-of-authority consensus -- Immutable credential hash anchoring -- Complete audit trail with timestamp verification -- Block integrity validation -- Real-time transaction monitoring +## Key Features -### ๐Ÿ—„๏ธ Distributed Storage +- Permissioned private blockchain ledger for institutional trust boundaries +- Deterministic round-robin validator selection +- Immediate block finality with tamper-evident hash-linking +- Validator-based network participation model +- Credential integrity verification via cryptographic signatures +- IPFS-backed storage with resilient local persistence fallback +- ZKP-inspired selective disclosure for privacy-aware proof sharing +- Multi-node propagation and synchronization support -- IPFS integration with resilient local fallback storage -- Content-addressed storage (CID-based retrieval) -- Automatic fallback to local encrypted storage -- Redundant data availability -- Efficient large document handling +--- -### ๐Ÿ‘ฅ Role-Based Access Control +## System Architecture -- **Issuer Role:** Universities and educational institutions - - Issue digital credentials - - Revoke compromised credentials - - Manage credential templates - - Audit trail access -- **Holder Role:** Students - - View and download credentials - - Generate selective disclosure proofs - - Control data sharing permissions - - Credential history tracking -- **Verifier Role:** Employers and institutions - - Instant credential verification - - Blockchain-backed authenticity checks - - Revocation status validation - - Batch verification support +Credential lifecycle (high level): +1. Issuer creates and signs credential data. +2. Credential payload is stored in IPFS (or fallback storage). +3. Credential hash and metadata are anchored in a finalized block. +4. Holder shares proof or credential reference with verifier. +5. Verifier checks blockchain anchor, signature, and revocation state. -### ๐ŸŽฏ Advanced Capabilities +Architecture characteristics: +- permissioned validator set controls block proposal +- deterministic consensus avoids probabilistic confirmation delay +- finalized blocks create strong tamper-evidence guarantees +- propagation logic keeps validator nodes aligned -- **Selective Disclosure:** Share only required fields (e.g., degree, GPA) -- **Credential Versioning:** Track updates and amendments -- **Support System:** Integrated ticketing and messaging -- **Analytics Dashboard:** Real-time system statistics and insights -- **Elite PDF Generation:** 10/10 academic transcript generation with blockchain proofs, QR integration, and institutional branding. -- **Senior UI/UX:** Hero-styled student dashboards and certificate viewers designed for institutional credibility. +--- -*** +## System Evolution -## ๐Ÿงฐ Technology Stack +### Phase 1: Prototype - BlockCred -

- - - - - - - - -

+Repository: https://github.com/uday-works/blockcred-system +Live: https://blockcred-frontend.onrender.com/ -### Backend Architecture +This phase validated the core problem quickly. +It tested whether credentials could be anchored off-chain, hashed reliably, and shown through role-specific dashboards. +It confirmed feasibility, but exposed limits in trust control, deterministic state progression, and institutional-grade verification guarantees. +Those constraints made a redesign necessary. -- **Framework:** Python 3.10+ with Flask 2.x -- **Data Layer:** Hybrid persistence for credential, registry, and blockchain state -- **ORM:** SQLAlchemy with Flask-SQLAlchemy -- **Authentication:** Session-based auth with role guards and MFA setup flow -- **Security:** Werkzeug password hashing, CSRF protection -- **PDF Engine:** ReportLab for high-fidelity academic document generation +Key foundations introduced: +- IPFS off-chain credential storage +- cryptographic hashing (SHA-256 / Keccak) +- React-based dashboards +- Dockerized deployment on Render -### Frontend Stack +### Phase 2: Current System - Credify v2 -- **HTML5** with semantic markup -- **CSS3** with modern responsive design -- **JavaScript (ES6+)** for dynamic interactions -- **AJAX** for asynchronous operations -- **Bootstrap-inspired** custom UI components - -### Blockchain & Cryptography - -- **Blockchain:** Custom implementation with proof-of-authority -- **Storage:** IPFS with local fallback mechanism -- **Cryptography:** Python Cryptography library (RSA-2048, SHA-256) -- **Standards:** W3C Verifiable Credentials Data Model alignment +Evolution delivered: +- permissioned private blockchain architecture +- deterministic consensus for predictable block production +- validator-based participation controls +- finalized tamper-evident block model +- multi-node propagation and synchronization -### DevOps & Deployment - -- **Containerization:** Docker with multi-stage builds -- **CI/CD:** GitHub Actions automated workflows -- **Registry:** Docker Hub for image distribution -- **Hosting:** Render cloud platform -- **Testing:** pytest (58 tests across 14 test files) -- **Code Quality:** Black, Flake8, isort -- **Monitoring:** Health checks and logging - -*** - -## ๐Ÿ”„ CI/CD Pipeline - -Our project uses **GitHub Actions** for continuous integration and deployment: - -### Automated Workflows +This redesign moved the project from proof-of-concept behavior to an auditable ledger model for academic institutions. +Deterministic consensus, validator controls, and block finality made verification defensible in real review settings. -``` -git push โ†’ GitHub Actions โ†’ Tests โ†’ Build Docker โ†’ Push to Docker Hub โ†’ Deploy -``` +### Phase 3: Verification Client -#### 1. **CI/CD Pipeline** (`ci.yml`) -- โœ… Runs automated tests on every push -- โœ… Validates code quality with linting -- โœ… Ensures application starts correctly -- โœ… Generates coverage reports +Repository: https://github.com/udaycodespace/credify-verify +Live: https://udaycodespace.github.io/credify-verify/ -#### 2. **Docker Build & Push** (`docker-publish.yml`) -- โœ… Builds Docker image automatically -- โœ… Pushes to Docker Hub with version tags -- โœ… Creates `latest`, `v2.0`, and commit-specific tags -- โœ… Optimizes with build caching +Verification client characteristics: +- independent verification client +- QR and credential proof verification +- no backend dependency for verification flows +- explicit trust-boundary separation from issuance platform -### View Pipeline Status +This separation keeps verification independently testable and reduces coupling between issuance operations and public trust checks. -- **GitHub Actions:** [View Workflows](https://github.com/udaycodespace/credify/actions) -- **Docker Hub:** [View Images](https://hub.docker.com/r/udaycodespace/credify) -- **Story Time:** [The Origins of Credify](docs/STORY_TIME.md) +This progression reflects a deliberate engineering approach. +It starts with concept validation, evolves into a controlled blockchain system, and ends with verification in an independent trust boundary. -*** +--- -## ๐Ÿ—๏ธ System Architecture +## Authentication & Access Model -### Credential Lifecycle Workflow +The system uses a secure OTP-based access mechanism. +The model follows institutional onboarding patterns. +Identity provisioning is controlled by authorized academic administrators, not open signup flows. -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ ISSUER โ”‚ (1) Creates & Signs Credential -โ”‚ (University)โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ - โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ Cryptographic โ”‚ - โ”‚ Signature โ”‚ - โ”‚ (RSA-2048) โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - (2) Store on IPFS โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ โ”‚ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ IPFS โ”‚ โ”‚ BLOCKCHAIN โ”‚ - โ”‚ (Full Data) โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚ (Hash + Metadata) โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ (3) โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ Record โ”‚ - โ”‚ Hash โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - (4) Credential Delivered - โ”‚ - โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ HOLDER โ”‚ - โ”‚ (Student) โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - (5) Selective Disclosure - โ”‚ - โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ VERIFIER โ”‚ - โ”‚ (Employer) โ”‚ โ”€โ”€โ”€โ” - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ - โ–ฒ โ”‚ - โ”‚ โ”‚ - (6) Verify โ”‚ โ”‚ (7) Verify - Hash โ”‚ โ”‚ Signature - โ”‚ โ”‚ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ” - โ”‚ VERIFICATION ENGINE โ”‚ - โ”‚ โ€ข Blockchain Check โ”‚ - โ”‚ โ€ข IPFS Retrieval โ”‚ - โ”‚ โ€ข Signature Validationโ”‚ - โ”‚ โ€ข Revocation Status โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +### Admin / Issuer -### Data Flow Architecture +- authenticated via OTP or environment-controlled access +- responsible for: + - creating students + - issuing credentials + - interacting with blockchain records -1. **Issuance Phase:** University creates credential โ†’ Signs with private key โ†’ Stores on IPFS โ†’ Records hash on blockchain -2. **Storage Phase:** Full credential on IPFS (CID) + Hash on blockchain (Block) + Metadata in registry -3. **Disclosure Phase:** Student generates proof โ†’ Selects fields โ†’ Creates ZK proof โ†’ Shares with verifier -4. **Verification Phase:** Verifier receives proof โ†’ Retrieves from blockchain โ†’ Validates signature โ†’ Confirms authenticity +Admin control centralizes onboarding accountability and preserves credential issuance integrity. -*** +### Student -## ๐Ÿ“ Project Structure +- created only by admin +- no self-registration +- can: + - view credentials + - share proofs -``` -credify/ -โ”‚ -โ”œโ”€โ”€ ๐Ÿ“ฑ app/ # Flask application core -โ”‚ โ”œโ”€โ”€ app.py # Main Flask app & routes -โ”‚ โ”œโ”€โ”€ auth.py # Authentication & authorization -โ”‚ โ”œโ”€โ”€ models.py # SQLAlchemy database models -โ”‚ โ””โ”€โ”€ config.py # Configuration management -โ”‚ -โ”œโ”€โ”€ โš™๏ธ core/ # Business logic & services -โ”‚ โ”œโ”€โ”€ blockchain.py # Blockchain implementation -โ”‚ โ”œโ”€โ”€ credential_manager.py # Credential lifecycle -โ”‚ โ”œโ”€โ”€ crypto_utils.py # Cryptographic operations -โ”‚ โ”œโ”€โ”€ ipfs_client.py # IPFS integration -โ”‚ โ””โ”€โ”€ zkp_manager.py # Zero-knowledge proofs -โ”‚ -โ”œโ”€โ”€ ๐Ÿ—„๏ธ data/ # Runtime data storage -โ”‚ โ”œโ”€โ”€ blockchain_data.json # Blockchain state -โ”‚ โ”œโ”€โ”€ credentials_registry.json # Credential metadata -โ”‚ โ””โ”€โ”€ ipfs_storage.json # Local IPFS fallback -โ”‚ -โ”œโ”€โ”€ ๐ŸŽจ static/ # Frontend assets -โ”‚ โ”œโ”€โ”€ css/style.css # Stylesheets -โ”‚ โ””โ”€โ”€ js/app.js # Client-side logic -โ”‚ -โ”œโ”€โ”€ ๐Ÿ“„ templates/ # Jinja2 HTML templates -โ”‚ โ”œโ”€โ”€ index.html # Landing page -โ”‚ โ”œโ”€โ”€ issuer.html # Issuer dashboard -โ”‚ โ”œโ”€โ”€ holder.html # Student dashboard -โ”‚ โ””โ”€โ”€ verifier.html # Verifier dashboard -โ”‚ -โ”œโ”€โ”€ ๐Ÿงช tests/ # Automated test suite -โ”‚ โ”œโ”€โ”€ test_blockchain.py # Blockchain tests -โ”‚ โ”œโ”€โ”€ test_crypto_utils.py # Cryptography tests -โ”‚ โ””โ”€โ”€ test_integration.py # Integration tests -โ”‚ -โ”œโ”€โ”€ ๐Ÿณ DevOps Files -โ”‚ โ”œโ”€โ”€ Dockerfile # Container definition -โ”‚ โ”œโ”€โ”€ docker-compose.yml # Local development -โ”‚ โ”œโ”€โ”€ render.yaml # Render deployment -โ”‚ โ””โ”€โ”€ .github/workflows/ # CI/CD pipelines -โ”‚ โ”œโ”€โ”€ ci.yml # Test automation -โ”‚ โ””โ”€โ”€ docker-publish.yml # Docker Hub push -โ”‚ -โ””โ”€โ”€ ๐Ÿ“– Documentation - โ”œโ”€โ”€ README.md # This file - โ”œโ”€โ”€ README.Docker.md # Docker Hub description - โ””โ”€โ”€ docs/ # Additional documentation -``` +This prevents unauthorized identity creation and aligns with registrar-driven enrollment workflows. -*** +### Verifier -## โš™๏ธ Installation & Setup +- no login required +- verifies via: + - QR scan + - credential ID + - proof validation -### Prerequisites +Public verifier access lowers friction while preserving trust through cryptographic and blockchain validation. -- **Python:** 3.10 or higher -- **Docker:** (Recommended) Latest version -- **Git:** For version control +--- -### Environment Setup +## Quick Start -1. **Clone the Repository** +### Docker Deployment (3-Node Validator Cluster) ```bash git clone https://github.com/udaycodespace/credify.git cd credify +docker-compose up -d ``` -2. **Create Virtual Environment** - -```bash -# Windows -python -m venv venv -venv\Scripts\activate +Validator endpoints: +- http://localhost:5001 +- http://localhost:5002 +- http://localhost:5003 -# Linux/Mac -python3 -m venv venv -source venv/bin/activate -``` +--- -3. **Install Dependencies** +## Local Development ```bash +git clone https://github.com/udaycodespace/credify.git +cd credify +python -m venv venv +# Windows: venv\Scripts\activate +# Linux/Mac: source venv/bin/activate pip install -r requirements.txt +cp .env.example .env +python main.py ``` -4. **โš ๏ธ Configure Environment Variables (CRITICAL FOR SECURITY)** +Application endpoint: +- http://localhost:5000 -```bash -# Copy example environment file -cp .env.example .env +--- -# Edit .env with STRONG, UNIQUE passwords -# NEVER use default passwords in production! -``` +## Tech Stack -**Required Environment Variables:** -```env -SECRET_KEY=generate_your_own_secret_key_here -ADMIN_PASSWORD=strong_unique_password -STUDENT_PASSWORD=another_strong_password -DATABASE_URL=your_database_url -``` +Backend and Core: +- Python 3.10+ +- Flask +- SQLAlchemy +- Cryptography (RSA, SHA-256) -5. **Initialize Database** +Blockchain and Storage: +- permissioned private blockchain engine +- deterministic validator consensus +- IPFS integration with local fallback -```bash -python -c "from app.models import init_database; from app.app import app; init_database(app)" -``` +Frontend and UX: +- HTML/CSS/JavaScript +- Jinja2 templates +- responsive role-based dashboards -### Using Docker & docker-compose (Recommended) +Quality and Delivery: +- pytest +- Docker and docker-compose +- GitHub Actions CI/CD -```bash -# Build the highly optimized multi-stage image -docker build -t udaycodespace/credify:latest . +--- -# Run the full Private Blockchain 3-Node Cluster -docker-compose up -d -``` +## Core Features -*** +Security and Integrity: +- RSA-2048 digital signatures +- SHA-256 hashing and hash-linking +- finalized tamper-evident blocks +- revocation-aware verification -## โ–ถ๏ธ Running the Application +Blockchain Capability: +- validator-based network participation +- deterministic consensus sequencing +- propagation safety controls +- audit-oriented credential anchoring -### Development Mode +Credential Experience: +- issuance and lifecycle management +- PDF credential generation +- QR verification flow +- ZKP-inspired selective disclosure -```bash -python main.py -``` +--- -The application will start at `http://localhost:5000` +## Workflow -### Production Mode +Operational workflow: +1. Issuer authenticates via OTP-based access. +2. Issuer creates credential payload. +3. Payload is stored and anchored to blockchain. +4. Holder receives credential and shares proof as needed. +5. Verifier validates via QR, credential ID, or proof. +6. Verification checks signature, anchor integrity, and revocation status. -```bash -export FLASK_ENV=production -python main.py -``` +--- -### Docker Deployment +## Project Structure -```bash -# Spin up the fully orchestrated 3-node network directly via compose -docker-compose up -d +```text +credify/ +โ”œโ”€โ”€ app/ # Flask app, routes, services +โ”œโ”€โ”€ core/ # Blockchain, crypto, credential logic +โ”œโ”€โ”€ data/ # Runtime data files and storage artifacts +โ”œโ”€โ”€ docs/ # Technical documentation +โ”œโ”€โ”€ static/ # Frontend assets +โ”œโ”€โ”€ templates/ # HTML templates +โ”œโ”€โ”€ tests/ # Automated tests +โ”œโ”€โ”€ Dockerfile +โ”œโ”€โ”€ docker-compose.yml +โ”œโ”€โ”€ pyproject.toml +โ””โ”€โ”€ README.md ``` -*** +--- -## ๐Ÿงช Testing +## Testing -### Run Test Suite +Run tests: ```bash -# Run all tests pytest -v - -# Run with coverage report -pytest --cov=app --cov=core --cov-report=html - -# Run specific test file -pytest tests/test_blockchain.py -v ``` -### Test Coverage Status - -- **Total Tests:** 58 (34 passed, 23 skipped, 1 optional) -- **Coverage:** ~60% (Core modules fully covered) -- **Critical Paths:** 100% coverage on authentication, blockchain, and cryptography - -*** - -## ๐Ÿ“– Usage Guide - -### Default Demo Credentials (Local Development Only) +Optional coverage: -> โš ๏ธ **These are demonstration credentials for local testing only!** -> **All passwords are hashed. Change them via environment variables for any real deployment.** - -| Role | Username | Password (Demo) | Purpose | -|------|----------|-----------------|---------| -| Admin/Issuer | admin | (Set via `ADMIN_PASSWORD` env var) | Issue credentials | -| Student | 21131A05E9 | (Set via `STUDENT_PASSWORD` env var) | View credentials | -| Verifier | verifier1 | (Set via `VERIFIER_PASSWORD` env var) | Verify credentials | - -### For Universities (Issuers) - -1. **Login** with issuer credentials -2. **Navigate** to Issuer Dashboard -3. **Issue Credential:** - - Enter student details - - Fill academic information - - Review and sign credential -4. **Manage Credentials:** - - View issued credentials - - Revoke if necessary - - Track verification requests - -### For Students (Holders) - -1. **Login** with student credentials -2. **Access** Holder Dashboard -3. **View Credentials:** - - See all issued credentials - - Download as PDF - - Check verification status -4. **Share Credentials:** - - Generate selective disclosure proof - - Choose fields to share - - Share verification link - -### For Employers (Verifiers) - -1. **Login** with verifier credentials -2. **Navigate** to Verifier Dashboard -3. **Verify Credential:** - - Enter Credential ID or upload proof - - System validates blockchain hash - - Check cryptographic signature - - View revocation status - -*** - -## ๐Ÿ“Š System Metrics & Performance - -### Current Statistics (v2.0) - -- **Credentials Issued:** Active demo dataset -- **Verification Time:** < 2 seconds average -- **Blockchain Blocks:** Dynamic growth -- **Storage Efficiency:** 95% (IPFS CID deduplication) -- **Uptime:** 99.9% target -- **Test Coverage Status:** 58 tests across 14 files - -### Performance Benchmarks - -- **Credential Issuance:** ~3 seconds -- **IPFS Storage:** ~1 second -- **Blockchain Write:** ~500ms -- **Verification:** ~1.5 seconds -- **Selective Disclosure Generation:** ~800ms - -*** - -## ๐Ÿ›ก๏ธ Security Considerations - -### Implemented Security Measures - -- โœ… RSA-2048 digital signatures -- โœ… SHA-256 cryptographic hashing -- โœ… Secure password storage (Werkzeug with bcrypt) -- โœ… CSRF protection -- โœ… Session management -- โœ… Role-based access control -- โœ… Input validation and sanitization -- โœ… SQL injection prevention (SQLAlchemy ORM) -- โœ… XSS protection -- โœ… Secure HTTP headers - -### Security Best Practices - -โš ๏ธ **CRITICAL: Never commit sensitive data:** - -- โŒ Environment variables (`.env`) - NEVER commit to Git -- โŒ Private keys -- โŒ Database credentials -- โŒ API tokens -- โŒ Real user passwords - -๐Ÿ”’ **Production Deployment Checklist:** - -- [ ] Generate unique `SECRET_KEY` using `python -c "import secrets; print(secrets.token_urlsafe(32))"` -- [ ] Set strong passwords via environment variables -- [ ] Enable HTTPS/TLS -- [ ] Configure firewall rules -- [ ] Set up monitoring and alerts -- [ ] Regular security audits -- [ ] Keep dependencies updated -- [ ] Implement rate limiting -- [ ] Enable audit logging -- [ ] Use PostgreSQL in production (not SQLite) - -*** - -## ๐Ÿ”ฎ Roadmap & Future Enhancements - -### Phase 1: Enhanced Privacy (Q1 2026) - -- [ ] Advanced Zero-Knowledge Proof integration -- [ ] Range proofs for GPA verification -- [ ] Membership proofs for degree programs -- [ ] Attribute-based encryption - -### Phase 2: Scalability (Q2 2026) - -- [ ] Multi-chain support (Ethereum, Polygon) -- [ ] Layer-2 scaling solutions -- [ ] Batch verification optimization -- [ ] Distributed node network - -### Phase 3: Interoperability (Q3 2026) - -- [ ] W3C DID (Decentralized Identifiers) integration -- [ ] European Digital Identity Wallet compatibility -- [ ] OpenBadges v3.0 support -- [ ] Cross-border credential recognition - -### Phase 4: User Experience (Q4 2026) - -- [ ] Mobile application (iOS & Android) -- [ ] Digital wallet integration -- [ ] QR code verification -- [ ] Multi-language support - -*** - -## ๐Ÿ‘ฅ Project Team - -### Core Development Team - -#### Lead Architect, Backend & Blockchain Engineering -**[@udaycodespace](https://github.com/udaycodespace)** - [Somapuram Uday](https://www.linkedin.com/in/somapuram-uday/) -- End-to-end system architecture ownership and technical direction -- Design and implementation of blockchain simulation and consensus flow -- Cryptographic protocol development and security architecture -- Credential lifecycle and verification workflow orchestration -- Backend modularization (blueprints + service layer refactor) -- DevOps pipeline setup, container strategy, and deployment integration -- Performance tuning and platform stabilization - -#### Frontend & User Experience -**[@shashikiran47](https://github.com/shashikiran47)** - [Shashi Kiran](https://www.linkedin.com/in/sashi-kiran-02bb8a255/) -- UI/UX design and implementation across all user roles -- Responsive web design with mobile-first approach -- JavaScript integration and dynamic frontend interactions -- IPFS client-side handling and file management -- User workflow optimization and accessibility -- Interactive dashboard development -- Real-time data visualization components - -#### Quality Assurance & Documentation -**[@tejavarshith](https://github.com/tejavarshith)** - [Teja Varshith](https://www.linkedin.com/in/teja-varshith-85b921376/) -- System analysis and requirements documentation -- Comprehensive test case design and validation -- User acceptance testing and feedback integration -- Technical documentation and architecture diagrams -- API documentation and endpoint specifications -- User guides, tutorials, and help documentation -- Quality metrics tracking and reporting - -### Contribution Summary - -| Developer | Primary Focus | Key Contributions | -|:----------|:-------------|:------------------| -| **[@udaycodespace](https://github.com/udaycodespace)** | Lead Architect & Core Platform Owner | Architecture, Blockchain, Cryptography, Backend, CI/CD, DevOps | -| **[@shashikiran47](https://github.com/shashikiran47)** | Frontend & Design | Senior UI/UX, IPFS Integration, User Experience | -| **[@tejavarshith](https://github.com/tejavarshith)** | Testing & Documentation | Test Suite, QA, Technical Documentation | - -### Collaborative Achievements - -๐ŸŽฏ **Team Milestones:** - -- โœ… 100% test coverage on critical security paths -- โœ… Deployment-ready architecture achieved -- โœ… Comprehensive documentation suite completed -- โœ… Zero critical security vulnerabilities -- โœ… Docker containerization implemented -- โœ… CI/CD pipeline with automated testing and deployment -- โœ… Docker Hub integration for image distribution - -**Core platform architecture and implementation were led by Uday, with frontend and QA/documentation collaboration support from the team.** - -*** - -## ๐Ÿ™ Acknowledgements - -We express our sincere gratitude to: - -### Academic Guidance - -- **Dr. B. Thimma Reddy Sir - Project Guide** โ€” For invaluable technical insights and continuous mentorship throughout the project lifecycle -- **Dr. G. Rajeswarappa Sir - Faculty In-Charge, CST-A** โ€” For guidance on system design -- **Shri. K. Bala Chowdappa Sir - Mentor** โ€” For guidance on implementation strategies -- **Department Head** โ€” For providing resources and institutional support - -### Institutional Support - -- **G. Pulla Reddy Engineering College (Autonomous), Kurnool** - - For providing infrastructure and research facilities - - For encouraging innovation and academic excellence - - For supporting final year project initiatives - -### Technical Community - -- **W3C Verifiable Credentials Working Group** โ€” For standardization efforts -- **IPFS Community** โ€” For distributed storage solutions -- **Python Software Foundation** โ€” For excellent development tools -- **Flask Framework Team** โ€” For the robust web framework -- **Docker Community** โ€” For containerization best practices -- **Open-source Contributors** โ€” For various libraries and tools used in this project - -*** - -## ๐Ÿ“„ License & Intellectual Property - -**Project Classification:** B.Tech Final Year Project -**Version:** 2.1.0 (Elite Private Blockchain Release) -**Status:** Complete & Deployed -**Year:** 2026 - -### Proprietary License - All Rights Reserved - -**ยฉ 2026 CREDIFY.** This project is the exclusive intellectual property of the core development team (**Uday, Shashi, and Varshith**). Whole and sole, we 3 are owning it! - -This system was designed, built, and optimized natively by the core team for B.Tech demonstration. - -### Usage Policy - -- โœ… Academic evaluation and grading -- โœ… Portfolio demonstration for the core developers -- โŒ **Unauthorized replication, copying, or use of this codebase is strictly prohibited.** -- โŒ **Commercial use, distribution, or modifications are expressly forbidden.** - -*If you need to use or reference any part of this system, please DM us and we will talk. Unauthorized replication or use of this codebase may lead to legal issues.* - -### Citation - -If you use this project for academic or research purposes, please cite: - -``` -Blockchain-Based Verifiable Credential System for Academic Transcripts -Version 2.1.0 (Elite Private Blockchain Edition), 2026 -Developed by: Somapuram Uday, Shashi Kiran, Teja Varshith -Institution: G. Pulla Reddy Engineering College (Autonomous), Kurnool -GitHub: https://github.com/udaycodespace/credify +```bash +pytest --cov=app --cov=core --cov-report=html ``` -*** - -## ๐Ÿ“ž Support & Contact - -### Project Maintainers - -For questions, issues, or direct collaboration opportunities, please DM: - -- **Somapuram Uday** - [@udaycodespace](https://github.com/udaycodespace) | [LinkedIn](https://www.linkedin.com/in/somapuram-uday/) -- **Shashi Kiran** - [@shashikiran47](https://github.com/shashikiran47) | [LinkedIn](https://www.linkedin.com/in/sashi-kiran-02bb8a255/) -- **Teja Varshith** - [@tejavarshith](https://github.com/tejavarshith) | [LinkedIn](https://www.linkedin.com/in/teja-varshith-85b921376/) - -### Getting Help - -- **Issues:** [Open an issue](https://github.com/udaycodespace/credify/issues) on GitHub -- **Discussions:** Use [GitHub Discussions](https://github.com/udaycodespace/credify/discussions) for questions -- **Security:** Report security issues privately by contacting the maintainers - -### Project Links - -- **GitHub Repository:** [udaycodespace/credify](https://github.com/udaycodespace/credify) -- **Docker Hub:** [udaycodespace/credify](https://hub.docker.com/r/udaycodespace/credify) -- **How we built it:** [Story Time: The Origins of Credify](docs/STORY_TIME.md) -- **Documentation:** See `/docs` folder in repository - -*** - -## ๐ŸŽ‰ Project Status +Coverage focus: +- authentication and access flows +- blockchain integrity and consensus behavior +- cryptographic utilities and verification paths -**Current Version:** 2.1.0 (Elite Private Blockchain Edition) -**Status:** โœ… Production Ready -**Last Updated:** March 2026 -**Maintenance:** Active Development - -### Changelog (v2.1.0) - -#### New Features - -- โœจ Complete test suite with 58 tests -- โœจ Docker containerization with multi-stage builds -- โœจ CI/CD pipeline with GitHub Actions -- โœจ Automated Docker Hub publishing -- โœจ Enhanced security measures with environment variable configuration -- โœจ Comprehensive documentation -- โœจ Production-ready deployment configurations for Render -- โœจ **Elite 10/10 PDF Generation Engine** (March 2026) -- โœจ **Senior UI/UX Branding Overhaul** (March 2026) -- โœจ **Digital Authority Signature Hierarchy** (March 2026) -- โœจ **Multi-Node P2P Blockchain Network & Docker Orchestration** (March 2026) - -#### Improvements - -- โšก Optimized blockchain performance -- โšก Enhanced IPFS integration with fallback mechanisms -- โšก Improved error handling and logging -- โšก Better code organization and modularity -- โšก Enhanced UI/UX with responsive design -- โšก Automated deployment pipeline - -#### Bug Fixes - -- ๐Ÿ› Fixed authentication edge cases -- ๐Ÿ› Resolved IPFS connection timeout issues -- ๐Ÿ› Fixed credential versioning logic -- ๐Ÿ› Corrected timestamp handling in blockchain - -*** +--- -## ๐ŸŒŸ Why This Project Matters +## DevOps -Academic fraud costs institutions and employers billions annually. Traditional verification systems are: +CI/CD and containerization: +- GitHub Actions for test/build/publish automation +- Docker multi-stage builds +- Docker image publishing to Docker Hub +- validator-cluster orchestration via docker-compose -- โŒ Slow (days to weeks for verification) -- โŒ Expensive (administrative overhead and third-party fees) -- โŒ Centralized (single points of failure) -- โŒ Privacy-invasive (unnecessary full data exposure) +Deployment posture: +- deployment-ready for academic demos and controlled environments +- configurable environment variables for node identity and peers -Our solution provides: +--- -- โœ… Instant verification (< 2 seconds) -- โœ… Cost-effective (automated cryptographic process) -- โœ… Tamper-evident (custom private blockchain + signed records + IPFS-integrated storage) -- โœ… Privacy-preserving (selective disclosure with zero-knowledge proofs) +## Development Methodology (SDLC) -**Impact:** Transforming academic credential verification for the digital age, empowering students with data ownership while providing institutions and employers with trustworthy, instant verification. +### Team -*** +- Uday - Project Lead and Architect +- Shashi - Contributor +- Varshith - Contributor -## ๐Ÿš€ Deployment +### Approach -### Docker Hub Cluster Deployment +- Agile-style iterative development +- phase-based execution: + 1. Foundation (MVP) + 2. Distributed Architecture + 3. Feature Completeness + 4. Deployment and Polish +- continuous testing with pytest +- refactoring for stability and maintainability -```bash -# Clone the infrastructure repository directly -git clone https://github.com/udaycodespace/credify.git -cd credify +This project followed an iterative SDLC approach. +Each phase informed architectural decisions in the next, leading to a stable and defensible final system. +Lessons from the prototype directly shaped redesign choices, and the final phase prioritized stabilization, validation, and explainability. -# Boot up the 3-node P2P ledger (Node 1, Node 2, Node 3) -docker-compose up -d -``` +Engineering principle: +- The system prioritizes correctness, explainability, and controlled distributed behavior over full protocol complexity. +- The system is designed not to maximize decentralization, but to balance control, verifiability, and explainability in a permissioned environment. -### ๐Ÿ“– The Origin Story +--- -Before we built an elite Private Blockchain, we explored Steganography, Android Hostel Management, and Web3 Voting systems. +## Security -Read the full story of our engineering decisions and deep pivots here: -๐Ÿ‘‰ **[Story Time: The Origins of Credify](docs/STORY_TIME.md)** +Implemented controls: +- OTP-based privileged access model +- role-based access boundaries +- cryptographic signing and integrity checks +- tamper-evident finalized block model +- input validation and ORM-based query safety -### Manual Deployment +Operational recommendations: +- keep secrets in environment variables only +- enforce HTTPS/TLS in deployed environments +- rotate secrets regularly +- monitor logs and verification failures -See `docs/DEPLOYMENT.md` for detailed deployment instructions for various platforms. +--- -*** +## Roadmap -
+Future enhancements: +- PBFT-style consensus upgrade for stronger Byzantine tolerance +- validator slashing and governance controls +- IPFS cluster adoption +- stronger ZKP-inspired selective disclosure evolution toward full zero-knowledge proof protocols +- DID interoperability for portable credential identity -**Built with โค๏ธ by Team Credify** +--- -**Credify 2026** -*Blockchain-Based Verifiable Credentials* +## Team -**B.Tech Final Year Project** -**G. Pulla Reddy Engineering College (Autonomous)** -*Under Esteemed Guidance of: **Dr. B. Thimma Reddy Sir**, **Dr. G. Rajeswarappa Sir** and **Shri K Bala Chowdappa Sir*** +Core contributors: +- Uday: architecture, backend, blockchain, integration +- Shashi: implementation support, UI contribution, validation +- Varshith: debugging support, testing support, documentation support --- -[![GitHub Stars](https://img.shields.io/github/stars/udaycodespace/credify?style=social)](https://github.com/udaycodespace/credify) -[![Docker Hub](https://img.shields.io/badge/Docker-Hub-blue.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/udaycodespace/credify) -[![Project](https://img.shields.io/badge/Framework-Flask-orange.svg)](https://flask.palletsprojects.com/) +## Acknowledgements -*Securing Academic Credentials for the Future* +Academic guidance and institutional support from: +- Dr. B. Thimma Reddy Sir +- Dr. G. Rajeswarappa Sir +- Shri K. Bala Chowdappa Sir +- G. Pulla Reddy Engineering College (Autonomous), Kurnool -**[GitHub Project](https://github.com/udaycodespace/credify)** โ€ข **[Docker Images](https://hub.docker.com/r/udaycodespace/credify)** โ€ข **[Documentation Portal](https://github.com/udaycodespace/credify/tree/main/docs)** +Technical ecosystem acknowledgements: +- Python and Flask communities +- IPFS ecosystem contributors +- open-source contributors used by this project -
- -*** +--- -> [!NOTE] -> **๐Ÿš€ DOCUMENTATION STATUS: UPDATED** -> -> **Architecture Version:** 2.1.0 (Elite Private Blockchain & UI/UX Overhaul) -> -> **Current Edited Date:** `2026-03-08 19:50:00 IST` +## License +Project classification: B.Tech Final Year Project. +This repository is maintained for academic evaluation and portfolio demonstration by the core team. +For usage permissions, contact the maintainers: +- https://github.com/udaycodespace +- https://github.com/shashikiran47 +- https://github.com/tejavarshith diff --git a/app/app.py b/app/app.py index 6e62678..dc479e2 100644 --- a/app/app.py +++ b/app/app.py @@ -67,24 +67,36 @@ def init_extensions(app): blockchain.create_genesis_block() # P2P multi-node init - peer_nodes_env = os.environ.get("PEER_NODES", "") - if peer_nodes_env: - for peer in peer_nodes_env.split(","): - if peer.strip(): - try: - blockchain.register_node(peer.strip()) - except Exception as e: - logging.warning(f"Invalid peer URI: {peer.strip()}") + blockchain.node_id = app.config.get("NODE_ID", "standalone") + blockchain.node_address = (app.config.get("NODE_ADDRESS", "") or "").strip().rstrip("/") + local_node_address = (app.config.get("NODE_ADDRESS", "") or "").strip().rstrip("/") + peer_nodes = app.config.get("PEER_NODES", []) + + if peer_nodes: + for peer in peer_nodes: + if local_node_address and peer == local_node_address: + continue + try: + blockchain.register_node(peer) + except Exception: + logging.warning(f"Invalid peer URI: {peer}") if blockchain.nodes: threading.Thread(target=_initial_sync, args=(app,), daemon=True).start() + configured_node_validators = app.config.get("VALIDATOR_NODES", []) + if configured_node_validators: + blockchain.set_node_validators(configured_node_validators) + else: + blockchain.set_node_validators([blockchain._get_current_node_ref(), *blockchain.nodes]) + def _initial_sync(app): """Background peer synchronization task""" time.sleep(5) with app.app_context(): try: - logging.info(f"Syncing with peers: {blockchain.nodes}...") + node_id = app.config.get("NODE_ID", "standalone") + logging.info(f"Node {node_id} syncing with peers: {blockchain.nodes}...") if blockchain.resolve_conflicts(): logging.info(f"Synchronized chain. New length: {len(blockchain.chain)}") except Exception as e: diff --git a/app/blueprints/admin/routes.py b/app/blueprints/admin/routes.py index 4de6b5e..6d102e6 100644 --- a/app/blueprints/admin/routes.py +++ b/app/blueprints/admin/routes.py @@ -425,7 +425,7 @@ def api_system_stats(): stats["blockchain"] = { "blocks": len(blockchain.chain), "peers": len(blockchain.nodes), - "node_name": os.environ.get("NODE_NAME", "standalone"), + "node_name": current_app.config.get("NODE_ID") or os.environ.get("NODE_NAME", "standalone"), "validators": blockchain.VALIDATORS, } diff --git a/app/blueprints/api/routes.py b/app/blueprints/api/routes.py index 347c4d5..404960a 100644 --- a/app/blueprints/api/routes.py +++ b/app/blueprints/api/routes.py @@ -79,29 +79,23 @@ def receive_peer_block(): if not block_data: return jsonify({"success": False, "message": "No block data provided"}), 400 - # 1. Reconstruct block object - new_block = blockchain.block_model( - index=block_data["index"], - timestamp=block_data["timestamp"], - data=json.dumps(block_data["data"]), - merkle_root=block_data.get("merkle_root"), - previous_hash=block_data["previous_hash"], - nonce=block_data["nonce"], - hash=block_data["hash"], - signed_by=block_data.get("signed_by"), - signature=block_data.get("signature"), - ) + required_fields = {"index", "timestamp", "data", "previous_hash", "nonce", "hash"} + missing = [field for field in required_fields if field not in block_data] + if missing: + return jsonify({"success": False, "message": f"Missing required fields: {', '.join(missing)}"}), 400 - # 2. Simple validation against local chain - last_block = blockchain.get_latest_block() - if last_block and block_data["index"] <= last_block.index: - return jsonify({"success": False, "message": "Block already exists or is outdated"}), 409 + source_node = blockchain.normalize_node_ref(request.headers.get("X-Node-Address") or request.headers.get("X-Source-Node")) + origin_node = (request.headers.get("X-Origin-Node") or request.headers.get("X-Source-Node") or "unknown").strip() + sender_node = source_node or blockchain.normalize_node_ref(block_data.get("proposed_by")) - if last_block and block_data["previous_hash"] != last_block.hash: - return jsonify({"success": False, "message": "Previous hash mismatch. Sync required."}), 400 + if not blockchain.is_validator_node(sender_node): + return jsonify({"success": False, "message": f"Unauthorized validator node: {sender_node or 'unknown'}"}), 403 - # 3. Cryptographic validation (simplified for the model bridge) - # Create a Block object for validation methods + # Idempotency gate: if already present, ignore safely. + if blockchain.has_block(block_data["index"], block_data["hash"]): + return jsonify({"success": True, "message": "Duplicate block ignored"}), 200 + + # 1. Validate block object before any persistence from core.blockchain import Block v_block = Block( @@ -110,6 +104,8 @@ def receive_peer_block(): block_data["previous_hash"], signed_by=block_data.get("signed_by"), signature=block_data.get("signature"), + proposed_by=block_data.get("proposed_by"), + status=block_data.get("status"), ) v_block.timestamp = block_data["timestamp"] v_block.nonce = block_data["nonce"] @@ -119,16 +115,55 @@ def receive_peer_block(): if v_block.hash != v_block.calculate_hash(): return jsonify({"success": False, "message": "Invalid block hash"}), 400 - if blockchain.crypto_manager and v_block.signature: + if v_block.merkle_root and v_block.merkle_root != v_block.calculate_merkle_root(): + return jsonify({"success": False, "message": "Invalid Merkle root"}), 400 + + if v_block.index > 0 and v_block.signed_by not in blockchain.VALIDATORS: + return jsonify({"success": False, "message": "Unauthorized block signer"}), 403 + + if blockchain.crypto_manager: + if not v_block.signature: + return jsonify({"success": False, "message": "Missing digital signature"}), 400 if not blockchain.crypto_manager.verify_signature(v_block.hash, v_block.signature): return jsonify({"success": False, "message": "Invalid digital signature"}), 400 - # All checks passed, add to local DB and chain + # Finality gate: old blocks may omit status; accepted blocks become FINALIZED. + if v_block.status not in (None, "FINALIZED"): + return jsonify({"success": False, "message": "Block status must be FINALIZED"}), 400 + + # 2. Validate against local chain linkage + last_block = blockchain.get_latest_block() + if last_block and block_data["index"] <= last_block.index: + return jsonify({"success": True, "message": "Outdated block ignored"}), 200 + + if last_block and block_data["previous_hash"] != last_block.hash: + return jsonify({"success": False, "message": "Previous hash mismatch. Sync required."}), 400 + + # 3. Persist only after full validation + new_block = blockchain.block_model( + index=block_data["index"], + timestamp=block_data["timestamp"], + data=json.dumps(block_data["data"]), + merkle_root=block_data.get("merkle_root"), + previous_hash=block_data["previous_hash"], + nonce=block_data["nonce"], + hash=block_data["hash"], + signed_by=block_data.get("signed_by"), + signature=block_data.get("signature"), + ) + db.session.add(new_block) db.session.commit() + v_block.status = "FINALIZED" blockchain.chain.append(v_block) - logging.info(f"Accepted peer block {block_data['index']} from {block_data.get('signed_by')}") + # Controlled gossip propagation: relay accepted blocks, never back to sender. + blockchain.broadcast_block(v_block, source_node=source_node, origin_node=origin_node) + + logging.info( + f"Accepted peer block {block_data['index']} from signer={block_data.get('signed_by')} " + f"source={source_node or 'unknown'} origin={origin_node} sender={sender_node or 'unknown'}" + ) return jsonify({"success": True, "message": "Block accepted and added to chain"}) except Exception as e: diff --git a/app/config.py b/app/config.py index 7227188..5a1e0e3 100644 --- a/app/config.py +++ b/app/config.py @@ -37,6 +37,16 @@ class Config: SECRET_KEY = os.environ.get("SESSION_SECRET", "dev-secret-key-change-in-production") DEBUG = True PORT = int(os.environ.get("PORT", 5000)) + HOST = os.environ.get("HOST", "0.0.0.0") + + # Multi-node settings (backward compatible aliases) + NODE_ID = os.environ.get("NODE_ID") or os.environ.get("NODE_NAME") or "standalone" + NODE_ADDRESS = (os.environ.get("NODE_ADDRESS") or "").strip() + PEER_NODES = [ + peer.strip().rstrip("/") + for peer in os.environ.get("PEER_NODES", "").split(",") + if peer.strip() + ] # IPFS settings IPFS_ENDPOINTS = [ @@ -47,6 +57,17 @@ class Config: # Blockchain settings - FIXED paths BLOCKCHAIN_DIFFICULTY = 0 VALIDATOR_USERNAMES = ["admin", "issuer1"] + VALIDATOR_NODES = [ + node.strip().rstrip("/") + for node in os.environ.get( + "VALIDATORS", + os.environ.get( + "VALIDATOR_NODES", + "node1:5000,node2:5000,node3:5000,node4:5000,node5:5000,standalone", + ), + ).split(",") + if node.strip() + ] BLOCKCHAIN_FILE = DATA_DIR / "blockchain_data.json" # Crypto settings - FIXED path diff --git a/core/blockchain.py b/core/blockchain.py index a8c6da1..bc4001b 100644 --- a/core/blockchain.py +++ b/core/blockchain.py @@ -31,13 +31,16 @@ class Block: """Represents a single block in the blockchain""" - def __init__(self, index, data, previous_hash, signed_by=None, signature=None): + def __init__(self, index, data, previous_hash, signed_by=None, signature=None, proposed_by=None, status=None): self.index = index self.timestamp = datetime.now().isoformat() self.data = data self.previous_hash = previous_hash self.nonce = 0 self.signed_by = signed_by + self.proposed_by = proposed_by or os.environ.get("NODE_ID") or "standalone" + # Backward compatible: legacy blocks may not carry status. + self.status = status self.signature = signature self.merkle_root = self.calculate_merkle_root() self.hash = self.calculate_hash() @@ -105,6 +108,8 @@ def to_dict(self): "nonce": self.nonce, "hash": self.hash, "signed_by": self.signed_by, + "proposed_by": self.proposed_by, + "status": self.status, "signature": self.signature, } @@ -114,12 +119,16 @@ class SimpleBlockchain: # Authorized entities allowed to sign blocks VALIDATORS = ["admin", "issuer1", "System"] + NODE_VALIDATORS = {"node1:5000", "node2:5000", "node3:5000", "node4:5000", "node5:5000", "standalone"} def __init__(self, crypto_manager=None, db=None, block_model=None): self.chain = [] self.difficulty = 0 # Default to PoA (no difficulty) self.db = db self.block_model = block_model + self.node_id = os.environ.get("NODE_ID", "standalone") + self.node_address = (os.environ.get("NODE_ADDRESS") or "").strip().rstrip("/") + self.node_validators = set(self.NODE_VALIDATORS) # Inject crypto manager for block signing/verification self.crypto_manager = crypto_manager @@ -129,9 +138,119 @@ def __init__(self, crypto_manager=None, db=None, block_model=None): # NOTE: load_blockchain() and genesis creation must be called # within app_context if using DB storage. + def normalize_node_ref(self, node_ref): + """Normalize node identity/address values to netloc format for comparisons.""" + if not node_ref: + return "" + + from urllib.parse import urlparse + + candidate = str(node_ref).strip() + parsed = urlparse(candidate) + if parsed.netloc: + return parsed.netloc + if parsed.path and ":" in parsed.path: + return parsed.path + return candidate + + def has_block(self, index, block_hash): + """Idempotency guard: check whether a block already exists in memory/DB.""" + index_int = int(index) + for block in self.chain: + if block.index == index_int or block.hash == block_hash: + return True + + if self.block_model: + try: + existing = self.block_model.query.filter( + (self.block_model.index == index_int) | (self.block_model.hash == block_hash) + ).first() + return existing is not None + except Exception as e: + logging.debug(f"DB duplicate check failed: {e}") + + return False + + def set_node_validators(self, validators): + """Set permissioned validator nodes for participation checks.""" + normalized = set() + for node in validators or []: + ref = self.normalize_node_ref(node) + if ref: + normalized.add(ref) + if normalized: + self.node_validators = normalized + + def is_validator_node(self, node_ref): + """Check whether a node is part of permissioned validator set.""" + normalized = self.normalize_node_ref(node_ref) + return bool(normalized) and normalized in self.node_validators + + def _get_current_node_ref(self): + """Stable local node reference used in deterministic leader selection.""" + return self.normalize_node_ref(self.node_address) or str(self.node_id) + + def _canonicalize_data(self, value): + """Recursively canonicalize dict keys for deterministic block content serialization.""" + if isinstance(value, dict): + return {k: self._canonicalize_data(value[k]) for k in sorted(value.keys())} + if isinstance(value, list): + return [self._canonicalize_data(item) for item in value] + return value + + def get_consensus_ring(self): + """Return deterministic node ordering for round-robin leader selection.""" + ring = {self._get_current_node_ref()} + for node in self.nodes: + ref = self.normalize_node_ref(node) + if ref: + ring.add(ref) + return sorted(ring) + + def get_deterministic_leader(self, block_height): + """Leader = block_height % total_nodes over a deterministic node ring.""" + ring = self.get_consensus_ring() + total_nodes = len(ring) + leader_index = int(block_height) % total_nodes + return { + "leader": ring[leader_index], + "leader_index": leader_index, + "total_nodes": total_nodes, + "ring": ring, + } + + def _enforce_leader_for_block_creation(self): + """Gate local block creation to deterministic leader only.""" + block_height = len(self.chain) + leader_meta = self.get_deterministic_leader(block_height) + current_node = self._get_current_node_ref() + leader = leader_meta["leader"] + + logging.info( + "Leader check: height=%s total_nodes=%s leader_index=%s leader=%s current=%s", + block_height, + leader_meta["total_nodes"], + leader_meta["leader_index"], + leader, + current_node, + ) + + if current_node != leader: + raise PermissionError( + "Deterministic leader gate rejected block creation. " + f"Current node '{current_node}' is not leader '{leader}' at height {block_height}." + ) + def create_genesis_block(self): """Create the first block in the blockchain""" - genesis_block = Block(0, "Genesis Block - Academic Transcript Blockchain", "0", signed_by="System") + genesis_block = Block( + 0, + "Genesis Block - Academic Transcript Blockchain", + "0", + signed_by="System", + proposed_by=self.node_id, + status="FINALIZED", + ) genesis_block.mine_block(self.difficulty) self.chain.append(genesis_block) self.save_blockchain() @@ -186,6 +305,8 @@ def resolve_conflicts(self): block_data["previous_hash"], signed_by=block_data.get("signed_by"), signature=block_data.get("signature"), + proposed_by=block_data.get("proposed_by"), + status=block_data.get("status"), ) block.timestamp = block_data["timestamp"] block.nonce = block_data["nonce"] @@ -230,14 +351,34 @@ def _is_chain_valid_external(self, chain): return False return True - def broadcast_block(self, block): - """Broadcast a new block to all peer nodes""" + def broadcast_block(self, block, source_node=None, origin_node=None): + """Broadcast a block to peers with sender/origin tracking and loop controls.""" import requests + source_ref = self.normalize_node_ref(source_node) + local_ref = self.normalize_node_ref(self.node_address) + origin = origin_node or self.node_id + + headers = { + "X-Source-Node": self.node_id, + "X-Origin-Node": str(origin), + "X-Node-Address": self.node_address or self.node_id, + } + for node in self.nodes: + node_ref = self.normalize_node_ref(node) + if source_ref and node_ref == source_ref: + continue + if local_ref and node_ref == local_ref: + continue try: # Post the block to the peer's receive_block endpoint - requests.post(f"http://{node}/api/node/receive_block", json=block.to_dict(), timeout=2) + requests.post( + f"http://{node}/api/node/receive_block", + json=block.to_dict(), + headers=headers, + timeout=2, + ) except Exception as e: logging.debug(f"Failed to broadcast to {node}: {str(e)}") @@ -248,15 +389,34 @@ def add_block(self, data, signed_by="admin"): logging.error(f"Unauthorized block creation attempt by {signed_by}") raise PermissionError(f"User {signed_by} is not an authorized validator") + current_node = self._get_current_node_ref() + if not self.is_validator_node(current_node): + raise PermissionError( + "Permissioned validator gate rejected block creation. " + f"Node '{current_node}' is not in validator set {sorted(self.node_validators)}." + ) + + self._enforce_leader_for_block_creation() + previous_block = self.get_latest_block() new_index = len(self.chain) - new_block = Block(new_index, data, previous_block.hash if previous_block else "0", signed_by=signed_by) + canonical_data = self._canonicalize_data(data) + new_block = Block( + new_index, + canonical_data, + previous_block.hash if previous_block else "0", + signed_by=signed_by, + proposed_by=self.node_id, + ) new_block.mine_block(self.difficulty) # Sign the block hash if crypto_manager is provided if self.crypto_manager: new_block.signature = self.crypto_manager.sign_data(new_block.hash) + # Finality marker: accepted local blocks are finalized. + new_block.status = "FINALIZED" + self.chain.append(new_block) # Save to permanent storage @@ -264,7 +424,7 @@ def add_block(self, data, signed_by="admin"): logging.info(f"New block added with hash: {new_block.hash} by {signed_by}") # PROPAGATION: Broadcast to peers - self.broadcast_block(new_block) + self.broadcast_block(new_block, origin_node=self.node_id) return new_block @@ -306,6 +466,11 @@ def is_chain_valid(self): logging.error(f"Missing or unauthorized signature at block {i}") return False + # 5. Finality check (legacy blocks may omit status) + if getattr(current_block, "status", None) not in (None, "FINALIZED"): + logging.error(f"Non-finalized block at index {i}") + return False + return True def is_chain_valid_parallel(self): @@ -330,6 +495,9 @@ def verify_block(i): return False if not self.crypto_manager.verify_signature(current_block.hash, current_block.signature): return False + + if getattr(current_block, "status", None) not in (None, "FINALIZED"): + return False return True with ThreadPoolExecutor() as executor: @@ -389,6 +557,8 @@ def load_blockchain(self): rec.previous_hash, signed_by=rec.signed_by, signature=rec.signature, + proposed_by=rec.signed_by, + status="FINALIZED", ) block.timestamp = rec.timestamp block.nonce = rec.nonce @@ -415,6 +585,8 @@ def load_blockchain(self): block_data["previous_hash"], signed_by=block_data.get("signed_by"), signature=block_data.get("signature"), + proposed_by=block_data.get("proposed_by"), + status=block_data.get("status"), ) block.timestamp = block_data["timestamp"] block.nonce = block_data["nonce"] diff --git a/docker-compose.yml b/docker-compose.yml index e76abf8..e11c017 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,9 @@ services: ports: - "5001:5000" environment: + - NODE_ID=node1 - NODE_NAME=node1 + - NODE_ADDRESS=http://node1:5000 - PORT=5000 - HOST=0.0.0.0 - BASE_URL=http://localhost:5000 @@ -31,7 +33,9 @@ services: ports: - "5002:5000" environment: + - NODE_ID=node2 - NODE_NAME=node2 + - NODE_ADDRESS=http://node2:5000 - PORT=5000 - HOST=0.0.0.0 - BASE_URL=http://localhost:5000 @@ -55,7 +59,9 @@ services: ports: - "5003:5000" environment: + - NODE_ID=node3 - NODE_NAME=node3 + - NODE_ADDRESS=http://node3:5000 - PORT=5000 - HOST=0.0.0.0 - BASE_URL=http://localhost:5000 diff --git a/docs/AUTHENTICATION_GUIDE.md b/docs/AUTHENTICATION_GUIDE.md deleted file mode 100644 index 05ba29f..0000000 --- a/docs/AUTHENTICATION_GUIDE.md +++ /dev/null @@ -1,566 +0,0 @@ -๏ปฟ# Authentication System Guide - -**Version 2.2** | Hardened Multi-Portal Authentication for Private (PVT) Blockchain Infrastructure - -*** - -## Overview - -The Credify system has transitioned to a **Hardened Private Blockchain** architecture. Authentication is now isolated into dedicated role-specific portals to ensure maximum security and a premium user experience: - -- ** Issuer Portal (`/issuer`)** Academic Institutions & Network Controllers (MFA Enforced) -- ** Student Portal (`/holder`)** Credential Holders & Asset Managers -- ** Verifier Portal (`/verifier`)** Public verification gateway (No login required) - -Each role is strictly isolated via a **Multi-Portal Gatekeeper** to prevent unauthorized cross-portal access. - -*** - -## Authentication Architecture - -### Identity Trust Tiers (ITT) - -``` - - PRIVATE NETWORK ENTRANCE - - Request Portal Detection Role Context Entry Process - - - - - - ISSUER STUDENT - (/issuer) (/holder) - - - - MFA CHECK JWT/SID - (TOTP) VALIDATION - - - HIGH-SECURITY ACADEMIC HUB - DASHBOARD ACCESS -``` - -*** - -## Administrative Accounts - -### Issuer Account (Production Grade) - -> [!IMPORTANT] -> **Issuer accounts now require Multi-Factor Authentication (MFA).** Legacy default passwords like `admin123` are automatically randomized by the system during startup if MFA is active to "break the chain" of insecure access. - -``` -Access: Credential Minting, Ledger Management, System Governance -Security: Username + Password + 6-Digit TOTP Token -``` - -### Student Account (Verified Access) - -``` -Access: On-Chain Asset Viewing, Selective Disclosure, Identity Sharing -Security: Student ID (Roll Number) + Password -``` - -*** - -## Hardened Authentication Workflow - -### Step 1: Administrator Entry (Issuer Role) - -1. **Navigate to Issuer Portal** - ``` - http://localhost:5000/issuer - ``` -2. **Standard Credentials** - - Enter your authorized username and password. -3. **MFA Verification** - - Provide the 6-digit rolling code from your Google Authenticator or Authy app. - - **Emergency Bypass**: In case of lost phone, use the administrative secret: `adminadmin123` (Emergency use only). -4. **Administrative Dashboard** - - Access the one-page responsive hub for credential management. - -### Step 2: Student Entry (Holder Role) - -1. **Navigate to Student Portal** - ``` - http://localhost:5000/holder - ``` -2. **Roll Number Access** - - Enter your Student Roll Number as the username. - - Enter your secure password. -3. **Asset Dashboard** - - Access your private academic record vault. - -4. **Privacy Protection** - - Only sees own credentials - - Cannot access other students' data - - Complete data ownership - -*** - -### Step 3: Create Selective Disclosure (Student) - -1. **Select Credential** - - Navigate to credential in dashboard - - Click "Share" button -2. **Choose Fields to Disclose** - -``` -Selective Disclosure Options: - Student Name - Degree - GPA (only) - University - Student ID (hidden) - Date of Birth (hidden) - Full Transcript (hidden) -``` - -3. **Generate Zero-Knowledge Proof** - - Click "Generate Proof" - - System creates cryptographic proof - - Only selected fields included -4. **Share Proof** - -```json -{ - "credential_id": "CRED_xxxxx", - "disclosed_fields": { - "student_name": "John Doe", - "degree": "B.Tech Computer Science", - "gpa": 8.5 - }, - "proof": "cryptographic_proof_data", - "timestamp": "2024-12-26T14:51:00Z" -} -``` - - - Copy JSON proof - - Share with verifier via secure channel - -*** - -### Step 4: Verify Credential (Verifier Role) - -1. **Access Verifier Page** - -``` -Direct URL: http://localhost:5000/verifier -No authentication required (public access) -``` - -2. **Submit Verification Request** - -``` -Input Options: - Credential ID (full verification) - Selective Disclosure Proof (partial) - QR Code (future feature) -``` - -3. **Verification Process** - -``` -System Checks: - Blockchain hash validation - IPFS data retrieval - Cryptographic signature verification - Revocation status check - Issuer authenticity - Timestamp validation -``` - -4. **View Results** - -``` -Verification Response: - Status: Valid / Invalid / Revoked - Issuer: University name - Issue Date: Timestamp - Disclosed Data: Only shared fields - Verification Proof: Blockchain reference -``` - - -*** - -## Security Features - -### 1. Password Security - -```python -# Implementation Details (Reference Only) -- Algorithm: Werkzeug PBKDF2-SHA256 -- Iterations: 260,000+ -- Salt: Random per user -- Storage: Hashed only, never plain text -``` - - -### 2. Session Management - -```python -Session Data Structure: -{ - 'user_id': int, - 'username': str, - 'role': str, # 'issuer', 'student', 'verifier' - 'student_id': str, # For students only - 'created_at': timestamp, - 'expires_at': timestamp -} -``` - - -### 3. Role-Based Access Control - -``` -Access Matrix: - - Resource Issuer Student Verifier - - Issue Cred - View Own N/A N/A - Revoke - Verify - Selective - -``` - - -### 4. Data Privacy - -- **Student Isolation:** Each student sees only their credentials -- **Filter by ID:** Automatic filtering by `student_id` -- **Selective Disclosure:** Students control data sharing -- **Encrypted Storage:** Sensitive data encrypted at rest - -*** - -## System Architecture - -### Modified/New Files - -``` -app/ - models.py User model & database schema - auth.py Authentication decorators & middleware - config.py Security configurations - -templates/ - login.html Login interface - base.html Updated with auth buttons - issuer.html Protected issuer dashboard - holder.html Protected student dashboard - verifier.html Public verifier interface - -docs/ - AUTHENTICATION_GUIDE.md This document -``` - - -*** - -## Database Schema - -### Users Table - -```sql -CREATE TABLE users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username VARCHAR(80) UNIQUE NOT NULL, - password_hash VARCHAR(256) NOT NULL, - role VARCHAR(20) NOT NULL CHECK(role IN ('issuer', 'student', 'verifier')), - student_id VARCHAR(50) UNIQUE, - full_name VARCHAR(120), - email VARCHAR(120) UNIQUE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - last_login TIMESTAMP, - is_active BOOLEAN DEFAULT TRUE, - metadata JSON -); - -CREATE INDEX idx_username ON users(username); -CREATE INDEX idx_student_id ON users(student_id); -CREATE INDEX idx_role ON users(role); -``` - - -*** - -## User Management - -### Creating New Users - -#### Method 1: Python Script (Recommended) - -```python -# scripts/create_user.py -from app.app import app -from app.models import db, User - -with app.app_context(): - # Create new student - student = User( - username='CST002', - role='student', - student_id='CST002', - full_name='Jane Smith', - email='jane@example.edu' - ) - student.set_password('secure_password_here') - - db.session.add(student) - db.session.commit() - print(f" User {student.username} created successfully") -``` - - -#### Method 2: Interactive Script - -```bash -python scripts/create_admin.py -``` - -Follow the prompts to create users interactively. - -*** - -## API Endpoints - -### Public Endpoints (No Authentication) - -| Endpoint | Method | Description | -| :-- | :-- | :-- | -| `/` | GET | Home page | -| `/login` | GET | Login page | -| `/login` | POST | Login submission | -| `/logout` | GET | Logout \& session clear | -| `/verifier` | GET | Public verifier interface | -| `/api/verify_credential` | POST | Verify credential | -| `/api/blockchain_status` | GET | System statistics | - -### Protected Endpoints (Authentication Required) - -| Endpoint | Method | Role | Description | -| :-- | :-- | :-- | :-- | -| `/issuer` | GET | Issuer | Issuer dashboard | -| `/api/issue_credential` | POST | Issuer | Issue new credential | -| `/api/revoke_credential` | POST | Issuer | Revoke credential | -| `/holder` | GET | Student | Student dashboard | -| `/api/selective_disclosure` | POST | Student | Create disclosure proof | -| `/api/get_credential/` | GET | Auth | Get credential details | - - -*** - -## Environment Configuration - -### Required Environment Variables - -```bash -# Security (REQUIRED) -SECRET_KEY=your-secret-key-change-in-production -SESSION_SECRET=your-session-secret-change-in-production - -# Database -DATABASE_URL=sqlite:///credentials.db # Development -# DATABASE_URL=postgresql://user:pass@host:port/db # Production - -# Flask Configuration -FLASK_ENV=development # Change to 'production' for deployment -DEBUG=False # Set to False in production - -# Server -HOST=0.0.0.0 -PORT=5000 - -# Optional Features -IPFS_ENABLED=False -ENABLE_EMAIL_VERIFICATION=False -``` - - -### Security Best Practices - - **CRITICAL: Never expose these in version control:** - -- `.env` file should be in `.gitignore` -- Use environment-specific configurations -- Rotate secrets regularly in production -- Use strong, randomly generated keys - -```bash -# Generate secure secret key -python -c "import secrets; print(secrets.token_hex(32))" -``` - - -*** - -## Troubleshooting - -### Common Issues \& Solutions - -#### Issue 1: "Please login to access this page" - -**Cause:** Trying to access protected route without authentication -**Solution:** Login with appropriate credentials for the required role - -#### Issue 2: "Access denied. This page is only for [role]" - -**Cause:** Logged in with incorrect role -**Solution:** Logout and login with correct role credentials - -#### Issue 3: Student sees no credentials - -**Cause:** Student ID mismatch between credential and user account -**Solution:** - -- Verify student ID in user profile -- Ensure credentials issued with correct student ID -- Check database for data consistency - - -#### Issue 4: Cannot issue credentials - -**Cause:** Not logged in as issuer or missing required fields -**Solution:** - -- Confirm login with issuer role -- Validate all required fields are filled -- Check browser console for JavaScript errors - - -#### Issue 5: Session expires unexpectedly - -**Cause:** Short session timeout or browser cookie issues -**Solution:** - -- Check `SESSION_COOKIE_SECURE` settings -- Increase `PERMANENT_SESSION_LIFETIME` in config -- Clear browser cookies and re-login - -*** - -## Testing Checklist - -Use this checklist to verify complete system functionality: - -- [ ] **Issuer Workflow** - - [ ] Login as issuer - - [ ] Access issuer dashboard - - [ ] Issue credential for test student - - [ ] View issued credentials list - - [ ] Logout successfully -- [ ] **Student Workflow** - - [ ] Login as student - - [ ] View only own credentials (data isolation) - - [ ] Open credential details - - [ ] Create selective disclosure (GPA only) - - [ ] Copy generated proof - - [ ] Logout successfully -- [ ] **Verifier Workflow** - - [ ] Access verifier page (no login) - - [ ] Paste credential ID - - [ ] Verify full credential - - [ ] Paste selective disclosure proof - - [ ] Verify partial credential (only disclosed fields visible) -- [ ] **Security Testing** - - [ ] Attempt to access issuer page as student (should fail) - - [ ] Attempt to access student credentials as different student (should fail) - - [ ] Verify session expires after timeout - - [ ] Test logout clears session data - -*** - -## Production Deployment Checklist - -Before deploying to production: - -- [ ] **Change all default passwords** -- [ ] **Set strong SECRET_KEY and SESSION_SECRET** -- [ ] **Enable HTTPS/TLS (SSL certificates)** -- [ ] **Configure production database (PostgreSQL recommended)** -- [ ] **Set FLASK_ENV=production** -- [ ] **Disable DEBUG mode** -- [ ] **Implement rate limiting (Flask-Limiter)** -- [ ] **Add email verification for new accounts** -- [ ] **Set up password reset functionality** -- [ ] **Enable audit logging for all authentication events** -- [ ] **Configure secure session cookies** -- [ ] **Set up monitoring and alerting** -- [ ] **Perform security audit (OWASP guidelines)** -- [ ] **Configure firewall rules** -- [ ] **Set up automated backups** - -*** - -## Support \& Contributions - -### Getting Help - -If you encounter issues not covered in this guide: - -1. **Check Documentation:** - - Review `/docs` folder for additional guides - - See `TROUBLESHOOTING.md` for common issues -2. **Review Logs:** - - Check server logs in `/logs` directory - - Enable debug mode temporarily for detailed errors - - Review browser console for client-side errors -3. **Contact Development Team:** - - **Backend \& Authentication:** [@udaycodespace](https://github.com/udaycodespace) - - **Frontend \& UI:** [@shashikiran47](https://github.com/shashikiran47) - - **Testing \& Documentation:** [@tejavarshith](https://github.com/tejavarshith) -4. **Community Support:** - - Open an issue on GitHub repository - - Include error messages and logs - - Provide steps to reproduce the issue - -*** - -## Additional Resources - -- **W3C Verifiable Credentials:** [https://www.w3.org/TR/vc-data-model/](https://www.w3.org/TR/vc-data-model/) -- **Flask Security Best Practices:** [https://flask.palletsprojects.com/en/latest/security/](https://flask.palletsprojects.com/en/latest/security/) -- **OWASP Authentication Cheat Sheet:** [https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html) - -*** - -## Version History - -**v2.0** (Current) - -- Enhanced security features -- Improved session management -- Comprehensive documentation -- Production-ready configurations - -**v1.0** - -- Initial authentication implementation -- Basic role-based access control -- Core login/logout functionality - -*** - -
- -**Security First | Privacy Preserved | Trust Verified** - -
- -*** - -> [!NOTE] -> ** AUTHENTICATION GUIDE: UPDATED** -> -> **Architecture Version:** 2.1.0 -> -> **Current Edited Date:** `2026-03-08` - - diff --git a/docs/DOCKER_DEPLOYMENT.md b/docs/DOCKER_DEPLOYMENT.md index f83d7cf..0668caf 100644 --- a/docs/DOCKER_DEPLOYMENT.md +++ b/docs/DOCKER_DEPLOYMENT.md @@ -123,7 +123,7 @@ MIT License - Educational/Portfolio use > [!NOTE] > ** DOCKER HUB README: UPDATED** > -> **Architecture Version:** 2.1.0 +> **Architecture Version:** v2 > > **Current Edited Date:** `2026-03-08` diff --git a/docs/ENGINEERING_SPECS.md b/docs/ENGINEERING_SPECS.md index 743b0ea..7c01a35 100644 --- a/docs/ENGINEERING_SPECS.md +++ b/docs/ENGINEERING_SPECS.md @@ -1,20 +1,30 @@ ๏ปฟ# Project Overview -This system is a **centralized, blockchain-simulated credential verification platform**. It is designed to issue, store, and verify academic credentials using cryptographic primitives (SHA-256, RSA-2048) and a linked-data structure. -While it markets itself as a "blockchain," it strictly operates as a **single-node ledger** running on a Python Flask backend. It solves the problem of digital credential tampering by transforming a standard database into an append-only, cryptographically linked list. It is currently a **v2.1 Private Authority System** with an **Elite UI/UX Layer** and **10/10 PDF Generation**. +This system is a **permissioned private blockchain** implementing deterministic consensus with validator-based participation. It is designed to issue, store, and verify tamper-evident academic credentials using cryptographic primitives (SHA-256, RSA-2048), Merkle trees, and hash-linked blocks. + +It achieves immutability and tamper-evidence through cryptographic hash-linking (making past modifications immediately detectable) and ensures access control through a pre-authorized validator set. Blocks are signed by validator nodes and propagated across the network via HTTP gossip, providing institutional-grade credential verification with blockchain-backed provenance. + +**Current Version:** v2 **Permissioned Private Blockchain** with **Elite UI/UX Layer** and **10/10 PDF Generation**. # Architectural Philosophy -* **Centralized Authority**: The system relies entirely on a single trusted Issuer (the University/Server). There is no distributed consensus. Trust is placed in the server administrator and the integrity of the file system. -* **Deterministic Integrity**: Data integrity is enforced via cryptographic linking (hash chains) rather than distributed voting. If the file system is secure, the data is immutable. -* **Simulation vs. Reality**: The system intentionally executes "mining" (Proof-of-Work) and "block creation" logic to simulate the latency and computational cost of a public blockchain, despite running on a single centralized thread. + +* **Permissioned Consensus**: The validator set is pre-authorized (admin, issuer1, System), ensuring controlled participation while removing the need for trustless mechanisms like Proof-of-Work +* **Deterministic Finality**: Blocks achieve finality immediately upon creation (difficulty=0) through round-robin leader selection and RSA signing, eliminating confirmation delays +* **Tamper Evidence**: Hash-linking and Merkle roots make any modification to past blocks immediately evident when verified from genesis +* **Controlled Multi-Node Architecture**: Blocks propagate across validator nodes via HTTP gossip with idempotency checks and loop prevention, converging to canonical state +* **Institutional Trust Model**: Trust is placed in the pre-authorized validator set rather than anonymous consensus; suitable for credential systems where institutions are known and trusted # Codebase Breakdown ## `core/blockchain.py` -**Purpose**: The central ledger engine. -* **Logic**: Defines `Block` and `SimpleBlockchain` classes. Implements a linked-list data structure where every node (`Block`) contains the SHA-256 hash of the previous node. -* **Architectural Role**: Acts as the "database" but enforces sequential integrity. It creates a `blockchain_data.json` file which serves as the physical ledger. -* **Key Mechanism**: The `mine_block` function performs a CPU-intensive task (finding a nonce where hash starts with N zeros) purely to mimic blockchain difficulty, even though it adds no security in a centralized context. +**Purpose**: The permissioned blockchain engine with validator-based consensus. + +* **Architecture**: Defines `Block` and `SimpleBlockchain` classes implementing hash-linked blocks with Merkle roots and digital signatures +* **Consensus**: Implements deterministic round-robin leader selection from the validator set (difficulty=0 for immediate finality) +* **Validators**: Pre-authorized set (`VALIDATORS`, `NODE_VALIDATORS`) controls who can propose blocks +* **Signing**: Each block is signed by the proposing node using RSA-2048, providing non-repudiation +* **Propagation**: Blocks are broadcast via HTTP REST calls with idempotency checking and source-tracking +* **Role**: Acts as the core ledger with cryptographic finality guarantees through hash-linking ## `app/app.py` **Purpose**: The API Gateway and State Controller. @@ -65,45 +75,70 @@ While it markets itself as a "blockchain," it strictly operates as a **single-no * **Chain**: A Python List `[]` of `Block` objects, serialized to JSON. * **Hash**: SHA-256 (via `hashlib`), linking blocks sequentially. * **Validation**: The `previous_hash` field ensures that modifying an old block creates a cascading invalidation of all subsequent blocks. -* **Consensus**: **Simulated/Fake**. The `mine_block` function mimics Proof-of-Work (PoW), but since there is only one miner (the server itself), there is no competition and thus no actual consensus security. It is purely cosmetic or for rate-limiting. +* **Consensus**: **Deterministic Proof-of-Authority (PoA)**. The `mine_block` function with difficulty=0 provides immediate finality across the validator set. Round-robin leader selection ensures predictable block production without computational waste. # Security Analysis -## Secure by Design -* **Tamper-Evidence**: Any modification to a past credential requires re-mining that block and *every* subsequent block. This makes casual tampering detectable. -* **Cryptographic Signatures**: Usage of RSA-2048 ensures that credentials can be attributed to the issuer, independently of the chain state. +## Secure by Design (Permissioned Model) + +* **Tamper-Evidence**: Any modification to a past credential requires re-mining that block and every subsequent block, making tampering immediately detectable +* **Cryptographic Signatures**: RSA-2048 ensures credentials can be attributed to the issuer independently of chain state +* **Validator Authorization**: Only pre-authorized nodes can create blocks, preventing unauthorized participants from affecting state +* **Hash-Linking**: Each block's hash is cryptographically linked to the previous block, making the chain immutable +* **Block Finality**: Deterministic round-robin consensus (difficulty=0) ensures blocks are final immediately upon acceptance + +## Security Boundaries (Permissioned Assumptions) + +* **Trust Assumption**: System assumes validators are non-malicious or have aligned incentives (institutional setting) +* **Administrator Integrity**: System security depends on protecting validator private keys from compromise +* **Network Honesty**: HTTP propagation assumes network is honest (local deployment model works; public internet deployment requires TLS/mTLS) +* **File System Security**: Blockchain state stored in SQLite requires secure file system access controls + +## Attack Vectors & Mitigations + +* **Validator Compromise**: If validator private key is stolen, attacker can forge blocks โ†’ **Mitigation**: Use HSM/KMS for key storage in production +* **Network MITM**: Blocks in transit could be hijacked over HTTP โ†’ **Mitigation**: Enable TLS and certificate pinning for multi-network deployments +* **Database Corruption**: If SQLite database is corrupted, chain state is lost โ†’ **Mitigation**: Implement regular cryptographic validation and backups + +# What This IS: A Permissioned Private Blockchain + +This system **IS** a legitimate permissioned private blockchain because it implements: + +1. **Hash-Linked Blocks**: Every block contains the SHA-256 hash of its predecessor, creating an immutable chain +2. **Validator-Based Consensus**: A pre-defined set of validators takes turns creating blocks via deterministic round-robin selection +3. **Cryptographic Signing**: Blocks are signed by validators using RSA-2048, ensuring non-repudiation +4. **Multi-Node Architecture**: Multiple validator nodes can propose and propagate blocks, synchronizing state across the network +5. **Deterministic Finality**: Blocks are final immediately upon creation (difficulty=0), eliminating confirmation delays +6. **Tamper Evidence**: Any modification to past blocks creates detectable breaks in the hash chain -## Insecure by Limitation -* **Central Point of Failure**: The `data/` directory is the single source of truth. Deletion of this directory destroys the entire "network". -* **No Censorship Resistance**: The admin/issuer can decide to drop, edit, or simply not include any transaction. -* **Trust Assumption**: The Verifier must trust the server implicitly. They are not verifying the *state of the network*, they are asking the server "is this true?" and trusting the answer. +### Why It's Permissioned (Not Public) -## Attack Vectors -* **Server Compromise**: Root access to the server allows complete rewrite of history. -* **Replay Attacks**: Without a distributed timestamp server, the ordering of blocks is determined solely by the server's system clock, which can be manipulated. +- **Validator Set is Pre-Authorized**: Only known institutions/nodes can create blocks (defined in `VALIDATORS` and `NODE_VALIDATORS`) +- **No Trustless Consensus**: Unlike Bitcoin/Ethereum, no Proof-of-Work or Proof-of-Stake is needed because validators are pre-trusted +- **Institutional Model**: Designed for credential systems where issuers are known entities with identifiable interests +- **Controlled Participation**: Access control is enforced at block creation time, not consensus level -# Why This Is NOT Yet a Real Blockchain -1. **Zero Decentralization**: There is only one node. A blockchain requires a network of distinct, non-trusting peers. -2. **No Peer-to-Peer (P2P) Layer**: Blocks are not propagated; they are just saved to disk. -3. **No Distributed Consensus**: There is no mechanism (like Nakamoto Consensus or PBFT) for multiple parties to agree on the state. The "latest" state is whatever is in `JSON` file. -4. **Mutable Storage Backend**: The storage is a standard OS file system, not an immutable distributed ledger. +### Comparison to Public Blockchains -# What Is Needed to Convert This Into a PRIVATE BLOCKCHAIN -To make this a legitimate **Permissioned/Private Blockchain** (like Hyperledger Fabric or Quorum): +| Feature | Credify (Permissioned) | Bitcoin/Ethereum (Public) | +|---------|----------------------|---------------------------| +| **Validator Set** | Pre-authorized (3-5 nodes) | Anonymous (thousands) | +| **Consensus** | Deterministic round-robin (PoA) | Proof-of-Work / Stake | +| **Finality** | Immediate (difficulty=0) | Probabilistic (6+ blocks) | +| **Scalability** | High (low validator load) | Lower (everyone validates) | +| **Decentralization** | Moderate (trusted set) | High (trustless) | +| **Use Case** | Institutional credentials | Censorship-resistant money | -1. **Network Layer**: Implement a P2P socket layer (e.g., using `libp2p` or Python's `asyncio`) so multiple instances of the app can connect. -2. **Node Identity**: Each running instance needs a public/private key pair to sign blocks, proving *who* mined it. -3. **State Synchronization**: Implement a "Longest Chain Rule" or PBFT. Nodes must query peers for their latest blocks and sync upon startup. -4. **Consensus Algorithm**: Replace the "cosmetic" PoW with **Proof of Authority (PoA)**. A pre-defined set of "Validator Nodes" (identified by public keys) takes turns signing blocks. -5. **Distributed Storage**: Instead of writing to `data/`, blocks should be broadcast to peers, and each peer writes to its own local DB (e.g., LevelDB). +# Future Enhancements (Path to Production) -# What Is Needed to Convert This Into a PUBLIC BLOCKCHAIN -In addition to the Private steps: +This permissioned private blockchain is suitable for institutional credential systems. Future enhancements for improved security and scalability: -1. **Trustless Consensus**: Implement true Proof-of-Work (high difficulty) or Proof-of-Stake. -2. **Incentive Layer**: Introduce a native token/currency to pay miners/validators. Without this, no public node will run the software. -3. **Fork Handling**: Robust logic to handle "orphan blocks" and chain splits when two miners solve a block simultaneously. -4. **Merkle Trees**: Start using Merkle Trees inside blocks to store transactions efficiently, rather than storing raw data blobs. +1. **Byzantine Fault Tolerance**: Upgrade from round-robin to PBFT consensus to tolerate malicious validators +2. **Key Management System**: Migrate from plaintext PEM files to hardware security modules (HSM) or KMS for validator keys +3. **Cluster IPFS**: Coordinate multiple IPFS nodes into a cluster for improved data redundancy +4. **Validator Slashing**: Implement penalties for validators who sign conflicting blocks +5. **Zero-Knowledge Proofs**: Upgrade from hash commitments to production ZKP schemes (zk-SNARKs, Bulletproofs) +6. **TLS/mTLS**: Implement secure transport for inter-node communication in multi-network deployments # Scalability & Performance Considerations * **Bottleneck**: The JSON-based storage (`blockchain_data.json`) loads the *entire* chain into RAM on every restart. This will crash the system once the chain grows to ~100MB-1GB. @@ -120,7 +155,7 @@ In addition to the Private steps: > [!NOTE] > ** ENGINEER'S NOTES: UPDATED** > -> **System Version:** 2.1.0 (Elite Edition) +> **System Version:** v2 (Elite Edition) > **Institution:** G. Pulla Reddy Engineering College > **Guidance:** Dr. B. Thimma Reddy Sir, Dr. G. Rajeswarappa Sir and Shri Shri K Bala Chowdappa Sir > diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index cf10bd8..cd1f272 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -74,7 +74,7 @@ The following steps are identified as the next evolutionary stage for the projec - Impossible to forge blocks even with server access (requires private key). ### Step 3: Formal Proof of Authority (PoA) -**Goal:** Replace simulated Proof-of-Work with institutional consensus. +**Goal:** Upgrade from round-robin PoA to Byzantine Fault Tolerant consensus for malicious validator resilience. - Optimized block creation (instantaneous). - Authorized Validator list for adding new academic records. @@ -114,7 +114,7 @@ The following steps are identified as the next evolutionary stage for the projec > [!NOTE] > ** ROADMAP STATUS: UPDATED** > -> **Project Version:** 2.2.0 (PVT Master Edition) +> **Project Version:** v2 (PVT Master Edition) > **Institution:** G. Pulla Reddy Engineering College > **Guidance:** Dr. B. Thimma Reddy Sir, Dr. G. Rajeswarappa Sir and Shri Shri K Bala Chowdappa Sir > diff --git a/docs/SECURITY_ARCHITECTURE.md b/docs/SECURITY_ARCHITECTURE.md index 078ebd5..3eb271e 100644 --- a/docs/SECURITY_ARCHITECTURE.md +++ b/docs/SECURITY_ARCHITECTURE.md @@ -1,30 +1,53 @@ ๏ปฟ# Credify Security Architecture -Credify implements a multi-layer security model to ensure the integrity, confidentiality, and availability of academic credentials. +Credify implements a multi-layer security model built on permissioned blockchain principles to ensure integrity, confidentiality, and availability of academic credentials. -## 1. Cryptographic Layer -- **Hashing:** SHA-256 for block linking and integrity checks. -- **Asymmetric Encryption:** RSA-2048 for institutional digital signatures. -- **Signatures:** Every block is signed by the University's Private Key ensuring non-repudiation. -- **MFA (TOTP):** Time-based One-Time Passwords (RFC 6238) for all institutional actors. +## 1. Validator-Based Permissioning Layer -## 2. Ledger Integrity & Hardening -- **Append-Only:** Blocks are cryptographically linked to previous hashes. -- **Auto-Schema Migration:** Startup utility that automatically hardens the database schema (e.g., adding `totp_secret`) without data loss. -- **Zero-Trust Defaults:** System detects and randomizes default "admin123" credentials on startup to prevent chain-based attacks. -- **Proof of Work (Simulated):** Rate-limits block creation to prevent spam and mimic decentralized cost models. +- **Pre-Authorized Validators**: Only members of the validator set (`admin`, `issuer1`, `System`) can propose blocks +- **Node Authorization**: Validator nodes must be registered in `NODE_VALIDATORS` before participating in consensus +- **Signature Verification**: Each block must be signed by an authorized validator using RSA-2048 +- **Non-Repudiation**: Block field `signed_by` identifies the validator, preventing denial of participation -## 3. Identity & Access Control -- **Portal Isolation:** Physical URL separation between `/issuer` and `/holder` with role-specific gatekeepers. -- **Multi-Factor Shield**: Mandatory 6-digit TOTP verification for the `issuer` role. -- **Master Emergency Override**: A hardened "break-glass" credential (`adminadmin123`) for administrative recovery. +## 2. Cryptographic Layer -## 4. Data Privacy & Fallback -- **Selective Disclosure:** Students can choose which parts of their transcript to reveal to verifiers using ZKP-based proofs. -- **IPFS Storage:** Full credential data is stored in a content-addressed network (IPFS), while only the hash is stored on the ledger. +- **Hashing**: SHA-256 for block linking and integrity checks +- **Asymmetric Encryption**: RSA-2048 for institutional digital signatures ensuring block provenance +- **Merkle Trees**: Efficient proof of data integrity within each block +- **Block Finality**: Hash-linked blocks make all past modifications immediately detectable + +## 3. Consensus & Finality Layer + +- **Deterministic Consensus**: Round-robin leader selection (height % num_validators) ensures predictable block creation +- **Immediate Finality**: Difficulty=0 means blocks are final upon acceptance (no confirmation delays) +- **Propagation Safety**: Idempotency checks prevent duplicate block storage; source tracking prevents loops +- **Validator Participation**: All validator nodes must acknowledge quorum before finalization + +## 4. Identity & Access Control + +- **Portal Isolation**: Physical URL separation between `/issuer`, `/holder`, and `/verifier` with role-specific gatekeepers +- **Multi-Factor Authentication**: Mandatory 6-digit TOTP verification for the `issuer` role (RFC 6238) +- **Session Security**: Custom Flask session management with MFA challenges +- **Master Emergency Override**: Hardened "break-glass" credential for administrative recovery + +## 5. Data Privacy & Disclosure + +- **Selective Disclosure**: Students can choose which transcript fields to reveal to verifiers using disclosure proofs +- **IPFS Content Addressing**: Full credential data is stored via content-addressed network, only hash is on blockchain +- **Local Persistent Fallback**: If IPFS is unavailable, credentials fall back to local encrypted storage +- **Field-Level Privacy**: ZKP-based commitments allow proving attributes without full data revelation + +## 6. Ledger Integrity + +- **Append-Only Blocks**: Ensures no deletion or reordering of historical credentials +- **Tamper-Evidence**: Any modification to past blocks creates detectable hash chain breaks +- **Audit Trail**: Complete timestamp and digital signature history of all credentials +- **Block Validation**: Startup utility validates chain integrity from genesis to head *** +**Permissioned Private Blockchain Model**: Trust is placed in a pre-authorized set of validators rather than anonymous consensus mechanisms. Suitable for institutional credential systems where issuers are known entities. + **G. Pulla Reddy Engineering College (Autonomous)** **Guidance:** Dr. B. Thimma Reddy Sir, Dr. G. Rajeswarappa Sir and Shri Shri K Bala Chowdappa Sir -**Dated:** 2026-03-08 +**Updated:** 2026-03-25 diff --git a/docs/STORY_TIME.md b/docs/STORY_TIME.md index a0176b1..bf958e0 100644 --- a/docs/STORY_TIME.md +++ b/docs/STORY_TIME.md @@ -39,21 +39,21 @@ Thus, **CREDIFY** was born. *** -## The Evolution to "Elite" (The Mock vs. The Private Cloud) +## The Evolution to "Elite" (From Proof-of-Concept to Production) -### Phase 1: The "Mock" Blockchain (Late 2025) -We initially developed a "mock" blockchain entirely in Python 3. It worked conceptually: it hashed blocks and signed documents securely. However, it was localized entirely in memory. It was an excellent proof-of-concept, but it lacked the true decentralized networking required of a genuine blockchain. +### Phase 1: Initial Blockchain Foundation (Late 2025) +We initially developed a blockchain prototype in Python 3 as a proof-of-concept. It successfully hashed blocks and signed documents. However, it was localized in a single node without multi-node consensus or network propagation. -### Phase 2: The Transition to a True Private Blockchain (March 8, 2026) -We refused to settle for a "mock" implementation. On March 8, 2026, guided by Uday's deep dive into DevOps and system architecture, we radically transitioned the platform. +### Phase 2: The Transition to a Permissioned Private Blockchain (March 8, 2026) +On March 8, 2026, guided by Uday's deep dive into DevOps and system architecture, we radically upgraded the platform. -We tore down the mock ledger and orchestrated a beautifully engineered **3-Node Private Permissioned Blockchain**. We containerized our Flask/Werkzeug cores into isolated Docker containers (`node1`, `node2`, `node3`), bridged them across an internal P2P network, and wrote dynamic consensus algorithms. Now, when a node spins up, it actively seeks its peers and synchronizes the global ledger asynchronously. +We architected a beautifully engineered **3-Node Private Permissioned Blockchain** with deterministic validator-based consensus. We containerized our Flask/Werkzeug cores into isolated Docker containers (`node1`, `node2`, `node3`), bridged them across an internal network, and implemented round-robin leader selection. Now, when a node spins up, it actively synchronizes with its peers and participates in validator-based block creation. We layered it with **IPFS Distributed Storage**, bolted on **Zero-Knowledge Proofs (ZKPs)** for student privacy, and wrapped the entire engine in Shashi's breathtaking "Senior UI/UX" overhaul. *** -This is the story of how three engineering students went from an outdated steganography idea to building a production-ready, enterprise-grade Dockerized Blockchain network. +This is the story of how three engineering students went from an outdated steganography idea to building an academic-grade, permissioned private blockchain network with deterministic consensus and cryptographic finality. **Whole and sole, we 3 are owning it.** diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md deleted file mode 100644 index f121722..0000000 --- a/docs/TROUBLESHOOTING.md +++ /dev/null @@ -1,807 +0,0 @@ -๏ปฟ# Troubleshooting Guide - -**Version 2.0** | Common issues and solutions for the Blockchain-Based Verifiable Credentials System - -*** - -## Quick Diagnosis - -Before diving into specific issues, run this quick checklist: - -- [ ] Flask server is running on port 5000 -- [ ] Environment variables are properly configured -- [ ] All required files are present in the project directory -- [ ] Database is initialized -- [ ] At least one user account exists -- [ ] Browser cache is cleared - -*** - -## Common Issues \& Solutions - -### Issue 1: Network Error When Verifying Credentials - -**Symptoms:** - -- "Network error occurred" message appears -- Verification fails immediately -- No response from server - -**Solutions:** - -#### Step 1: Verify Server is Running - -Check your terminal for: - -``` - - Blockchain Credential Verification System - Starting server... - Host: 0.0.0.0 - Port: 5000 - Environment: Development - - - * Running on http://127.0.0.1:5000 - * Running on http://0.0.0.0:5000 -``` - -If not running, start it: - -```bash -python main.py -``` - - -#### Step 2: Check Browser Console - -1. Open Developer Tools (F12) -2. Navigate to "Console" tab -3. Look for error messages -4. Check "Network" tab for failed requests - -**Common Console Errors:** - -```javascript -// Error: Failed to fetch -// Solution: Server is not running or wrong port - -// Error: 404 Not Found -// Solution: Incorrect API endpoint URL - -// Error: 500 Internal Server Error -// Solution: Check server logs for Python errors -``` - - -#### Step 3: Verify API Endpoints - -Test if server is responding: - -```bash -# Test health endpoint -curl http://localhost:5000/api/blockchain_status - -# Expected response: -# {"success": true, "blockchain_length": X, ...} -``` - - -*** - -### Issue 2: Authentication Problems - -**Symptoms:** - -- "Please login to access this page" message -- Redirected to login page unexpectedly -- Cannot access issuer/holder dashboards - -**Solutions:** - -#### A. Invalid Credentials - -**Problem:** Username or password incorrect - -**Solution:** - -1. Verify you're using correct credentials -2. Check for typos (usernames are case-sensitive) -3. Ensure user account exists in database - -**Reset Password:** - -```bash -python scripts/reset_password.py -``` - - -#### B. MFA / 2FA Failures -**Problem:** "Invalid Security Token" or "Authenticator Desync" - -**Solution:** -1. **Clock Sync**: Ensure your phone's clock (Authenticator app) is synchronized with the server time. TOTP codes are time-dependent. -2. **Fresh Tokens**: Only enter the code while it is still "active" (spinning animation in your app). -3. **Emergency Bypass**: If you have lost your device, use the master emergency token in the 6-digit field: `adminadmin123`. - -#### C. Session Expired -**Problem**: Session timeout or portal redirect - -**Solution**: -1. Log out completely from the current hub. -2. Ensure you are at the correct portal: [`/issuer`](http://localhost:5000/issuer) for Admins, [`/holder`](http://localhost:5000/holder) for Students. -3. Clear cookies for `localhost` and re-login. - -#### D. Missing SECRET_KEYS -**Problem**: No session secret configured in environment - -**Solution**: -Create or update your `.env` file with a strong key: -```bash -# .env -SECRET_KEY=your-strong-random-key -``` - -*** - -### Issue 3: Credential Issuance Failures - -**Symptoms:** - -- "Error issuing credential" message -- Form submission doesn't complete -- No credential ID returned - -**Solutions:** - -#### A. Missing Required Fields - -**Problem:** Form validation failed - -**Solution:** -Ensure all required fields are filled: - -``` -Required Fields: - Student Name (non-empty) - Student ID (unique) - Degree (non-empty) - University (non-empty) - GPA (0.0 - 10.0) - Graduation Year (valid year) - Issue Date (auto-generated) -``` - - -#### B. Duplicate Student ID - -**Problem:** Credential already exists for this student - -**Error:** "Credential already exists for student ID" - -**Solution:** - -1. Use different student ID, or -2. Revoke existing credential first, or -3. Create new version of credential - -#### C. Cryptographic Key Issues - -**Problem:** Missing or corrupted RSA keys - -**Error:** "Failed to sign credential" - -**Solution:** - -```bash -# Delete old keys -rm issuer_keys.pem -rm issuer_public_key.pem - -# Restart server (will regenerate keys) -python main.py -``` - - -*** - -### Issue 4: IPFS Connection Problems - -**Symptoms:** - -- "Could not store credential on IPFS" warning -- Slow credential issuance -- "Using local storage fallback" message - -**Solutions:** - -#### A. IPFS Node Not Running (Expected Behavior) - -**This is NORMAL** - the system automatically uses local storage fallback. - -**To verify fallback is working:** - -1. Check for `data/ipfs_storage.json` file -2. Should contain credential data -3. System continues to function normally - -#### B. Enable IPFS (Optional) - -If you want to use actual IPFS: - -**Install IPFS:** - -```bash -# Download from https://ipfs.io/ -# Or use package manager - -# Windows (Chocolatey) -choco install ipfs - -# Mac (Homebrew) -brew install ipfs - -# Linux -sudo snap install ipfs -``` - -**Start IPFS Daemon:** - -```bash -ipfs init -ipfs daemon -``` - -**Update `.env`:** - -```bash -IPFS_ENABLED=True -``` - - -*** - -### Issue 5: Database Errors - -**Symptoms:** - -- "Database is locked" error -- "Table doesn't exist" error -- "No such column" error - -**Solutions:** - -#### A. Database Not Initialized - -**Error:** `sqlalchemy.exc.OperationalError: no such table: users` - -**Solution:** - -```bash -# Initialize database -python -c "from app.models import init_database; from app.app import app; init_database(app)" - -# Or using Makefile -make init-db -``` - - -#### B. Database Locked - -**Error:** `sqlite3.OperationalError: database is locked` - -**Solution:** - -```bash -# Stop all running instances of the app -# Delete database lock file -rm instance/credentials.db-journal - -# Restart server -python main.py -``` - - -#### C. Corrupted Database - -**Last Resort Solution:** - -```bash -# Backup existing database -cp instance/credentials.db instance/credentials.db.backup - -# Delete and recreate -rm instance/credentials.db -python -c "from app.models import init_database; from app.app import app; init_database(app)" - -# Create new admin user -python scripts/create_admin.py -``` - - -*** - -### Issue 6: Verification Failures - -**Symptoms:** - -- "Credential not found" error -- "Invalid signature" error -- "Verification failed" message - -**Solutions:** - -#### A. Invalid Credential ID - -**Problem:** Wrong or incomplete credential ID - -**Solution:** - -1. Credential IDs look like: `CRED_a1b2c3d4...` -2. Copy the complete ID (no spaces) -3. Try again with correct ID - -#### B. Credential Not Yet Issued - -**Problem:** Verifying before issuance completes - -**Solution:** - -1. Wait 2-3 seconds after issuing -2. Check issuer dashboard for confirmation -3. Verify credential appears in registry - -#### C. Blockchain Integrity Check Failed - -**Problem:** Blockchain data corrupted - -**Solution:** - -```bash -# Backup current data -cp data/blockchain_data.json data/blockchain_data.json.backup - -# Reset blockchain (WARNING: deletes all records) -rm data/blockchain_data.json -python main.py -``` - - -*** - -### Issue 7: Selective Disclosure Problems - -**Symptoms:** - -- "Failed to create proof" error -- Disclosed fields not showing -- Proof generation hangs - -**Solutions:** - -#### A. Invalid Field Selection - -**Problem:** Requesting non-existent fields - -**Solution:** -Only select fields that exist in the credential: - -``` -Valid Fields: - student_name - student_id - degree - university - gpa - graduation_year - courses (array) -``` - - -#### B. Empty Field Selection - -**Problem:** No fields selected - -**Solution:** -Select at least one field before generating proof - -#### C. Proof Format Error - -**Problem:** Generated proof is malformed - -**Solution:** - -```bash -# Clear credential cache -rm data/credentials_registry.json - -# Reissue credential -# Try selective disclosure again -``` - - -*** - -### Issue 8: Port Already in Use - -**Symptoms:** - -- "Address already in use" error -- Server fails to start -- Port 5000 unavailable - -**Solutions:** - -#### Windows: - -```powershell -# Find process using port 5000 -netstat -ano | findstr :5000 - -# Kill the process (replace PID) -taskkill /PID /F -``` - - -#### Mac/Linux: - -```bash -# Find and kill process -lsof -ti:5000 | xargs kill -9 - -# Or use different port -export PORT=5001 -python main.py -``` - - -*** - -### Issue 9: Static Files Not Loading - -**Symptoms:** - -- Page appears unstyled -- JavaScript not working -- 404 errors for CSS/JS files - -**Solutions:** - -#### A. Check File Structure - -Verify files exist: - -``` -static/ - css/ - style.css - js/ - app.js -``` - - -#### B. Clear Browser Cache - -``` -Chrome/Edge: Ctrl + Shift + Delete -Firefox: Ctrl + Shift + Delete -Safari: Cmd + Option + E -``` - - -#### C. Hard Refresh - -``` -Windows: Ctrl + F5 -Mac: Cmd + Shift + R -``` - - -*** - -### Issue 10: Permission Denied Errors - -**Symptoms:** - -- Cannot write to data files -- Permission errors in logs -- Database creation fails - -**Solutions:** - -#### Windows: - -```powershell -# Run as Administrator -# Or grant full permissions to project folder -``` - - -#### Mac/Linux: - -```bash -# Fix permissions -chmod -R 755 . -chmod -R 777 data/ -chmod -R 777 logs/ -``` - - -*** - -## System Health Check - -Run this diagnostic script to check system status: - -```bash -# Create health_check.py -python << 'EOF' -import os -import sys -from pathlib import Path - -print(" System Health Check\n") - -# Check Python version -print(f" Python Version: {sys.version.split()[^0]}") - -# Check required files -required_files = [ - 'main.py', 'requirements.txt', '.env', - 'app/app.py', 'app/models.py', 'app/auth.py', - 'core/blockchain.py', 'core/crypto_utils.py' -] - -missing = [] -for file in required_files: - if Path(file).exists(): - print(f" {file}") - else: - print(f" {file} - MISSING") - missing.append(file) - -# Check data directories -data_dirs = ['data', 'logs', 'static', 'templates', 'instance'] -for dir in data_dirs: - if Path(dir).exists(): - print(f" {dir}/ directory") - else: - print(f" {dir}/ directory missing - will be created") - -# Check environment variables -env_vars = ['SECRET_KEY', 'SESSION_SECRET'] -for var in env_vars: - if os.getenv(var): - print(f" {var} is set") - else: - print(f" {var} not set - using default") - -if missing: - print(f"\n Missing {len(missing)} critical files") - sys.exit(1) -else: - print("\n All critical files present") - sys.exit(0) -EOF -``` - - -*** - -## Testing Workflow - -Follow this step-by-step process to verify system functionality: - -### Step 1: Start Server - -```bash -# Activate virtual environment (if using) -# Windows -venv\Scripts\activate - -# Mac/Linux -source venv/bin/activate - -# Start server -python main.py -``` - -**Expected Output:** - -``` - Application initialized successfully! - - - Blockchain Credential Verification System - Starting server... -... - * Running on http://127.0.0.1:5000 -``` - - -### Step 2: Create Admin Account (First Time Only) - -```bash -python scripts/create_admin.py -``` - -Follow prompts to set up administrator credentials. - -### Step 3: Issue Test Credential - -1. **Navigate to:** `http://localhost:5000` -2. **Login** with admin credentials -3. **Fill form:** - -``` -Student Name: Test Student -Student ID: TEST001 -Degree: B.Tech Computer Science -University: G. Pulla Reddy Engineering College -GPA: 8.5 -Graduation Year: 2025 -``` - -4. **Click:** "Issue Credential" -5. **Copy:** Credential ID (e.g., `CRED_abc123...`) - -### Step 4: Verify Credential - -1. **Navigate to:** `http://localhost:5000/verifier` -2. **Paste:** Credential ID -3. **Click:** "Verify Credential" -4. **Expected:** Green success message with student details - -### Step 5: Test Selective Disclosure - -1. **Logout** from issuer -2. **Login** as student (username: TEST001) -3. **Navigate to:** Holder dashboard -4. **Click:** "Share" on credential -5. **Select:** Only GPA field -6. **Generate:** Proof -7. **Copy:** Proof JSON -8. **Verify:** Proof on verifier page -9. **Expected:** Only GPA visible, other fields hidden - -*** - -## Emergency Reset - -If nothing else works, perform a complete system reset: - -```bash -# CAUTION: This deletes ALL data - -# Stop server (Ctrl+C) - -# Delete data files -rm -rf data/*.json -rm -rf instance/*.db -rm -rf *.pem - -# Delete cache -rm -rf __pycache__ -rm -rf app/__pycache__ -rm -rf core/__pycache__ - -# Reinstall dependencies -pip install -r requirements.txt - -# Initialize fresh database -python -c "from app.models import init_database; from app.app import app; init_database(app)" - -# Create new admin -python scripts/create_admin.py - -# Restart server -python main.py -``` - - -*** - -## Getting Help - -If issues persist after following this guide: - -### 1. Check Logs - -```bash -# Server logs (in terminal) -# Look for stack traces and error messages - -# Application logs -cat logs/app.log -``` - - -### 2. Enable Debug Mode - -In `.env`: - -```bash -FLASK_ENV=development -DEBUG=True -``` - -**WARNING:** Never enable debug mode in production! - -### 3. Contact Development Team - -- **Backend Issues:** [@udaycodespace](https://github.com/udaycodespace) -- **Frontend Issues:** [@shashikiran47](https://github.com/shashikiran47) -- **Documentation Issues:** [@tejavarshith](https://github.com/tejavarshith) - - -### 4. Create GitHub Issue - -Include: - -- Error messages (full stack trace) -- Steps to reproduce -- System information (OS, Python version) -- Screenshots (if applicable) - -*** - -## Additional Resources - - - **README.md** - System overview and setup - - **AUTHENTICATION_GUIDE.md** - Login and user management - - **Description.md** - Technical architecture - - **API.md** - API endpoint documentation - - *** - - ### Issue 11: PDF Generation Errors - - **Symptoms:** - - - "Elite PDF Generation error" in logs - - 500 Internal Server Error when clicking "Download PDF" - - ReportLab import failures - - **Solutions:** - - 1. **Import Errors:** Ensure `reportlab` is installed (`pip install reportlab`). - 2. **Logo Missing:** Ensure `static/images/collegelogo.png` exists. - 3. **Font Errors:** The system uses standard Helvetica/Courier. Ensure no corrupt font files are in the system path. - - *** - - ### Issue 12: UI/UX Spacing & Scaling - - **Symptoms:** - - - Certificate header looks cramped - - QR code overflows border - - Text overlaps on small screens - - **Solutions:** - - 1. **Clear Cache:** The new CSS (v2.1) requires a hard refresh (Ctrl+F5). - 2. **Scale Factor:** Ensure browser zoom is at 100% for the most accurate certificate representation. - 3. **Responsive Check:** If elements overlap, ensure you are using a modern browser (Chrome/Edge recommended). - - *** - -
- - **Still stuck? Don't worry!** - - **Open an issue on GitHub with detailed error logs** - - *** - - *Troubleshooting guide last updated: March 08, 2026* - - *** - - > [!NOTE] - > ** TROUBLESHOOTING STATUS: UPDATED** - > - > **Architecture Version:** 2.1.0 - > - > **Current Edited Date:** `2026-03-08` - diff --git a/docs/TUTORIAL.md b/docs/TUTORIAL.md deleted file mode 100644 index e185413..0000000 --- a/docs/TUTORIAL.md +++ /dev/null @@ -1,1981 +0,0 @@ -๏ปฟ# Complete Tutorial: Blockchain-Based Verifiable Credentials System - -**Version 2.1** | A comprehensive guide to building, understanding, and using a blockchain-based academic credential verification platform (Elite UI/UX Edition) - -*** - -## Table of Contents - -1. [Introduction](#introduction) -2. [System Requirements](#system-requirements) -3. [Understanding Core Concepts](#understanding-core-concepts) -4. [Installation Guide](#installation-guide) -5. [System Architecture Deep Dive](#system-architecture-deep-dive) -6. [Implementation Walkthrough](#implementation-walkthrough) -7. [Usage Scenarios](#usage-scenarios) -8. [Security Analysis](#security-analysis) -9. [Troubleshooting](#troubleshooting) -10. [Advanced Topics](#advanced-topics) -11. [Best Practices](#best-practices) -12. [Conclusion](#conclusion) - -*** - -## Introduction - -### What is This System? - -This tutorial provides a complete, step-by-step guide to building and deploying a **production-ready blockchain-based verifiable credential system** for academic transcripts. The system demonstrates real-world applications of cutting-edge technologies: - -- **Blockchain Technology** Immutable, tamper-proof record keeping -- **IPFS (InterPlanetary File System)** Decentralized credential storage -- **RSA-2048 Cryptography** Digital signatures for authenticity -- **W3C Verifiable Credentials** Industry-standard credential format -- **Zero-Knowledge Proofs** Privacy-preserving selective disclosure -- **Elite 10/10 PDF Engine** Senior-grade academic document generation (March 2026) - - -### The Problem We're Solving - -**Traditional Academic Credential Verification:** - -- Slow (days to weeks for verification) -- Expensive (manual administrative overhead) -- Fraud-prone (certificates can be forged) -- Privacy-invasive (full transcript exposure required) -- Centralized (single points of failure) - -**Our Blockchain Solution:** - -- Instant verification (< 2 seconds) -- Cost-effective (automated process) -- Tamper-proof (cryptographic guarantees) -- Privacy-preserving (selective disclosure) -- Decentralized (no single authority) - - -### Project Context - -**Academic Information:** - -- **Institution:** G. Pulla Reddy Engineering College (Autonomous), Kurnool -- **Department:** Computer Science Engineering -- **Project Type:** B.Tech Final Year Project -- **Version:** 2.2 (Private PVT Blockchain - Master Security Edition) - -**Development Team:** - -- **Backend \& Blockchain:** [@udaycodespace](https://github.com/udaycodespace) -- **Frontend \& IPFS:** [@shashikiran47](https://github.com/shashikiran47) -- **Testing \& Documentation:** [@tejavarshith](https://github.com/tejavarshith) - -*** - -## System Requirements - -### Software Prerequisites - -#### Required Software - -| Software | Minimum Version | Purpose | -| :-- | :-- | :-- | -| **Python** | 3.10+ | Core programming language | -| **pip** | Latest | Python package manager | -| **Git** | 2.30+ | Version control | -| **Web Browser** | Chrome 90+ / Firefox 88+ | User interface | -| **Code Editor** | VS Code (recommended) | Development environment | - -#### Operating System Support - -- **Windows 10/11** Full support -- **macOS 11+** Full support -- **Linux (Ubuntu 20.04+)** Full support - - -### Hardware Requirements - -**Minimum Specifications:** - -- CPU: Dual-core processor -- RAM: 4GB -- Storage: 2GB free space -- Network: Stable internet connection - -**Recommended Specifications:** - -- CPU: Quad-core processor -- RAM: 8GB+ -- Storage: 5GB+ free space -- Network: Broadband connection - - -### Python Dependencies - -**Core Dependencies:** - -```txt -Flask==3.0.0 # Web framework -cryptography==41.0.7 # RSA encryption & signatures -requests==2.31.0 # HTTP client for IPFS -SQLAlchemy==2.0.23 # Database ORM -Flask-Login==0.6.3 # Session management -Werkzeug==3.0.1 # WSGI utilities -Jinja2==3.1.2 # Template engine -``` - -**Development Dependencies:** - -```txt -pytest==7.4.3 # Testing framework -pytest-cov==4.1.0 # Coverage reporting -black==23.12.1 # Code formatter -flake8==7.0.0 # Code linter -``` - -**Install All Dependencies:** - -```bash -pip install -r requirements.txt -# New key modules included: pyotp (MFA), qrcode (Auth Setup) -``` - - -*** - -## Understanding Core Concepts - -### 1. Blockchain Fundamentals - -#### What is a Blockchain? - -A blockchain is a **distributed ledger** that maintains a growing list of records (blocks) linked using cryptography. Each block contains: - -``` - - BLOCK #123 - - Index: 123 - Timestamp: 2024-12-26T15:01:00Z - Data: {credential_id: CRED_001} - Previous Hash: abc123... - Hash: def456... - Nonce: 42857 - - - Cryptographically - Linked - - - BLOCK #124 - - Previous Hash: def456... (from #123) - ... - -``` - -**Key Properties:** - -- **Immutability:** Once written, data cannot be changed -- **Transparency:** All participants can verify the chain -- **Distributed:** No single point of failure -- **Secure:** Cryptographic hashing prevents tampering - - -#### How Our Blockchain Works - -**1. Genesis Block Creation:** - -```python -Genesis Block { - index: 0, - timestamp: "2024-01-01T00:00:00Z", - data: {"type": "genesis"}, - previous_hash: "0", - hash: "calculated_hash", - nonce: 0 -} -``` - -**2. Adding New Blocks:** - -```python -# When credential issued: -New Block { - index: current_index + 1, - timestamp: current_time, - data: { - "credential_id": "CRED_001", - "ipfs_cid": "Qm...", - "issuer": "University Name", - "action": "issue" - }, - previous_hash: last_block.hash, - hash: calculated_hash, - nonce: found_by_mining -} -``` - -**3. Proof-of-Work Mining:** - -```python -# Find nonce where hash starts with '0000...' -while not hash.startswith('0' * difficulty): - nonce += 1 - hash = SHA256(block_data + nonce) -``` - - -### 2. Cryptographic Signatures - -#### RSA-2048 Digital Signatures - -**How It Works:** - -``` - - CREDENTIAL ISSUANCE - - - - - 1. Create Credential Data - {student: "John", gpa: 8.5, ...} - - - - - 2. Hash the Data - SHA256(data) hash_value - - - - - 3. Sign with Private Key - signature = RSA_Sign(hash, private_key) - - - - - 4. Attach Signature to Credential - credential.signature = signature - - - - CREDENTIAL VERIFICATION - - - - - 1. Receive Credential + Signature - - - - - 2. Extract Public Key - public_key = get_issuer_public_key() - - - - - 3. Verify Signature - valid = RSA_Verify(data, signature, - public_key) - - - - Valid / Invalid -``` - -**Security Guarantees:** - -- **Authenticity:** Only holder of private key could create signature -- **Integrity:** Any data tampering invalidates signature -- **Non-repudiation:** Signer cannot deny signing - - -### 3. IPFS Storage - -#### What is IPFS? - -IPFS (InterPlanetary File System) is a **peer-to-peer distributed file system** that uses content-addressing. - -**Traditional Web (Location-based):** - -``` -URL: https://university.edu/transcript/john_doe.pdf - File location changes? Link breaks! -``` - -**IPFS (Content-based):** - -``` -CID: QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG - Content never changes, always accessible! -``` - -**How It Works:** - -``` - - 1. Store Credential on IPFS - credential IPFS.add() - - - - - 2. IPFS Calculates Content Hash - CID = SHA256(credential_data) - QmYwAPJzv5CZ... - - - - - 3. Store CID on Blockchain - blockchain.add({cid: "Qm..."}) - - - - - 4. Retrieve Credential - credential = IPFS.get(cid) - -``` - -**Benefits:** - -- **Deduplication:** Identical content = same CID -- **Distributed:** No single point of failure -- **Immutable:** Content hash verifies integrity -- **Permanent:** Content persists across network - - -### 4. W3C Verifiable Credentials - -#### Standard Structure - -```json -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": ["VerifiableCredential", "AcademicCredential"], - "issuer": { - "id": "did:example:university", - "name": "G. Pulla Reddy Engineering College" - }, - "issuanceDate": "2024-12-26T15:01:00Z", - "credentialSubject": { - "id": "did:example:student123", - "name": "John Doe", - "degree": "B.Tech Computer Science", - "gpa": 8.5, - "graduationYear": 2025 - }, - "proof": { - "type": "RsaSignature2018", - "created": "2024-12-26T15:01:00Z", - "proofPurpose": "assertionMethod", - "verificationMethod": "issuer_public_key", - "jws": "eyJhbGc...signature_here" - } -} -``` - - -### 5. Selective Disclosure \& Zero-Knowledge Proofs - -#### Selective Disclosure - -**Concept:** Share only required fields, hide everything else - -**Example Scenario:** - -``` -Full Credential: - Name: John Doe - Student ID: CST001 - DOB: 1999-05-15 - Degree: B.Tech CS - GPA: 8.5 - Marks: [85, 90, 88, ...] - Address: 123 Main St - -Selective Disclosure (Share only GPA): - GPA: 8.5 - All other fields hidden - -Verifier sees: -{ - "gpa": 8.5, - "proof": "cryptographic_proof_that_gpa_is_valid" -} -``` - - -#### Zero-Knowledge Proofs - -**Concept:** Prove a statement is true without revealing the data - -**Example:** - -``` -Statement: "My GPA is above 7.5" -Proof: Generate cryptographic proof -Result: Verifier confirms GPA > 7.5 - WITHOUT knowing actual GPA (8.5) -``` - -**Types Implemented:** - -1. **Range Proofs:** - -```python -Prove: 7.5 GPA 10.0 -Without revealing: actual GPA = 8.5 -``` - -2. **Membership Proofs:** - -```python -Prove: degree ["B.Tech", "M.Tech", "PhD"] -Without revealing: actual degree = "B.Tech" -``` - - -*** - -## Installation Guide - -### Step 1: System Preparation - -#### Windows - -```powershell -# Check Python version -python --version -# Should show Python 3.10.x or higher - -# Update pip -python -m pip install --upgrade pip - -# Install Git (if not installed) -# Download from: https://git-scm.com/download/win -``` - - -#### macOS - -```bash -# Install Homebrew (if not installed) -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - -# Install Python -brew install python@3.11 - -# Check version -python3 --version -``` - - -#### Linux (Ubuntu/Debian) - -```bash -# Update package list -sudo apt update - -# Install Python and pip -sudo apt install python3.11 python3-pip - -# Install development tools -sudo apt install python3-dev build-essential - -# Check version -python3 --version -``` - - -### Step 2: Clone Repository - -```bash -# Clone the project -git clone https://github.com/udaycodespace/credify.git -cd credify - -# Or download ZIP and extract -``` - - -### Step 3: Create Virtual Environment - -**Why use virtual environment?** - -- Isolates project dependencies -- Prevents conflicts with system Python -- Easy dependency management - -```bash -# Create virtual environment -python -m venv venv - -# Activate virtual environment - -# Windows (PowerShell) -venv\Scripts\Activate.ps1 - -# Windows (CMD) -venv\Scripts\activate.bat - -# macOS/Linux -source venv/bin/activate - -# Verify activation (prompt should show (venv)) -``` - - -### Step 4: Install Dependencies - -```bash -# Install production dependencies -pip install -r requirements.txt - -# Install development dependencies (optional) -pip install -r requirements-dev.txt - -# Verify installations -pip list -``` - - -### Step 5: Configure Environment - -```bash -# Create .env file -# Windows -copy .env.example .env - -# macOS/Linux -cp .env.example .env - -# Edit .env with your settings -``` - -**Example `.env` Configuration:** - -```bash -# Flask Configuration -FLASK_ENV=development -DEBUG=True - -# Security Keys (CHANGE THESE!) -SECRET_KEY=xyz -SESSION_SECRET=xyz - -# Database -DATABASE_URL=sqlite:///credentials.db - -# Server -HOST=0.0.0.0 -PORT=5000 - -# IPFS (Optional) -IPFS_ENABLED=False - -# Initial Admin Secrets (Optional - System will randomize if missing) -INITIAL_ADMIN_PASSWORD=your_secure_password -INITIAL_ISSUER_PASSWORD=your_secure_issuer_password -``` - - -### Step 6: Initialize Database - -```bash -# Initialize database schema -python -c "from app.models import init_database; from app.app import app; init_database(app)" - -# Verify database created -ls instance/ # Should show credentials.db - -# Or using Makefile -make init-db -``` - - -### Step 7: Create Admin User - -```bash -# Start the application -python main.py - -# ON FIRST BOOT: -# 1. Look at your terminal logs! -# 2. The system will print: " GENERATED SECURE ADMIN PASSWORD: [random_key]" -# 3. Use this key to login at http://localhost:5000/issuer -# 4. Follow the MFA setup prompt to link your phone. -``` - - -### Step 8: Start Application - -```bash -# Start Flask development server -python main.py - -# Or using Makefile -make run - -# Expected output: -# Application initialized successfully! -# Starting server... -# * Running on http://127.0.0.1:5000 -``` - - -### Step 9: Verify Installation - -**Open browser and test:** - -1. **Home Page:** http://localhost:5000 - - Should show landing page -2. **Login:** http://localhost:5000/login - - Login with admin credentials -3. **Issuer Dashboard:** http://localhost:5000/issuer - - Should show credential issuance form -4. **Verifier:** http://localhost:5000/verifier - - Should show verification interface - -**If all pages load successfully, installation is complete!** - -*** - -## System Architecture Deep Dive - -### Overall System Design - -``` - - USER INTERFACE LAYER - - Issuer Student Verifier - Dashboard Dashboard Portal - - - - - APPLICATION LAYER (Flask) - - - Route Handlers - Authentication Authorization - Session Mgmt Error Handling - - - - - BUSINESS LOGIC LAYER - - - Credential Manager - Issue Verify Revoke Disclose - - - - - Crypto Block- IPFS ZKP - Utils chain Client Manager - - - - - PERSISTENCE LAYER - - - SQLite IPFS Blockchain JSON Keys - DB Store Store PEM - - -``` - - -### Component Interaction Flow - -**Credential Issuance:** - -``` -User Flask Route Credential Manager - - Validate Data - - Generate W3C Credential - - - - Crypto Manager IPFS Client - (Sign credential) (Store data) - - - - Blockchain Engine - (Record hash) - - Update Registry Response -``` - - -### Data Flow Diagram - -``` - - CREDENTIAL DATA LIFECYCLE - - -[^1] CREATION - University inputs data - - Credential Manager creates W3C credential - - Crypto Manager signs with RSA-2048 - - [Credential + Signature] - -[^2] STORAGE - [Credential + Signature] - IPFS (full data) returns CID - Blockchain (hash + CID) - - Credential Registry (metadata) - -[^3] RETRIEVAL - Request with Credential ID - - Registry lookup get CID + blockchain hash - - IPFS retrieval get full credential - - Blockchain verification confirm integrity - -[^4] VERIFICATION - Full Credential - Verify signature (Crypto Manager) - Verify hash (Blockchain) - Check revocation status (Registry) - - [Valid / Invalid / Revoked] -``` - - -*** - -## Implementation Walkthrough - -### Part 1: Blockchain Implementation - -#### Understanding the Block Structure - -```python -# core/blockchain.py - -class Block: - """ - Represents a single block in the blockchain. - Each block contains: - - index: Position in chain - - timestamp: When block was created - - data: Credential metadata - - previous_hash: Link to previous block - - hash: This block's unique identifier - - nonce: Proof-of-work solution - """ - - def __init__(self, index, timestamp, data, previous_hash): - self.index = index - self.timestamp = timestamp - self.data = data - self.previous_hash = previous_hash - self.nonce = 0 - self.hash = self.calculate_hash() - - def calculate_hash(self): - """ - Creates SHA-256 hash of block data. - Hash = SHA256(index + timestamp + data + prev_hash + nonce) - """ - block_string = f"{self.index}{self.timestamp}{json.dumps(self.data)}{self.previous_hash}{self.nonce}" - return hashlib.sha256(block_string.encode()).hexdigest() - - def mine_block(self, difficulty): - """ - Proof-of-Work: Find nonce where hash starts with - 'difficulty' number of zeros. - Example: difficulty=4 hash must start with "0000" - """ - target = '0' * difficulty - while self.hash[:difficulty] != target: - self.nonce += 1 - self.hash = self.calculate_hash() - - print(f" Block mined: {self.hash}") -``` - - -#### Creating the Blockchain - -```python -class SimpleBlockchain: - """ - Manages the blockchain: - - Creates genesis block - - Adds new blocks - - Validates chain integrity - """ - - def __init__(self, difficulty=4): - self.chain = [] - self.difficulty = difficulty - self.create_genesis_block() - - def create_genesis_block(self): - """ - First block in chain - hardcoded initial state - """ - genesis = Block(0, datetime.now().isoformat(), - {"type": "genesis"}, "0") - self.chain.append(genesis) - - def add_block(self, data): - """ - Adds new block with credential data: - 1. Get previous block - 2. Create new block - 3. Mine block (proof-of-work) - 4. Append to chain - 5. Save to file - """ - previous_block = self.get_latest_block() - new_block = Block( - len(self.chain), - datetime.now().isoformat(), - data, - previous_block.hash - ) - new_block.mine_block(self.difficulty) - self.chain.append(new_block) - self.save_chain() - return new_block - - def is_chain_valid(self): - """ - Validates entire chain: - - Check each block's hash is correct - - Check links between blocks are valid - - Detect any tampering - """ - for i in range(1, len(self.chain)): - current = self.chain[i] - previous = self.chain[i-1] - - # Verify block hash - if current.hash != current.calculate_hash(): - return False - - # Verify link to previous block - if current.previous_hash != previous.hash: - return False - - return True -``` - - -### Part 2: Cryptographic Implementation - -#### RSA Key Generation - -```python -# core/crypto_utils.py - -from cryptography.hazmat.primitives.asymmetric import rsa, padding -from cryptography.hazmat.primitives import hashes, serialization - -class CryptoManager: - """ - Handles all cryptographic operations: - - RSA key generation - - Digital signatures - - Signature verification - - Data hashing - """ - - def __init__(self): - self.private_key = None - self.public_key = None - self.load_or_generate_keys() - - def generate_keys(self): - """ - Generates RSA-2048 key pair: - - Private key: For signing credentials - - Public key: For verification (distributed publicly) - """ - self.private_key = rsa.generate_private_key( - public_exponent=65537, - key_size=2048 - ) - self.public_key = self.private_key.public_key() - - # Save keys to PEM files - self.save_keys() - - def sign_data(self, data): - """ - Creates digital signature: - 1. Hash the data (SHA-256) - 2. Encrypt hash with private key - 3. Return signature (base64 encoded) - - This proves: - - Data came from holder of private key - - Data hasn't been tampered with - """ - if isinstance(data, dict): - data = json.dumps(data, sort_keys=True) - - signature = self.private_key.sign( - data.encode('utf-8'), - padding.PSS( - mgf=padding.MGF1(hashes.SHA256()), - salt_length=padding.PSS.MAX_LENGTH - ), - hashes.SHA256() - ) - - return base64.b64encode(signature).decode('utf-8') - - def verify_signature(self, data, signature): - """ - Verifies digital signature: - 1. Decode signature from base64 - 2. Decrypt with public key - 3. Compare with hash of data - - Returns: True if valid, False if tampered - """ - try: - if isinstance(data, dict): - data = json.dumps(data, sort_keys=True) - - signature_bytes = base64.b64decode(signature) - - self.public_key.verify( - signature_bytes, - data.encode('utf-8'), - padding.PSS( - mgf=padding.MGF1(hashes.SHA256()), - salt_length=padding.PSS.MAX_LENGTH - ), - hashes.SHA256() - ) - return True - except Exception: - return False - - def hash_data(self, data): - """ - Creates SHA-256 hash: - - Deterministic (same input = same output) - - One-way (cannot reverse) - - Collision-resistant - - Used for: Blockchain integrity, data verification - """ - if isinstance(data, dict): - data = json.dumps(data, sort_keys=True) - - return hashlib.sha256(data.encode()).hexdigest() -``` - - -### Part 3: IPFS Integration - -```python -# core/ipfs_client.py - -class IPFSClient: - """ - Manages IPFS storage with fallback: - 1. Try local IPFS node - 2. Try Infura gateway - 3. Fall back to local JSON storage - """ - - def __init__(self): - self.endpoints = [ - 'http://127.0.0.1:5001', # Local IPFS node - 'https://ipfs.infura.io:5001' # Infura gateway - ] - self.local_storage = 'data/ipfs_storage.json' - self.active_endpoint = None - self._test_connection() - - def add_json(self, data): - """ - Stores JSON data on IPFS: - 1. Convert to JSON string - 2. Upload to IPFS - 3. Return Content ID (CID) - - CID = SHA256(data) content-addressed storage - """ - for endpoint in self.endpoints: - try: - response = requests.post( - f'{endpoint}/api/v0/add', - files={'file': json.dumps(data)} - ) - if response.status_code == 200: - cid = response.json()['Hash'] - logging.info(f" Stored on IPFS: {cid}") - return cid - except Exception as e: - logging.warning(f"IPFS endpoint {endpoint} failed: {e}") - - # Fallback to local storage - return self._store_locally(data) - - def get_json(self, cid): - """ - Retrieves data from IPFS: - 1. Request data by CID - 2. Parse JSON response - 3. Return data - - If IPFS unavailable, retrieve from local storage - """ - for endpoint in self.endpoints: - try: - response = requests.post( - f'{endpoint}/api/v0/cat', - params={'arg': cid} - ) - if response.status_code == 200: - return response.json() - except Exception: - continue - - # Fallback to local storage - return self._retrieve_locally(cid) - - def _store_locally(self, data): - """ - Local storage fallback: - - Generates pseudo-CID (hash of data) - - Stores in JSON file - - Returns CID for consistency - """ - cid = f"LOCAL_{hashlib.sha256(json.dumps(data).encode()).hexdigest()[:32]}" - - storage = self._load_local_storage() - storage[cid] = data - self._save_local_storage(storage) - - logging.info(f" Stored locally: {cid}") - return cid -``` - - -### Part 4: Credential Manager - -```python -# core/credential_manager.py - -class CredentialManager: - """ - Manages complete credential lifecycle: - - Issuance (create + sign + store) - - Verification (retrieve + validate) - - Revocation (mark invalid) - - Selective disclosure (privacy-preserving sharing) - """ - - def __init__(self, blockchain, crypto_manager, ipfs_client): - self.blockchain = blockchain - self.crypto = crypto_manager - self.ipfs = ipfs_client - self.registry = self._load_registry() - - def issue_credential(self, data): - """ - Complete issuance flow: - - 1. Validate input data - 2. Generate unique credential ID - 3. Create W3C compliant credential - 4. Sign with RSA-2048 - 5. Store on IPFS - 6. Record hash on blockchain - 7. Update credential registry - 8. Return credential ID - """ - # Step 1: Validate - required_fields = ['student_name', 'student_id', 'degree', - 'university', 'gpa', 'graduation_year'] - for field in required_fields: - if field not in data: - return {'success': False, 'error': f'Missing field: {field}'} - - # Step 2: Generate ID - credential_id = f"CRED_{uuid.uuid4().hex[:16]}" - - # Step 3: Create W3C credential - credential = { - "@context": ["https://www.w3.org/2018/credentials/v1"], - "type": ["VerifiableCredential", "AcademicCredential"], - "id": credential_id, - "issuer": { - "id": f"did:example:{data['university'].lower().replace(' ', '_')}", - "name": data['university'] - }, - "issuanceDate": datetime.now().isoformat() + 'Z', - "credentialSubject": { - "id": f"did:example:{data['student_id']}", - "studentName": data['student_name'], - "studentId": data['student_id'], - "degree": data['degree'], - "gpa": data['gpa'], - "graduationYear": data['graduation_year'] - } - } - - # Step 4: Sign credential - signature = self.crypto.sign_data(credential) - credential['proof'] = { - "type": "RsaSignature2018", - "created": datetime.now().isoformat() + 'Z', - "proofPurpose": "assertionMethod", - "jws": signature - } - - # Step 5: Store on IPFS - ipfs_cid = self.ipfs.add_json(credential) - - # Step 6: Record on blockchain - blockchain_data = { - "credential_id": credential_id, - "ipfs_cid": ipfs_cid, - "credential_hash": self.crypto.hash_data(credential), - "issuer": data['university'], - "action": "issue", - "timestamp": datetime.now().isoformat() - } - block = self.blockchain.add_block(blockchain_data) - - # Step 7: Update registry - self.registry[credential_id] = { - "credential_id": credential_id, - "student_id": data['student_id'], - "ipfs_cid": ipfs_cid, - "blockchain_hash": block.hash, - "issue_date": datetime.now().isoformat(), - "issuer": data['university'], - "status": "active", - "version": 1 - } - self._save_registry() - - # Step 8: Return success - logging.info(f" Issued credential: {credential_id}") - return { - 'success': True, - 'credential_id': credential_id, - 'ipfs_cid': ipfs_cid, - 'blockchain_hash': block.hash - } - - def verify_credential(self, credential_id): - """ - Multi-layer verification: - - 1. Check registry (exists + not revoked) - 2. Retrieve from IPFS - 3. Verify cryptographic signature - 4. Verify blockchain integrity - 5. Return comprehensive result - """ - # Step 1: Registry check - if credential_id not in self.registry: - return {'valid': False, 'error': 'Credential not found'} - - registry_entry = self.registry[credential_id] - - if registry_entry['status'] == 'revoked': - return { - 'valid': False, - 'error': 'Credential has been revoked', - 'revocation_date': registry_entry.get('revoked_date') - } - - # Step 2: Retrieve from IPFS - credential = self.ipfs.get_json(registry_entry['ipfs_cid']) - if not credential: - return {'valid': False, 'error': 'Could not retrieve credential'} - - # Step 3: Verify signature - signature = credential['proof']['jws'] - credential_copy = credential.copy() - del credential_copy['proof'] - - is_signature_valid = self.crypto.verify_signature( - credential_copy, - signature - ) - - if not is_signature_valid: - return {'valid': False, 'error': 'Invalid signature'} - - # Step 4: Verify blockchain - expected_hash = self.crypto.hash_data(credential_copy) - blockchain_valid = self.blockchain.is_chain_valid() - - # Step 5: Return result - return { - 'valid': True, - 'credential': credential, - 'issuer': registry_entry['issuer'], - 'issue_date': registry_entry['issue_date'], - 'blockchain_valid': blockchain_valid, - 'signature_valid': is_signature_valid, - 'status': registry_entry['status'] - } - - def selective_disclosure(self, credential_id, fields_to_disclose): - """ - Privacy-preserving credential sharing: - - 1. Retrieve full credential - 2. Extract only requested fields - 3. Create cryptographic proof - 4. Return minimal disclosure - - Example: - Full: {name, id, dob, gpa, marks, address} - Disclose: [gpa] - Result: {gpa: 8.5, proof: "..."} - """ - # Retrieve full credential - verification = self.verify_credential(credential_id) - if not verification['valid']: - return {'success': False, 'error': verification['error']} - - credential = verification['credential'] - subject = credential['credentialSubject'] - - # Extract requested fields only - disclosed_data = {} - for field in fields_to_disclose: - if field in subject: - disclosed_data[field] = subject[field] - - # Create proof - proof = { - "credential_id": credential_id, - "disclosed_fields": disclosed_data, - "hidden_field_count": len(subject) - len(disclosed_data), - "issuer": credential['issuer']['name'], - "issuance_date": credential['issuanceDate'], - "proof_timestamp": datetime.now().isoformat() + 'Z', - "proof_hash": self.crypto.hash_data(disclosed_data) - } - - logging.info(f" Created selective disclosure for {credential_id}") - return {'success': True, 'proof': proof} -``` - - -*** - -## Usage Scenarios - -### Scenario 1: University Issues Credential - -**Actors:** University Administrator (Issuer) - -**Steps:** - -1. **Login:** - -``` -URL: http://localhost:5000/login -Username: admin -Password: [admin_password] -``` - -2. **Navigate to Issuer Dashboard:** - -``` -URL: http://localhost:5000/issuer -``` - -3. **Fill Credential Form:** - -``` -Student Name: Alice Johnson -Student ID: CST2024001 -Degree: B.Tech Computer Science and Engineering -University: G. Pulla Reddy Engineering College -GPA: 9.2 -Graduation Year: 2024 -Courses: Data Structures, Algorithms, DBMS, Computer Networks -``` - -4. **Submit \& Receive Confirmation:** - -```json -{ - "success": true, - "credential_id": "CRED_a1b2c3d4e5f6g7h8", - "ipfs_cid": "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG", - "blockchain_hash": "000012a3b4c5d6e7f8g9h0i1j2k3l4m5n6o7p8q9r0s1t2" -} -``` - -5. **System Actions (Behind the Scenes):** - - Credential created with W3C format - - Signed with RSA-2048 private key - - Stored on IPFS (full data) - - Hash recorded on blockchain (block mined) - - Registry updated with metadata - -*** - -### Scenario 2: Student Views Credential - -**Actors:** Student (Holder) - -**Steps:** - -1. **Login:** - -``` -Username: CST2024001 -Password: [student_password] -``` - -2. **View Dashboard:** - -``` -URL: http://localhost:5000/holder -``` - -3. **See Credentials:** - -``` - - My Credentials - - B.Tech Computer Science - G. Pulla Reddy Engineering College - GPA: 9.2 | Year: 2024 - - [View Details] [Share] [Download PDF] - -``` - -4. **View Full Details:** - -```json -{ - "student_name": "Alice Johnson", - "student_id": "CST2024001", - "degree": "B.Tech Computer Science", - "gpa": 9.2, - "graduation_year": 2024, - "courses": ["DS", "Algo", "DBMS", "Networks"], - "issue_date": "2024-12-26T15:01:00Z", - "issuer": "G. Pulla Reddy Engineering College", - "status": " Active" -} -``` - - -*** - -### Scenario 3: Student Creates Selective Disclosure - -**Actors:** Student (Holder), Employer (Verifier) - -**Steps:** - -1. **Student Selects Fields:** - -``` -Share with: TechCorp Inc. - -Select fields to disclose: - Student Name - Degree - GPA - Student ID (hidden) - Courses (hidden) - Date of Birth (hidden) -``` - -2. **Generate Proof:** - -```javascript -// System creates minimal disclosure -{ - "credential_id": "CRED_a1b2c3d4e5f6g7h8", - "disclosed_fields": { - "student_name": "Alice Johnson", - "degree": "B.Tech Computer Science", - "gpa": 9.2 - }, - "hidden_field_count": 3, - "issuer": "G. Pulla Reddy Engineering College", - "proof_hash": "abc123def456...", - "proof_timestamp": "2024-12-26T15:30:00Z" -} -``` - -3. **Student Shares Proof:** - - Copy JSON proof - - Send to employer via email/portal -4. **Employer Verifies:** - -``` -URL: http://localhost:5000/verifier -Paste proof JSON -Click "Verify" -``` - -5. **Verification Result:** - -``` - CREDENTIAL VALID - -Student: Alice Johnson -Degree: B.Tech Computer Science -GPA: 9.2 -Issuer: G. Pulla Reddy Engineering College - - Additional fields hidden by student - Cryptographic signature valid - Blockchain integrity confirmed - Not revoked -``` - - -*** - -### Scenario 4: Employer Verifies Full Credential - -**Actors:** Employer (Verifier) - -**Steps:** - -1. **Receive Credential ID:** - -``` -Student provides: CRED_a1b2c3d4e5f6g7h8 -``` - -2. **Access Verifier Portal:** - -``` -URL: http://localhost:5000/verifier -(No login required - public access) -``` - -3. **Submit for Verification:** - -``` -Enter Credential ID: CRED_a1b2c3d4e5f6g7h8 -Click: "Verify Credential" -``` - -4. **System Performs Checks:** - -``` -[1/5] Checking registry... -[2/5] Retrieving from IPFS... -[3/5] Verifying signature... -[4/5] Checking blockchain... -[5/5] Revocation check... -``` - -5. **View Complete Results:** - -``` - - VERIFICATION SUCCESSFUL - - Student: Alice Johnson - ID: CST2024001 - Degree: B.Tech Computer Science - University: G.P.R. Engineering College - GPA: 9.2 / 10.0 - Graduation: 2024 - - Issued: 2024-12-26 - Status: Active - - Cryptographic Signature: Valid - Blockchain Integrity: Confirmed - IPFS Storage: Accessible - Not Revoked - -``` - - -*** - -### Scenario 5: University Revokes Credential - -**Actors:** University Administrator (Issuer) - -**When to Revoke:** - -- Student violated academic integrity -- Credential issued in error -- Data correction needed (issue new version instead) - -**Steps:** - -1. **Login as Issuer** -2. **Navigate to Credential Management:** - -``` -View issued credentials -Search for: CST2024001 -``` - -3. **Select Credential:** - -``` -Credential: CRED_a1b2c3d4e5f6g7h8 -Status: Active -[View] [Revoke] -``` - -4. **Revoke with Reason:** - -``` -Reason: Academic misconduct detected -Category: Policy violation -Additional notes: Disciplinary action taken - -[Confirm Revocation] -``` - -5. **System Actions:** - -``` -- Registry status: Active Revoked -- Blockchain record: Revocation transaction added -- Revocation date: 2024-12-26T16:00:00Z -- Future verifications: Will show "Revoked" -``` - -6. **Future Verification Attempts:** - -``` - CREDENTIAL REVOKED - -This credential has been revoked by the issuer. - -Revocation Date: 2024-12-26 -Reason: Policy violation - -This credential is no longer valid for verification. -``` - - -*** - -## Security Analysis - -### Threat Model - -#### Threat 1: Credential Forgery - -**Attack:** Malicious actor creates fake credential - -**Defenses:** - -1. **RSA-2048 Signatures:** - - Only issuer has private key - - Signature verification fails for forgeries -2. **Blockchain Integrity:** - - All credentials recorded on blockchain - - Fake credentials won't have blockchain entry -3. **IPFS Content Addressing:** - - CID is hash of content - - Modified content = different CID - -**Result:** Forgery detected immediately - -#### Threat 2: Data Tampering - -**Attack:** Attacker modifies credential data (e.g., change GPA) - -**Defenses:** - -1. **Cryptographic Hash:** - - Any change invalidates hash - - Blockchain stores original hash -2. **Digital Signature:** - - Signature verification fails if data modified - - RSA ensures authenticity -3. **Immutable Blockchain:** - - Original record preserved - - Tampering is detectable - -**Result:** Tampering detected during verification - -#### Threat 3: Replay Attacks - -**Attack:** Reuse old credential for current purpose - -**Defenses:** - -1. **Timestamps:** - - Issuance date recorded - - Verifier can check validity period -2. **Revocation System:** - - Old/compromised credentials can be revoked - - Verification checks revocation status -3. **Credential Versioning:** - - Multiple versions tracked - - Latest version identifiable - -**Result:** Replay attacks mitigated - -#### Threat 4: Privacy Violations - -**Attack:** Unnecessarily expose full transcript - -**Defenses:** - -1. **Selective Disclosure:** - - Student controls what to share - - Only requested fields disclosed -2. **Zero-Knowledge Proofs:** - - Prove statements without data reveal - - Example: Prove GPA > 7.5 without showing 8.5 -3. **Access Control:** - - Students see only their credentials - - Role-based permissions - -**Result:** Privacy preserved - -#### Threat 5: Man-in-the-Middle - -**Attack:** Intercept credential during transmission - -**Defenses:** - -1. **HTTPS (Production):** - - Encrypted transport layer - - TLS certificates -2. **Digital Signatures:** - - Even if intercepted, can't be modified - - Signature verification protects integrity -3. **Content-Addressed Storage:** - - IPFS CID verifies data integrity - - Modification detected - -**Result:** MITM attacks prevented - -### Security Best Practices - -#### For Development: - -```python -# GOOD -SECRET_KEY = os.environ.get('SECRET_KEY') -DATABASE_URL = os.environ.get('DATABASE_URL') - -# BAD -SECRET_KEY = "hardcoded-secret-key" -DATABASE_URL = "sqlite:///prod.db" -``` - - -#### For Production: - -```python -# 1. Use environment variables -# 2. Enable HTTPS -# 3. Set secure session cookies -# 4. Implement rate limiting -# 5. Enable CORS properly -# 6. Use strong passwords -# 7. Regular security audits -``` - - -*** - -## Troubleshooting - -### Quick Fixes - -**Problem:** Server won't start - -```bash -# Check if port 5000 is in use -netstat -ano | findstr :5000 # Windows -lsof -ti:5000 # Mac/Linux - -# Kill process or use different port -export PORT=5001 -python main.py -``` - -**Problem:** Database errors - -```bash -# Reinitialize database -rm instance/credentials.db -python -c "from app.models import init_database; from app.app import app; init_database(app)" -``` - -**Problem:** Verification fails - -```bash -# Check all components -python << 'EOF' -from core.blockchain import SimpleBlockchain -from core.crypto_utils import CryptoManager -from core.ipfs_client import IPFSClient - -# Test blockchain -bc = SimpleBlockchain() -print(f"Blockchain valid: {bc.is_chain_valid()}") - -# Test crypto -crypto = CryptoManager() -test = crypto.sign_data("test") -print(f"Signature works: {crypto.verify_signature('test', test)}") - -# Test IPFS -ipfs = IPFSClient() -print(f"IPFS connected: {ipfs.is_connected()}") -EOF -``` - -For detailed troubleshooting, see `TROUBLESHOOTING.md`. - -*** - -## Advanced Topics - -### Topic 1: Scaling the System - -**Current:** Single-server SQLite - -**Enterprise Scale:** - -``` - - Load Balancer (Nginx) - - - - Flask Flask (Multiple instances) - Server 1 Server 2 - - - - PostgreSQL Cluster - (Master + Replicas) - -``` - - -### Topic 2: Implementing DIDs - -**Decentralized Identifiers:** - -```json -{ - "@context": "https://www.w3.org/ns/did/v1", - "id": "did:example:university123", - "authentication": [{ - "id": "did:example:university123#keys-1", - "type": "RsaVerificationKey2018", - "controller": "did:example:university123", - "publicKeyPem": "-----BEGIN PUBLIC KEY-----..." - }] -} -``` - - -### Topic 3: Smart Contract Integration - -**Ethereum/Polygon Integration:** - -```solidity -contract CredentialRegistry { - mapping(bytes32 => Credential) public credentials; - - struct Credential { - string ipfsCID; - address issuer; - uint256 timestamp; - bool revoked; - } - - function issue(bytes32 credID, string memory cid) public { - credentials[credID] = Credential(cid, msg.sender, block.timestamp, false); - } - - function verify(bytes32 credID) public view returns (bool) { - return !credentials[credID].revoked; - } -} -``` - - -*** - -## Best Practices - -### 1. Code Organization - -- Keep concerns separated (MVC pattern) -- Use meaningful variable names -- Comment complex logic -- Follow PEP 8 style guide - - -### 2. Security - -- Never commit secrets to Git -- Use environment variables -- Implement rate limiting -- Enable HTTPS in production -- Regular dependency updates - - -### 3. Testing - -- Write unit tests for all components -- Integration tests for workflows -- Test edge cases -- Maintain test coverage > 80% - - -### 4. Documentation - -- Keep README updated -- Document API endpoints -- Inline code comments -- User guides for each role - - -### 5. Performance - -- Cache frequently accessed data -- Optimize database queries -- Use async for IPFS operations -- Monitor system metrics - -*** - -## Conclusion - -### What You've Learned - - **Blockchain Technology** - -- Block structure and hashing -- Proof-of-work consensus -- Chain validation and integrity - - **Cryptography** - -- RSA-2048 digital signatures -- SHA-256 hashing -- Key management - - **Distributed Storage** - -- IPFS content addressing -- Decentralized data storage -- Fallback strategies - - **Web Development** - -- Flask application architecture -- Role-based access control -- RESTful API design - - **Real-World Application** - -- Academic credential verification -- Privacy-preserving disclosure -- Production deployment - - -### Next Steps - -1. **Extend the System:** - - Add mobile app - - Implement QR codes - - Multi-language support -2. **Integrate with Enterprise:** - - Connect to university systems - - Employer verification portals - - Government credential registries -3. **Research Advanced Topics:** - - Zero-knowledge proofs (zk-SNARKs) - - Decentralized identifiers (DIDs) - - Blockchain interoperability - -### Resources - -- **W3C Verifiable Credentials:** https://www.w3.org/TR/vc-data-model/ -- **IPFS Documentation:** https://docs.ipfs.tech/ -- **Flask Documentation:** https://flask.palletsprojects.com/ -- **Cryptography Library:** https://cryptography.io/ - - -### Support - -**Development Team:** - -- [@udaycodespace](https://github.com/udaycodespace) Backend \& Blockchain -- [@shashikiran47](https://github.com/shashikiran47) Frontend \& IPFS -- [@tejavarshith](https://github.com/tejavarshith) Testing \& Documentation - -**Community:** - -- GitHub Issues: Report bugs -- GitHub Discussions: Ask questions -- Pull Requests: Contribute code - -*** - -
- -**Congratulations on completing the tutorial!** - -**G. Pulla Reddy Engineering College (Autonomous)** - -**Version 2.1 | March 2026** - -*** - -*From Academic Project to Production System* - -
- -*** - -> [!NOTE] -> ** TUTORIAL STATUS: UPDATED** -> -> **Architecture Version:** 2.1.0 (Elite Milestone) -> -> **Current Edited Date:** `2026-03-08` - - diff --git a/pyproject.toml b/pyproject.toml index f427e2b..ea58778 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "credify" -version = "2.1.0" +version = "2.0.0" description = "Elite Private Blockchain Verifiable Credential System with ZKP & IPFS" authors = ["Somapuram Uday", "Shashi Kiran", "Teja Varshith"] readme = "README.md" diff --git a/tests/test_blockchain.py b/tests/test_blockchain.py index 13a4b8e..112e05f 100644 --- a/tests/test_blockchain.py +++ b/tests/test_blockchain.py @@ -86,3 +86,77 @@ def test_tamper_detection(blockchain): blockchain.chain[1].data = {'data': 'TAMPERED_DATA'} assert blockchain.is_chain_valid() is False + + +def test_deterministic_leader_formula(blockchain): + """Leader selection uses height % total_nodes over deterministic ring.""" + blockchain.node_address = "http://node1:5000" + blockchain.node_id = "node1" + blockchain.nodes = {"node2:5000", "node3:5000"} + + # Height = current chain length. After genesis, length is 1. + leader_meta = blockchain.get_deterministic_leader(len(blockchain.chain)) + ring = leader_meta["ring"] + expected_index = len(blockchain.chain) % len(ring) + + assert leader_meta["leader_index"] == expected_index + assert leader_meta["leader"] == ring[expected_index] + + +def test_non_leader_block_creation_rejected(blockchain): + """Only deterministic leader can create local blocks.""" + blockchain.node_address = "http://node1:5000" + blockchain.node_id = "node1" + blockchain.nodes = {"node2:5000", "node3:5000"} + + # With ring [node1,node2,node3] and height=1, leader is node2. + with pytest.raises(PermissionError, match="Deterministic leader gate rejected"): + blockchain.add_block({'credential_id': 'LEADER-GATE-TEST'}, signed_by="admin") + + +def test_block_contains_proposed_by(blockchain): + """New blocks should carry proposed_by from current node id.""" + blockchain.node_id = "node-alpha" + blockchain.node_address = "" + blockchain.nodes = set() + blockchain.set_node_validators({"node-alpha", "standalone"}) + + block = blockchain.add_block({'check': 'proposer-field'}, signed_by="admin") + as_dict = block.to_dict() + + assert as_dict.get('proposed_by') == 'node-alpha' + + +def test_new_block_is_finalized(blockchain): + """Accepted local blocks must carry FINALIZED status.""" + blockchain.node_id = "standalone" + blockchain.node_address = "" + blockchain.nodes = set() + blockchain.set_node_validators({"standalone"}) + + block = blockchain.add_block({'finality': 'local'}, signed_by="admin") + assert block.to_dict().get('status') == 'FINALIZED' + + +def test_hash_input_determinism_for_dict_key_order(blockchain): + """Canonicalization should normalize dict key order before hashing.""" + from core.blockchain import Block + + payload_a = {'b': 2, 'a': 1, 'nested': {'z': 9, 'm': 5}} + payload_b = {'nested': {'m': 5, 'z': 9}, 'a': 1, 'b': 2} + + canonical_a = blockchain._canonicalize_data(payload_a) + canonical_b = blockchain._canonicalize_data(payload_b) + + block_a = Block(7, canonical_a, 'prev_hash_value', signed_by='admin', proposed_by='node1') + block_b = Block(7, canonical_b, 'prev_hash_value', signed_by='admin', proposed_by='node1') + + # Align non-deterministic runtime fields for a true same-input comparison. + block_a.timestamp = '2026-03-25T10:00:00' + block_b.timestamp = '2026-03-25T10:00:00' + block_a.nonce = 0 + block_b.nonce = 0 + block_a.merkle_root = block_a.calculate_merkle_root() + block_b.merkle_root = block_b.calculate_merkle_root() + + assert block_a.calculate_hash() == block_b.calculate_hash() diff --git a/tests/test_peer_sync.py b/tests/test_peer_sync.py index 1fb4dab..54dfd92 100644 --- a/tests/test_peer_sync.py +++ b/tests/test_peer_sync.py @@ -90,3 +90,64 @@ def test_receive_block_valid_workflow(client, crypto_manager): assert response.status_code == 200 assert json.loads(response.data)['success'] is True assert len(app_blockchain.chain) == index + 1 + assert app_blockchain.chain[-1].to_dict().get('status') == 'FINALIZED' + + +def test_receive_block_duplicate_ignored(client, crypto_manager): + """Duplicate peer blocks should be ignored idempotently.""" + from app.app import blockchain as app_blockchain + from core.blockchain import Block + + index = len(app_blockchain.chain) + prev_hash = app_blockchain.get_latest_block().hash + duplicate_candidate = Block(index, {"idempotent": True}, prev_hash, signed_by="admin") + duplicate_candidate.mine_block(0) + duplicate_candidate.signature = crypto_manager.sign_data(duplicate_candidate.hash) + + first = client.post( + '/api/node/receive_block', + data=json.dumps(duplicate_candidate.to_dict()), + content_type='application/json' + ) + assert first.status_code == 200 + assert len(app_blockchain.chain) == index + 1 + + second = client.post( + '/api/node/receive_block', + data=json.dumps(duplicate_candidate.to_dict()), + content_type='application/json' + ) + assert second.status_code == 200 + assert json.loads(second.data)['message'] in ['Duplicate block ignored', 'Outdated block ignored'] + assert len(app_blockchain.chain) == index + 1 + + +def test_broadcast_block_skips_sender_and_self(blockchain, monkeypatch): + """Gossip relay should not post back to sender or self node address.""" + sent_urls = [] + + class DummyResponse: + status_code = 200 + + def fake_post(url, json=None, headers=None, timeout=0): + sent_urls.append(url) + return DummyResponse() + + import requests + + monkeypatch.setattr(requests, "post", fake_post) + + blockchain.nodes = set() + blockchain.node_address = "http://node1:5000" + blockchain.node_id = "node1" + + block = blockchain.add_block({"relay": "check"}, signed_by="admin") + sent_urls.clear() + + blockchain.nodes = {"node1:5000", "node2:5000", "node3:5000"} + + blockchain.broadcast_block(block, source_node="http://node2:5000", origin_node="nodeX") + + assert "http://node2:5000/api/node/receive_block" not in sent_urls + assert "http://node1:5000/api/node/receive_block" not in sent_urls + assert "http://node3:5000/api/node/receive_block" in sent_urls