Biometric Workshop Suite ๐Ÿซ†

April 5, 2026 ยท View on GitHub

Biometric Workshop Suite

CI Docs Coverage Python License Educational Use Only Static Version

GitHub Sponsors Ko-fi thanks.dev

An interactive, multi-modality biometric demonstration suite built for classroom and workshop use. Students enrol their biometric traits across five different techniques and see in real time how each system works โ€” from feature extraction through to matching and identification.

โš ๏ธ Educational Use Only

This project is designed exclusively for education and training purposes. The algorithms, storage, and architecture are intentionally simplified to make the concepts accessible and observable. This suite must not be used in any security-critical, production, or real-world authentication context. It provides no meaningful security guarantees and should never be used to protect real systems, data, or identities.


Modules

ModuleTechniqueFeatures extracted
โŒจ๏ธ Keystroke DynamicsTyping rhythm analysisDwell time, flight time per character
๐Ÿ–ฑ๏ธ Mouse DynamicsPointer movement profilingMovement time, path curvature, click dwell
๐Ÿง‘ Face RecognitionGeometric facial features16 normalised landmark ratios (68-point model)
๐ŸŽ™๏ธ Voice BiometricsSpeaker characterisationMFCC mean vector, pitch, spectrogram
โœ๏ธ Signature DynamicsOn-screen handwritingDuration, path length, velocity, stroke count

Every module supports Enrol and Identify (or Verify) with live visualisations so students can see exactly which features are being extracted and how the matching score is calculated.


Requirements

  • Python 3.14+
  • uv (recommended) or pip
  • A modern web browser (Chrome or Firefox recommended)
  • A webcam for the Face Recognition module
  • A microphone for the Voice Biometrics module

Quick Start

1. Clone the repository

git clone <repo-url>
cd Biometric-Workshop-Suite

2. Install dependencies

uv sync

3. Run the server

just run

4. Open your browser

http://localhost:5000

Running a Workshop Session

Before students arrive

  1. Start the server on the presenter's machine.
  2. Connect all student devices to the same network and point browsers at http://<your-ip>:5000.
    • Or use a single shared computer and take turns.
  3. Navigate to Instructor Admin on the home page and enter the admin PIN to reset any profiles left from a previous session.

General pattern for each module

  1. Each student enters their name and enrols by performing the biometric action (typing, moving the mouse, speaking, etc.).
  2. Once several students are enrolled, any student can press Identify โ€” the system ranks all profiles by confidence and shows the best match.
  3. Discuss the results as a group (see discussion prompts below).

Module-specific notes

Keystroke Dynamics

  • Students type the quick brown fox 5 times to build their profile. Encourage natural, consistent typing speed.
  • The fixed phrase keeps all profiles comparable. Changing it mid-session requires re-enrolling everyone.

Mouse Dynamics

  • Students click through 8 on-screen targets 5 times. Movement paths are visualised live.
  • Results vary noticeably between a mouse and a trackpad โ€” worth demonstrating.

Face Recognition

  • Requires webcam access. One capture per student (single-sample enrolment).
  • Uses facial geometry (ratios between landmarks), not pixel comparison โ€” lighting affects results.

Voice Biometrics

  • Students speak for ~10 seconds to enrol. A second recording is used for identification.
  • Results are affected by background noise, microphone quality, and speaking style.

Signature Dynamics

  • Students draw their signature on screen using a mouse, trackpad, or touchscreen.
  • The system measures how the signature is drawn (speed, pressure, stroke order), not just its shape.

Discussion prompts

  • Why does the system sometimes get it right / wrong?
  • Which module felt most reliable? Why?
  • What would an attacker need to do to fool each system?
  • How do these techniques differ from passwords or PINs?
  • What are the privacy implications of storing biometric data?
  • Where are these techniques used in the real world?

Admin Panel

An instructor admin page is available at /admin (or admin.html in the static version). It is PIN-protected to prevent students from accidentally or deliberately managing each other's profiles.

Default PIN: 1965

From the admin panel the instructor can:

  • View all enrolled profiles for every modality
  • Delete individual profiles
  • Reset all profiles for a specific modality
  • Reset all profiles across all modalities at once (clean slate)
  • Export profiles for any modality as a JSON file
  • Import profiles from a previously exported JSON file
  • Change the admin PIN

To change the default PIN before a session, navigate to /admin, log in with 1965, and use the Change Admin PIN form.


How the Matching Works

Keystroke & Mouse Dynamics

Profiles are built by computing the mean and standard deviation of each timing feature across multiple enrolment attempts. Identification uses a normalised Manhattan distance:

distance = mean over all features of  |sample โˆ’ mean| / max(std, floor)

Features with low variance (consistent behaviour) are weighted more heavily. Distances are converted to confidence percentages via softmax.

Face Recognition

16 geometric ratios are extracted from 68 facial landmarks detected by a TinyFace model (runs entirely in the browser). Identification uses cosine similarity between the enrolment vector and the live capture.

Voice Biometrics

Short-time Fourier analysis produces a spectrogram, from which Mel-Frequency Cepstral Coefficients (MFCCs) are extracted per frame. The mean MFCC vector across the recording forms the profile. Identification uses cosine similarity.

Signature Dynamics

Six scalar features are extracted from the stroke data: total duration, normalised path length, average velocity, peak velocity, stroke count, and direction-change rate. Identification uses a weighted Euclidean distance normalised per feature.


Configuration

Open src/app.py and edit the constants near the top:

VariableDefaultDescription
PHRASE"the quick brown fox"The phrase typed in the Keystroke module
ENROLL_SAMPLES_REQUIRED5Keystroke enrolment attempts required
MOUSE_ENROLL_SAMPLES_REQUIRED5Mouse enrolment attempts required
DEFAULT_ADMIN_PIN"1965"Fallback PIN if admin_config.json is absent

The admin PIN can also be changed at runtime via the admin panel without restarting the server.


Hosting Options

Option A โ€” GitHub Pages (static, no server needed)

The docs/ folder is a fully self-contained static version โ€” all logic runs in JavaScript and all profiles are stored in the browser's localStorage. No Python or server required.

The included GitHub Actions workflow (.github/workflows/docs.yml) automatically deploys both the static app and the MkDocs documentation to GitHub Pages on every push to main.

  1. Push the repository to GitHub.
  2. Go to Settings โ†’ Pages, set source to GitHub Actions.
  3. Your suite will be live at https://<username>.github.io/<repo-name>/ and the documentation at https://<username>.github.io/<repo-name>/documentation/.

Note: In the static version, each student's data is stored in their own browser. The admin page on the static version can only manage data on the device where it is opened. For a shared server where all students connect to the same backend, use Option B or C.


Option B โ€” Render (hosted Flask app, shared across devices)

The Flask version stores all profiles on the server โ€” all students share the same profile store in real time. Ideal when students each have their own device.

  1. Push the repository to GitHub.
  2. Sign up at render.com and click New โ†’ Web Service.
  3. Connect your repository. Render will detect render.yaml and configure everything automatically.
  4. Click Deploy and share the URL with students.

Note: Render's free tier spins down after 15 minutes of inactivity โ€” the first request after a sleep may take ~30 seconds. Profile data stored on disk will be reset on each redeploy.

To run in production mode locally (mirrors the Render environment):

just serve

Option C โ€” Local network (no deployment required)

The simplest option for a classroom: run the server on the presenter's machine and share the local IP address.

just run-network

Then share http://<your-local-ip>:5000 with students on the same Wi-Fi. No accounts, deployment, or internet connection needed.


Project Structure

.
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ app.py                   # Flask backend โ€” routes, APIs, matching algorithms
โ”œโ”€โ”€ templates/
โ”‚   โ”œโ”€โ”€ home.html                # Landing page
โ”‚   โ”œโ”€โ”€ admin.html               # PIN-protected instructor admin panel
โ”‚   โ”œโ”€โ”€ keystroke.html           # Keystroke dynamics module
โ”‚   โ”œโ”€โ”€ mouse.html               # Mouse dynamics module
โ”‚   โ”œโ”€โ”€ face.html                # Face recognition module
โ”‚   โ”œโ”€โ”€ voice.html               # Voice biometrics module
โ”‚   โ””โ”€โ”€ signature.html           # Signature dynamics module
โ”œโ”€โ”€ docs/                        # Fully static version (GitHub Pages)
โ”‚   โ”œโ”€โ”€ index.html
โ”‚   โ”œโ”€โ”€ admin.html
โ”‚   โ”œโ”€โ”€ keystroke.html
โ”‚   โ”œโ”€โ”€ mouse.html
โ”‚   โ”œโ”€โ”€ face.html
โ”‚   โ”œโ”€โ”€ voice.html
โ”‚   โ””โ”€โ”€ signature.html
โ”œโ”€โ”€ tests/                       # pytest + Playwright test suite
โ”œโ”€โ”€ profiles.json                # Keystroke profiles (auto-created)
โ”œโ”€โ”€ mouse_profiles.json          # Mouse profiles (auto-created)
โ”œโ”€โ”€ face_profiles.json           # Face profiles (auto-created)
โ”œโ”€โ”€ voice_profiles.json          # Voice profiles (auto-created)
โ”œโ”€โ”€ signature_profiles.json      # Signature profiles (auto-created)
โ”œโ”€โ”€ admin_config.json            # Admin PIN storage (auto-created)
โ”œโ”€โ”€ render.yaml                  # Render deployment config
โ”œโ”€โ”€ justfile                     # Task runner shortcuts
โ””โ”€โ”€ pyproject.toml               # Project metadata and dependencies

Troubleshooting

ProblemSolution
Wrong key resets the keystroke attemptType carefully โ€” the phrase must be typed exactly as shown
Keystroke/mouse results always favour the same personEnsure at least 3โ€“4 students have enrolled before identifying
Identification seems randomTry enrolling with more consistent speed and technique
Server not reachable from other devicesUse just run-network or ensure host="0.0.0.0" in src/app.py
Camera not working (Face module)Check browser permissions โ€” the page needs webcam access
Microphone not working (Voice module)Check browser permissions and ensure no other app holds the mic
Face model fails to loadThe model files in static/models/ must be accessible โ€” check the browser console for 404 errors
Admin PIN forgottenDelete admin_config.json from the project root; the default PIN 1965 will be restored on next start

Support

If you find this project useful for your teaching or workshops, consider buying me a coffee โ€” it helps cover hosting costs and motivates continued development.

GitHub Sponsors Ko-fi thanks.dev


Licence

This project is released for educational use. See LICENSE for details.