BioKey is a keystroke-dynamics biometric authentication prototype with:
- API auth + biometric verification
- Admin dashboard and evaluation tooling
- Social-style typing-capture prototype
- Synthetic human-like data generation
- Encrypted database backup workflow
android-client/Android app (Kotlin + Compose)backend-server/Sinatra API + auth + dashboard + prototype routesdatabase/schema + Docker compose for PostgreSQLnative-engine/native biometric math module (legacy/optional)tools/generation/export/encryption scriptsdocs/dashboard and evaluation docssecure-backups/encrypted DB backups (.enc) safe to keep in repo
- Ruby 3.x + Bundler
- PostgreSQL (local install) or Docker Desktop
- Android Studio + Android SDK + Java 17+
- Start PostgreSQL.
- Run backend migrations and app:
cd backend-server
bundle install
ruby db/migrate.rb
set APP_SESSION_SECRET=replace_with_min_32_char_secret
set SESSION_TOKEN_PEPPER=replace_with_min_32_char_secret
set APP_AUTH_PEPPER=replace_with_min_16_char_secret
ruby app.rb- Open:
- Dashboard:
http://127.0.0.1:4567/admin - Prototype login:
http://127.0.0.1:4567/prototype/login
From repo root:
.\run_local.ps1Batch wrapper:
run_local.batHealth check:
GET http://127.0.0.1:4567/health
Expected response: JSON status ok
Readiness check:
GET http://127.0.0.1:4567/ready
Expected response: JSON status ready when DB/schema (and Redis, if configured) are healthy.
Metrics endpoint (localhost/admin protected):
GET http://127.0.0.1:4567/metrics
POST /v1/auth/registerPOST /v1/auth/loginPOST /v1/auth/intelligenceGET /v1/auth/profileGET /v1/auth/export-dataPOST /v1/auth/consentPOST /v1/auth/delete-accountPOST /v1/auth/refreshPOST /v1/auth/logoutPOST /v1/trainPOST /v1/login
GET /prototype/loginGET /prototype/feedGET /prototype/api/profile(bearer token required)POST /prototype/api/typing-events(bearer token required)
GET /admin/api/overviewGET /admin/api/feedGET /admin/api/live-feedGET /admin/api/auth-feedGET /admin/api/typing-capturePOST /admin/api/attempt/:id/labelPOST /admin/api/attempts/label-bulkPOST /admin/api/export-datasetPOST /admin/api/run-evaluationPOST /admin/api/apply-retentionGET /admin/api/jobs/:job_id
Responses include:
X-Request-IdX-Api-Version
Biometric verification now includes an intelligence layer that computes:
- entropy-based anomaly signals
- temporal consistency signals
- profile uniqueness and spoofability risk
- action recommendation (
allow,challenge_or_monitor,step_up_auth)
The intelligence payload is included in /v1/login responses and is available as a standalone analysis endpoint at /v1/auth/intelligence.
Script: tools/generate_human_synthetic_40.rb
Examples:
# default preset
cd backend-server
ruby ../tools/generate_human_synthetic_40.rb
# heavy preset
ruby ../tools/generate_human_synthetic_40.rb heavy
# custom: mode users train_repetitions logins_per_user typing_batches_per_user typing_chars_per_batch
ruby ../tools/generate_human_synthetic_40.rb heavy 100 6 60 18 70Generated typing events are tagged with metadata.synthetic = true.
# biometric attempt export + report
ruby tools/export_dataset.rb json
ruby tools/evaluate_dataset.rb docs/evaluation.md
# typing capture export
ruby tools/export_typing_dataset.rbRaw DB dumps are not committed. Use encrypted backups.
Output location: exports/db_backups/*.dump
set DB_BACKUP_PASSPHRASE=replace-with-strong-secret
ruby tools/encrypt_db_backup.rb exports/db_backups/biokey_db_YYYYMMDD_HHMMSS.dumpEncrypted output goes to secure-backups/*.enc.
set DB_BACKUP_PASSPHRASE=replace-with-strong-secret
ruby tools/decrypt_db_backup.rb secure-backups/biokey_db_YYYYMMDD_HHMMSS.dump.encImportant:
- Keep passphrase out of git (for example in local
.secrets/or a secure password manager). .secrets/andexports/are ignored by.gitignore.
Backend:
cd backend-server
bundle exec ruby -Itest test/auth_service_test.rb
bundle exec ruby -Itest test/evaluation_service_test.rb
bundle exec ruby -Itest test/integration_api_test.rbAndroid:
cd android-client
./gradlew testDebugUnitTest --no-daemon
./gradlew :app:assembleDebug --no-daemonWorkflow: .github/workflows/ci.yml
On push/PR to main:
- Backend syntax check (
bundle exec ruby -c app.rb) - Backend migration run (
bundle exec ruby db/migrate.rb) - Backend unit + integration tests
- Android unit tests
- Android assemble debug build
- Runtime schema creation is disabled in app boot; run migrations before app start.
- Dashboard read access is allowed on localhost.
- Dashboard control actions require admin session or
X-Admin-Token. - Proxy trust is gated by
TRUST_PROXY=1. - Required runtime secrets:
APP_SESSION_SECRET,SESSION_TOKEN_PEPPER,APP_AUTH_PEPPER. - Production control token hash:
ADMIN_TOKEN_HASH(lowercase SHA-256 hex digest). - FAR/FRR report quality depends on labeled attempts (
GENUINE/IMPOSTER). - Session tokens are stored as SHA-256 digests at rest (token hashing with pepper).
- With
REDIS_URLset, rate limiting and admin async jobs are coordinated across processes.
Additional production guidance:
- Threat model:
docs/threat_model.md - Monitoring and alerting:
docs/monitoring_alerting.md - Operations maturity plan:
docs/ops_maturity.md - Automated dependency updates:
.github/dependabot.yml - Weekly security workflow:
.github/workflows/security-maintenance.yml
CI includes a lightweight backend performance gate script:
cd backend-server
ruby tools/perf_smoke_gate.rbSupported environment knobs:
PERF_GATE_URL(defaulthttp://127.0.0.1:4567/health)PERF_GATE_REQUESTS(default30)PERF_GATE_P95_MS(default350)
BioKey is a prototype and is not fully production-hardened.