Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SENTRY — Cognitive Behavioural Biometric Authentication

Continuous, passive identity verification by how you type and move the mouse — not by a password.

SENTRY runs silently in the background. Every 10 seconds it evaluates a 12-dimensional behavioural fingerprint against a per-user Isolation Forest model. If the behaviour stops matching the enrolled user, the workstation locks automatically.


Screenshots

Login Data collection
Login page Data collection task page
Locked out Dashboard
Locked-out page on anomaly General dashboard

How it works

1. Behavioural Capture — daemon.py

A background thread (InputCapture, powered by pynput) hooks four event streams simultaneously:

Stream Events captured
Keyboard key_press (down), key_release (up) — key identity + timestamp
Mouse move on_move — (x, y, timestamp)
Mouse click on_click — (x, y, button, pressed, timestamp)
Scroll wheel on_scroll — (x, y, dx, dy, timestamp)

Events are collected into a thread-safe ring buffer and flushed every 10-second micro-session into the cognitive mapping pipeline.

2. Cognitive Mapping — cognitive_mapper.py

Raw events are converted into a 12-feature behavioural vector:

Code Feature What it measures
SE Saccade Entropy Randomness of cursor scanning directions (Shannon entropy over 8 directional bins)
KDV Key Dwell Variability Std-dev of key hold durations
DFT Digram Flight Time Std-dev of key-release to key-press gaps across all keystrokes
HHE Hick-Hyman Entropy Slope How movement time scales with click-distance complexity (regression slope)
PAR Pause-to-Action Ratio Fraction of session time spent in gaps greater than 500 ms
MJA Mouse Jerk/Acceleration Mean derivative of cursor velocity (abrupt stop control, micro-tremor)
SWV Scroll Wheel Variance Std-dev of inter-scroll gaps × 100 (reading rhythm)
ECR Error Correction Rate Backspace+Delete events divided by max(total_keystrokes, 40)
ARM Adaptation Reaction Margin Latency to correct toward a displaced UI element (perturbation probe)
MRC Motor Recovery Curve Velocity normalisation slope after first contact with displaced target
HRR Habituation Response Rate Rate at which ARM shrinks across repeated probes (habituation)
SOR Spatial Overshoot Ratio Max overshoot divided by displacement when clicking a displaced target

ARM / MRC / HRR / SOR are computed from periodic perturbation probes injected by the Electron frontend and smoothed with EMA (alpha = 0.3 fast update, alpha = 0.05 slow decay between probes).

3. Anomaly Detection — ml_backend.py

A decoupled Isolation Forest ensemble is trained per user on StandardScaler-normalised features:

Sub-model Features Contamination
combined All 12 features Dynamic (see below)
kb KDV, DFT 0.07
mouse SE, HHE, MJA 0.05
bs ECR 0.05
adapt ARM, MRC, HRR, SOR 0.08
per-metric (x12) One feature each Dynamic

Hyperparameters common to all sub-models:

n_estimators  = 100
random_state  = 42
max_samples   = "auto"   (scikit-learn default — min(256, n_samples))
max_features  = 1.0      (scikit-learn default)

Dynamic contamination (applied to combined and all per-metric models based on training-set size):

Training sessions contamination
fewer than 50 0.15
50 to 99 0.10
100 to 199 0.07
200 or more 0.05

Scoring pipeline: each active sub-model emits a raw decision-function score; per-channel sensitivity sliders (mouse / typing / scroll / backspace, range 1.0–N) shift and amplify the score. The worst (most anomalous) score across all active sub-models drives the state machine. Per-metric scores are smoothed with EMA (alpha = 0.3).

4. State Machine — auth_orchestrator.py

State Enters when Exits when
AUTH_OK Default after model is trained 1 ANOMALOUS session → LOCK; 1 SUSPICIOUS session → RISK
RISK vote_count between 1 and lock_threshold 3 consecutive SUSPICIOUS sessions → LOCK; 2 consecutive CLEAN sessions → AUTH_OK
LOCK vote_count >= lock_threshold OR 3 consecutive SUSPICIOUS sessions 2 consecutive CLEAN sessions OR manual unlock

vote_count: number of per-metric Isolation Forests that vote anomalous for the current micro-session.
lock_threshold: default 3, configurable 1–8 via the dashboard sensitivity panel.

On entering LOCK, the Python backend calls ctypes.windll.user32.LockWorkStation() to lock the Windows session instantly.

5. Enrollment — main.py

  • A minimum of 50 quality sessions (each 10-second micro-window with at least 3 non-zero features, de-duplicated by feature hash) must be collected before an Isolation Forest can be trained.
  • Raw telemetry is persisted to ~/Documents/input data/<user>_<timestamp>.json so the model can always be retrained from scratch.
  • Offline replay: python main.py --user <name> --replay <path> imports a saved telemetry JSON and retrains without live capture.

6. Frontend — Electron + React + Vite

The desktop shell (frontend/) communicates with the Python process over newline-delimited stdio JSON:

Screen Purpose
Login User selection and account creation (SQLite, bcrypt-hashed passwords)
Data collection Enrolment UI with real-time session progress; injects perturbation probes (displaced click targets) to capture ARM/MRC/HRR/SOR adaptation metrics
Dashboard Live 12-metric radar chart, Z-score sparkline, per-channel sensitivity sliders, auth-state indicator, session history
Lock screen Shown when SENTRY raises an anomaly; requires password re-authentication to unlock

Architecture

daemon.py              → InputCapture: background keystroke / mouse / scroll capture (pynput)
cognitive_mapper.py    → raw events → 12D behavioural feature vectors
ml_backend.py          → per-user decoupled Isolation Forest ensemble (scikit-learn)
auth_orchestrator.py   → enrol / verify / lock finite state machine
main.py                → stdio JSON bridge (Electron IPC ↔ Python backend)
frontend/              → Electron 40 + React 19 + Vite 7 desktop app

Stack

Layer Technology
Behavioural capture Python · pynput · psutil
Feature engineering NumPy · SciPy (entropy, linregress)
Anomaly detection scikit-learn (IsolationForest, StandardScaler)
Data persistence JSON (raw telemetry) · pickle (trained models) · SQLite (user accounts)
Desktop shell Electron 40 · React 19 · Vite 7 · Recharts
IPC stdio newline-delimited JSON

Running locally

Python backend

pip install -r requirements.txt
python main.py --user your_username

First run with no existing model enters unenrolled mode; the Electron frontend guides you through the data collection and training flow. Once 50+ quality sessions are captured, the Isolation Forest is trained and live verification begins.

# Offline replay from a previously saved telemetry file
python main.py --user your_username --replay path/to/telemetry.json

Electron frontend

cd frontend
npm install
npm run dev        # starts Vite dev server + Electron concurrently

Note on scope

SENTRY was built as a final-year academic research project exploring passive continuous authentication through behavioural biometrics — as a complementary layer alongside (not a replacement for) traditional credentials. It is a research and demonstration system and is not hardened for production deployment.

About

SENTRY: A passive continuous authentication system using cognitive behavioural biometrics and Isolation Forest anomaly detection.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages