Skip to content

memo-13-byte/Secure-Flask-Auth-Portal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ” Secure Flask Authentication Portal with Hash Chain-Based OTP

Python Flask Security RSA License

Flask web authentication portal with two-factor authentication using 100-iteration SHA-256 hash chain-based OTP and RSA-encrypted database storage

Features β€’ Installation β€’ Usage β€’ Security β€’ Documentation


πŸ“‹ Table of Contents


🎯 Overview

This project implements a modern web authentication system with two-factor authentication (2FA) using a unique hash chain-based One-Time Password (OTP) mechanism. It combines traditional password authentication with cryptographic OTP verification for enhanced security.

What is Hash Chain-Based OTP?

Unlike traditional TOTP (Time-based OTP) or HOTP (HMAC-based OTP), this system uses a hash chain approach:

Password β†’ SHA-256 β†’ SHA-256 β†’ ... (100 times) β†’ OTP Chain
Sβ‚€ β†’ S₁ β†’ Sβ‚‚ β†’ ... β†’ S₉₉ β†’ S₁₀₀

Usage: S₁₀₀, S₉₉, Sβ‚‰β‚ˆ, ... (reverse order)
Verification: SHA-256(Sₙ₋₁) = Sβ‚™

Advantages:

  • βœ… Offline Capable - No time synchronization needed
  • βœ… Replay Attack Resistant - Each OTP used exactly once
  • βœ… Lightweight - No additional hardware/apps required
  • βœ… Cryptographically Secure - SHA-256 hash chain

✨ Features

πŸ”’ Authentication & Security

  • βœ… Two-Factor Authentication (2FA) - Password + OTP verification
  • βœ… Hash Chain-Based OTP - 100-iteration SHA-256 chain
  • βœ… RSA Encrypted Database - PKCS1_OAEP encryption for data at rest
  • βœ… SHA-256 Password Hashing - Secure credential storage
  • βœ… Automatic OTP Chain Renewal - Seamless chain regeneration
  • βœ… Session Management - Flask secure sessions

πŸ’» Web Application

  • βœ… Flask Framework - Modern Python web framework
  • βœ… Responsive UI - HTML/CSS templates
  • βœ… User Registration - Secure account creation
  • βœ… User Login - Multi-step authentication
  • βœ… Welcome Page - Post-authentication dashboard
  • βœ… Input Validation - Username/password requirements
  • βœ… Flash Messages - User feedback and error handling

πŸ›‘οΈ Security Features

  • βœ… Encrypted Storage - RSA encryption for database
  • βœ… OTP Counter Tracking - Prevents OTP reuse
  • βœ… Chain Exhaustion Handling - Automatic renewal at 100 logins
  • βœ… Server-Side Validation - All security logic on backend
  • βœ… Password Complexity Requirements - Minimum 6 characters
  • βœ… Username Restrictions - Alphanumeric only

πŸ” Security Architecture

System Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           Flask Authentication Portal Architecture          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CLIENT (Flask Frontend)                    SERVER (Backend Logic)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Registration Form  β”‚                   β”‚  User Database       β”‚
β”‚  - Username         │──────────────────▢│  (RSA Encrypted)     β”‚
β”‚  - Password         β”‚   Hash Password   β”‚  username;hash;OTP   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   Generate OTP    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                          β”‚
         β”‚                                          β”‚
         β–Ό                                          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Login Form         β”‚                   β”‚  Verification Logic  β”‚
β”‚  - Username         │──────────────────▢│  1. Check Password   β”‚
β”‚  - Password         β”‚   Send Hashed     β”‚  2. Verify OTP       β”‚
β”‚                     β”‚   Password + OTP  β”‚  3. Update Counter   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                          β”‚
         β”‚                    βœ“ Valid               β”‚
         β–Ό                                          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Welcome Page       │◀──────────────────│  Session Created     β”‚
β”‚  "Welcome, user!"   β”‚   Redirect        β”‚  Login Successful    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Authentication Flow

Registration Process

1. User Input:
   - Username (letters only)
   - Password (>6 chars)

2. Client-Side:
   - Validate username format: ^[A-Za-z]+$
   - Validate password length: >6
   - Hash password: SHA-256(password)
   - Generate OTP chain: hash_otp(password, 100)
   - Send: username, hashed_password, OTP[0] (S₁₀₀)

3. Server-Side:
   - Check username uniqueness
   - Encrypt database entry with RSA
   - Store: username;hash;S₁₀₀;0
   - Save encrypted to database.txt

4. Result:
   - Redirect to login page
   - Flash: "User registered successfully"

Login Process

1. User Input:
   - Username
   - Password

2. Client-Side (Password Verification):
   - Hash password: SHA-256(password)
   - Send: username, hashed_password

3. Server-Side (Password Check):
   - Decrypt database
   - Verify: username exists AND hash matches
   - Return: True/False

4. Client-Side (OTP Generation):
   - Generate OTP chain: hash_otp(password, 100)
   - Get current index: counter % 100
   - Send: OTP[counter] (Sₙ₋₁)

5. Server-Side (OTP Verification):
   - Load stored OTP: Sβ‚™
   - Hash received OTP: SHA-256(Sₙ₋₁)
   - Verify: SHA-256(Sₙ₋₁) == Sβ‚™
   - Update: store Sₙ₋₁, increment counter
   - Re-encrypt database

6. Result:
   - If valid: Redirect to /welcome
   - If invalid: Show error message

πŸš€ Installation

Prerequisites

Python 3.8 or higher
pip (Python package manager)

Clone Repository

git clone https://github.com/memo-13-byte/secure-flask-auth-portal.git
cd secure-flask-auth-portal

Install Dependencies

pip install Flask pycryptodome

Required Libraries:

  • Flask - Web framework
  • pycryptodome - Cryptographic operations

Generate RSA Keys

# generate_keys.py
from Crypto.PublicKey import RSA

# Generate 2048-bit RSA key pair
key = RSA.generate(2048)

# Save private key
with open('private.pem', 'wb') as f:
    f.write(key.export_key())

# Save public key
with open('public.pem', 'wb') as f:
    f.write(key.publickey().export_key())

print("Keys generated successfully!")
python generate_keys.py

πŸ’‘ Quick Start

1. Project Structure

Ensure your project has this structure:

secure-flask-auth-portal/
β”œβ”€β”€ Client.py              # Flask application (frontend)
β”œβ”€β”€ Server.py              # Backend logic
β”œβ”€β”€ templates/
β”‚   β”œβ”€β”€ register.html      # Registration form
β”‚   β”œβ”€β”€ login.html         # Login form
β”‚   └── welcome.html       # Welcome page
β”œβ”€β”€ public.pem             # RSA public key
β”œβ”€β”€ private.pem            # RSA private key
β”œβ”€β”€ database.txt           # Encrypted user database (auto-generated)
β”œβ”€β”€ requirements.txt       # Python dependencies
β”œβ”€β”€ .gitignore
β”œβ”€β”€ LICENSE
└── README.md

2. Run Application

python Client.py

3. Access Portal

Open your browser and navigate to:

http://localhost:5000

4. Register a User

  1. Click "Register" or go to http://localhost:5000/register
  2. Enter username (letters only): alice
  3. Enter password (>6 chars): mysecurepassword
  4. Click "Register"
  5. You'll be redirected to login page

5. Login

  1. Enter username: alice
  2. Enter password: mysecurepassword
  3. Click "Submit"
  4. OTP is automatically verified
  5. You'll see: "Welcome, alice!"

πŸ“š Technical Documentation

Hash Chain-Based OTP

Generation Process

def hash_otp(seed: str, n: int = 100) -> list:
    """
    Generate hash chain OTP
    
    Process:
    1. Start with password as seed
    2. Hash 100 times using SHA-256
    3. Return chain in reverse order
    
    Example:
    Sβ‚€ = "password"
    S₁ = SHA-256(Sβ‚€)
    Sβ‚‚ = SHA-256(S₁)
    ...
    S₁₀₀ = SHA-256(S₉₉)
    
    Return: [S₁₀₀, S₉₉, Sβ‚‰β‚ˆ, ..., S₁]
    """
    chain = []
    current_hash = bytes(seed, 'utf-8')
    
    for i in range(n):
        hash_obj = SHA256.new(current_hash)
        current_hash = hash_obj.digest()
        chain.append(current_hash.hex())
    
    return chain[::-1]  # Reverse for usage

Verification Process

Server stores: Sβ‚™
Client sends: Sₙ₋₁

Server verification:
1. Hash client OTP: SHA-256(Sₙ₋₁)
2. Compare: SHA-256(Sₙ₋₁) == Sβ‚™
3. If match:
   - Update stored OTP: Sβ‚™ ← Sₙ₋₁
   - Increment counter: counter += 1
   - Save encrypted database
4. Return: True/False

Chain Renewal

When counter reaches 100:
1. Client generates new chain
2. Reset counter to 0
3. Store new S₁₀₀
4. Continue authentication

Client Implementation

Client.py - Flask Application

Routes:

Route Methods Description
/ GET Redirects to /login
/register GET, POST User registration form
/login GET, POST User login with OTP
/welcome GET Post-authentication page

Key Functions:

# Password hashing
hash_password(password, algorithm="SHA256")
β†’ Returns: Hex digest of hashed password

# OTP chain generation
hash_otp(seed, n=100)
β†’ Returns: List of 100 OTP values in reverse order

# Registration handler
@app.route('/register', methods=['GET', 'POST'])
β†’ Validates input β†’ Generates OTP β†’ Registers user

# Login handler
@app.route('/login', methods=['GET', 'POST'])
β†’ Verifies password β†’ Generates OTP β†’ Validates OTP β†’ Redirects

Server Implementation

Server.py - Backend Logic

Class: Server

Attributes:

database_path: str = "database.txt"
public_key: RSA.RsaKey
private_key: RSA.RsaKey
index: int = 0
register_otp: str = "000000"
otp_mod: int = 99  # 100 - 1

Methods:

Method Purpose Input Output
encrypt_line() Encrypt data with RSA plaintext ciphertext
decrypt_line() Decrypt data with RSA ciphertext plaintext
load_database() Load encrypted database - List of users
save_database() Save encrypted database user list -
register_user() Register new user username, hash, OTP True/False
verify_login() Verify credentials username, hash True/False
validate_otp() Verify OTP username, OTP True/False
hash_one_time_otp() Hash single OTP OTP hashed OTP

Database Encryption:

RSA PKCS1_OAEP Encryption Flow:

Write:
1. Format: "username;hash;OTP;counter"
2. Encrypt with public key
3. Store: [4 bytes size] + [encrypted data]

Read:
1. Read 4-byte size
2. Read encrypted data
3. Decrypt with private key
4. Parse: split by ";"

πŸ—„οΈ Database Structure

File Format

Filename: database.txt (RSA encrypted)

Decrypted Format:

username1;hashed_password;OTP_token;counter
username2;hashed_password;OTP_token;counter

Field Descriptions:

Field Type Description Example
username str Letters only alice
hashed_password hex SHA-256 hash 5e884898da...
OTP_token hex Current OTP (Sβ‚™) a3f2b8c1...
counter int OTP usage count 0-99

Example Entry (Decrypted):

alice;5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8;a3f2b8c1d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6;5

Encryption Details

Storage Process:
1. Format line: "user;hash;otp;counter"
2. Encrypt with RSA public key (PKCS1_OAEP)
3. Get encrypted bytes
4. Write: [len(encrypted).to_bytes(4, 'big')] + [encrypted]

Retrieval Process:
1. Read 4 bytes β†’ get encrypted data length
2. Read N bytes β†’ get encrypted data
3. Decrypt with RSA private key
4. Parse decrypted string by ";"

πŸŽ“ Academic Context

Course: BBM 465 - Information Security Laboratory
Institution: Hacettepe University, Computer Engineering Department
Semester: Fall 2024
Group: 28
Team Members:

  • Mehmet Yiğit (b2210356159)
  • Mehmet Oğuz Kocadere (b2210356021)

Topics Covered:

  • Multi-factor authentication (MFA/2FA)
  • Hash chain-based OTP systems
  • RSA public key encryption
  • SHA-256 cryptographic hashing
  • Flask web application security
  • Secure password storage
  • Session management
  • Database encryption

Assignment Objectives:

  1. Implement secure user authentication
  2. Design hash chain OTP mechanism
  3. Encrypt sensitive data with RSA
  4. Build Flask web application
  5. Understand 2FA principles
  6. Practice secure coding

⚠️ Security Considerations

Strengths βœ…

  1. Two-Factor Authentication

    • Password + OTP verification
    • Each factor independently secure
  2. Hash Chain Security

    • SHA-256 cryptographic strength
    • One-time use prevents replay attacks
    • Offline capable (no time sync)
  3. Database Encryption

    • RSA PKCS1_OAEP encryption
    • Data encrypted at rest
    • Private key required for access
  4. Password Protection

    • SHA-256 hashing
    • Never stored in plaintext
    • Server-side verification only
  5. OTP Counter Tracking

    • Prevents OTP reuse
    • Automatic chain renewal
    • State management

Limitations ⚠️

  1. Password Hashing (Educational)

    • Issue: Basic SHA-256 without salt
    • Production Fix: Use bcrypt, Argon2, or PBKDF2
    • Example:
    # Instead of:
    SHA256(password)
    
    # Use:
    bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
  2. RSA Key Management

    • Issue: Keys stored in plaintext files
    • Production Fix: Use HSM or key vault
    • Example: AWS KMS, Azure Key Vault
  3. Session Management

    • Issue: Basic Flask sessions
    • Production Fix: Use secure session storage
    • Example: Redis, database-backed sessions
  4. No Rate Limiting

    • Issue: Vulnerable to brute force
    • Production Fix: Implement rate limiting
    • Example: Flask-Limiter
  5. Global Index Variable

    • Issue: Not thread-safe
    • Production Fix: Use database-stored counter
    • Example: Store counter per-user in database

Production Recommendations

# 1. Password Hashing
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(12))

# 2. Rate Limiting
from flask_limiter import Limiter
limiter = Limiter(app, default_limits=["5 per minute"])

# 3. HTTPS Only
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True

# 4. CSRF Protection
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)

# 5. Environment Variables for Keys
import os
private_key_path = os.environ.get('PRIVATE_KEY_PATH')

# 6. Logging
import logging
logging.basicConfig(level=logging.INFO)

# 7. Input Sanitization
from bleach import clean
username = clean(username, tags=[])

πŸ“‘ API Reference

Client Endpoints

POST /register

Register a new user account.

Request Body (Form):

username: str (letters only)
password: str (>6 chars)

Process:

  1. Validate username/password
  2. Hash password (SHA-256)
  3. Generate OTP chain (100 iterations)
  4. Send to server: username, hash, OTP[0]

Response:

  • Success: Redirect to /login + flash message
  • Failure: Error message displayed

POST /login

Authenticate user with password + OTP.

Request Body (Form):

username: str
password: str

Process:

  1. Hash password
  2. Verify credentials with server
  3. Generate OTP chain
  4. Send OTP[counter] to server
  5. Verify OTP

Response:

  • Success: Redirect to /welcome
  • Failure: Error message displayed

GET /welcome

Display welcome page after successful login.

Response:

<h1>Welcome, {username}!</h1>

Server Methods

register_user(username, hashed_password, otp_token)

Input:

  • username (str): Unique username
  • hashed_password (str): SHA-256 hash
  • otp_token (str): Initial OTP (S₁₀₀)

Output:

  • True: Registration successful
  • False: Username exists

verify_login(username, hashed_password)

Input:

  • username (str): Username to verify
  • hashed_password (str): SHA-256 hash

Output:

  • True: Valid credentials
  • False: Invalid credentials

validate_otp(username, client_otp)

Input:

  • username (str): Username
  • client_otp (str): OTP from client (Sₙ₋₁)

Process:

  1. Load stored OTP (Sβ‚™)
  2. Hash client OTP: SHA-256(Sₙ₋₁)
  3. Compare: SHA-256(Sₙ₋₁) == Sβ‚™
  4. Update: store Sₙ₋₁, counter++

Output:

  • True: Valid OTP
  • False: Invalid OTP

🀝 Contributing

Contributions welcome! Areas for improvement:

  1. Add bcrypt password hashing
  2. Implement rate limiting
  3. Add CSRF protection
  4. Create user profile pages
  5. Add password reset functionality
  6. Implement email verification
  7. Add logging and monitoring
  8. Create admin dashboard

How to Contribute

  1. Fork repository
  2. Create feature branch
  3. Make changes
  4. Test thoroughly
  5. Submit pull request

πŸ“„ License

MIT License - see LICENSE file


πŸ‘€ Author

Mehmet Oğuz Kocadere

πŸ”— Related Security Projects


πŸ™ Acknowledgments

  • Hacettepe University - Computer Engineering Department
  • BBM 465 Course - Information Security Laboratory
  • Flask Documentation - Web framework guide
  • PyCryptoDome - Cryptographic library

πŸ“Š Statistics

Python Lines of Code Security


πŸ“š References


⭐ Star this repository if you found it helpful!

Made with ❀️ for modern web security education

About

Flask web authentication portal with two-factor authentication using 100-iteration SHA-256 hash chain-based OTP, RSA-encrypted database storage (PKCS1_OAEP), secure password hashing, automatic OTP chain renewal, and session management. Educational Python web security project demonstrating modern authentication.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors