Offline QR & Link Security for the Privacy-Conscious
"Mehr" (Persian: مهر) means trust, covenant, light — the foundation of secure scanning.
📺 Watch the Demo: https://youtu.be/n8bheouj4jM
| Item | Link |
|---|---|
| 📝 Essay (300 words) | ESSAY.md |
| 🎬 Demo Video | YouTube |
| 📋 Submission Checklist | SUBMISSION_CHECKLIST.md |
| 🔍 Judge Quickstart | JUDGE_QUICKSTART.md |
| 📅 Contest Timeline | CONTEST_START.md |
| Step | Action | Time |
|---|---|---|
| 1 | 📱 Download APK | 10s |
| 2 | 🌐 Open Web Demo — paste paypa1-secure.tk |
20s |
| 3 | ✅ Run ./judge/verify_offline.sh (proves zero network calls) |
30s |
📋 Full Guide: JUDGE_QUICKSTART.md • 📝 Essay: ESSAY.md
Mehr Guard is a privacy-first QR code and URL security scanner built with Kotlin Multiplatform. It detects phishing attacks, brand impersonation, and malicious redirects entirely on-device — no cloud APIs, no data collection, no network calls.
Core Value Proposition:
- 100% Offline Analysis — Your scanned URLs never leave your device
- 5 Platform Targets — Android, iOS, Desktop (JVM), Web (JS), Web (Wasm)
- 87% F1 Score — Ensemble ML + 25 heuristics detect real-world phishing
- <5ms Latency — Real-time analysis during camera scanning
Live Web Demo: raoof128.github.io
Paste any URL to test detection:
| URL | Expected Verdict |
|---|---|
https://google.com |
✅ SAFE |
https://paypa1-secure.tk/login |
🔴 MALICIOUS — Brand impersonation |
https://gооgle.com (Cyrillic о) |
🔴 MALICIOUS — Homograph attack |
Download: MehrGuard-2.0.36-debug.apk
Install on any Android 8+ device. No build required.
Note: Debug-signed APK (suitable for judge evaluation). A release-signed APK is not required for evaluation.
| Requirement | Version | Notes |
|---|---|---|
| JDK | 17+ | Temurin or Corretto recommended |
| Gradle | 8.13 (bundled) | Uses wrapper |
| Android Studio | Latest | For Android builds |
| Xcode | 15+ | For iOS builds (macOS only) |
git clone https://github.com/Raoof128/Raoof128.github.io.git
cd Raoof128.github.io# Debug build (installs to connected device/emulator)
./gradlew :androidApp:installDebug
# Release APK
./gradlew :androidApp:assembleRelease
# Output: androidApp/build/outputs/apk/release/androidApp-release.apkNote: Release builds require signing. Copy keystore.properties.template to keystore.properties and configure your keystore, or the build will use debug signing.
# Run directly
./gradlew :desktopApp:run
# Package for distribution
./gradlew :desktopApp:packageDmg # macOS
./gradlew :desktopApp:packageMsi # Windows
./gradlew :desktopApp:packageDeb # Linux# Step 1: Build KMP framework
./gradlew :common:linkDebugFrameworkIosSimulatorArm64
# Step 2: Open Xcode project
open iosApp/MehrGuard.xcodeproj
# Step 3: In Xcode
# - Select iPhone 16 Pro simulator (or any iOS 17+ simulator)
# - Press ⌘+R to build and runFirst-time setup: Link the framework in Xcode:
- Select MehrGuard target → General tab
- Scroll to "Frameworks, Libraries, and Embedded Content"
- Add
common/build/bin/iosSimulatorArm64/debugFramework/common.framework - Set Embed to "Embed & Sign"
# Development server with hot reload
./gradlew :webApp:jsBrowserDevelopmentRun
# Opens http://localhost:8080
# Production build
./gradlew :webApp:jsBrowserProductionWebpack
# Output: webApp/build/dist/js/productionExecutable/# Development server
./gradlew :webApp:wasmJsBrowserDevelopmentRun
# Production build
./gradlew :webApp:wasmJsBrowserProductionWebpack# All shared tests
./gradlew :common:allTests
# Platform-specific
./gradlew :common:desktopTest # JVM tests
./gradlew :androidApp:testDebugUnitTest # Android unit tests
# Coverage report
./gradlew :common:koverXmlReport
# Output: common/build/reports/kover/xml/report.xml┌─────────────────────────────────────────────────────────────────────┐
│ Application Layer │
├──────────────┬──────────────┬──────────────┬──────────────┬─────────┤
│ androidApp │ iosApp │ desktopApp │ webApp │ webApp │
│ Compose UI │ SwiftUI + │ Compose │ Kotlin/JS │ Kotlin/ │
│ CameraX │ KMP Bridge │ Desktop │ Browser │ Wasm │
│ ML Kit │ Vision │ ZXing │ jsQR │ jsQR │
└──────┬───────┴──────┬───────┴──────┬───────┴──────┬───────┴────┬────┘
│ │ │ │ │
└──────────────┴──────────────┴──────────────┴────────────┘
│
▼
┌───────────────────────────────────────────────┐
│ common module (100% shared) │
│ • PhishingEngine (orchestration) │
│ • EnsembleModel (3-model ML) │
│ • HeuristicsEngine (25+ rules) │
│ • BrandDetector (60+ brands) │
│ • FeatureExtractor (URL features) │
│ • SQLDelight (scan history) │
└───────────────────────────────────────────────┘
| Component | Lines | Shared |
|---|---|---|
| Detection Engine | ~11,000 | 100% |
| ML Models | ~1,400 | 100% |
| Heuristics | ~2,500 | 100% |
| Platform Code | ~12,500 | 0% |
| Total | ~26,000 | 52% |
All security-critical logic lives in common/src/commonMain/kotlin/. Platform modules only implement camera/QR scanning and native UI.
-
Heuristics Engine (25+ checks)
- Homograph detection (Cyrillic, Greek lookalikes)
- Brand impersonation (typosquatting, fuzzy matching)
- Suspicious TLDs (.tk, .ml, .ga, .cf)
- IP obfuscation (decimal, hex, octal)
- @ symbol injection, URL shorteners, credential paths
-
Ensemble ML Model
- Logistic Regression (speed)
- Gradient Boosting (accuracy)
- Decision Rules (explainability)
- Majority voting for final prediction
-
Verdict Determination
- Each component votes: SAFE / SUSPICIOUS / MALICIOUS
- 3+ SAFE votes → SAFE
- 2+ MALICIOUS votes → MALICIOUS
- Critical escalations override (homograph, @ symbol)
| Metric | Value |
|---|---|
| P50 Latency | <1ms |
| P99 Latency | <5ms |
| F1 Score | 87% |
| False Positive Rate | <5% on Alexa Top 100 |
Red Team Mode is a hidden developer feature that exposes curated attack scenarios for testing the detection engine. This allows judges and developers to instantly verify detection accuracy without needing to print QR codes.
┌─────────────────────────────────────────────────────────────────────┐
│ RED TEAM MODE ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ SHARED MODULE (common/redteam/) │ │
│ │ │ │
│ │ RedTeamScenarios.kt │ │
│ │ ├── 19 curated attack scenarios (object SCENARIOS) │ │
│ │ ├── Scenario data class (id, category, url, expectedScore) │ │
│ │ ├── Categories: Homograph, IP Obfuscation, TLD, Brand, etc. │ │
│ │ └── Utility: groupedByCategory(), getById() │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ ▼ ▼ ▼ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ Android │ │ iOS │ │ Desktop │ │
│ │ RedTeamPanel │ │ RedTeamPanel │ │ RedTeamChips │ │
│ │ (Compose) │ │ (SwiftUI) │ │ (Compose) │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Web (JavaScript array mirrors Kotlin RedTeamScenarios) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
All 5 platforms share the exact same scenarios with identical IDs, URLs, and expected scores:
| Source File | Platform | Implementation |
|---|---|---|
common/.../redteam/RedTeamScenarios.kt |
Android, Desktop | Direct Kotlin import |
iosApp/.../MockTypes.swift |
iOS | Swift enum mirroring Kotlin |
webApp/.../scanner.js |
Web (JS/Wasm) | JavaScript array mirror |
| Platform | Activation Method | UI Location |
|---|---|---|
| Android | Settings → Tap version number 7 times → Developer Mode unlocks | Red Team panel appears at top of Scanner screen |
| iOS | Settings → Tap version number 7 times → Developer Mode unlocks | Red Team scenarios panel in Scanner view |
| Desktop | Click "🕵️ Judge Mode" toggle in header bar | Horizontal scrollable chip bar in Scanner |
| Web | Settings → Security Settings → Toggle "Enable Red Team Scenarios" | Chip grid appears above scanner |
| Category | Count | Example | Detection Target |
|---|---|---|---|
| Homograph Attack | 3 | https://аpple.com (Cyrillic 'а') |
Mixed Unicode scripts |
| IP Obfuscation | 3 | http://3232235777/malware |
Decimal/Hex/Octal IP |
| Suspicious TLD | 3 | https://paypa1-secure.tk |
Free/abused TLDs |
| Nested Redirect | 2 | https://legit.com?url=https://phishing.tk |
URL-in-URL patterns |
| Brand Impersonation | 3 | https://paypa1.com |
Typosquatting |
| URL Shortener | 2 | https://bit.ly/xyz |
Destination hiding |
| Safe Control | 2 | https://google.com |
Baseline verification |
// 1. User taps a Red Team scenario chip
val scenario = RedTeamScenarios.getById("HG-001") // Cyrillic Apple
// 2. URL is fed directly to PhishingEngine (bypasses camera)
val result = phishingEngine.analyze(scenario.maliciousUrl)
// 3. Result displayed with full breakdown
// - Expected: score 70-100, verdict MALICIOUS
// - Signals: MIXED_SCRIPTS, BRAND_IMPERSONATION, HOMOGRAPH_DETECTED# Run all judge verification tests
./judge/verify_all.sh
# Individual verifications:
./judge/verify_offline.sh # Proves zero network calls
./judge/verify_performance.sh # Proves <5ms latency
./judge/verify_accuracy.sh # Proves 87% F1 score on red team corpus
./judge/verify_parity.sh # Proves identical verdicts across platformsMehr Guard makes zero network calls for analysis. Verification:
./judge/verify_offline.sh
# ✅ OFFLINE VERIFICATION PASSED
# Analyzed 27 URLs, made 0 network callsThe detection engine has no HTTP client dependencies. Privacy is architectural, not a policy.
18 languages supported across all platforms:
English, German, French, Spanish, Italian, Portuguese, Russian, Chinese, Japanese, Korean, Hindi, Arabic, Thai, Vietnamese, Turkish, Indonesian, Hebrew, Persian
├── common/ # Shared KMP module (detection engine, ML, data)
│ ├── src/commonMain/ # Cross-platform Kotlin
│ ├── src/androidMain/ # Android-specific (SQLite driver)
│ ├── src/iosMain/ # iOS-specific (SQLite driver)
│ ├── src/desktopMain/ # Desktop-specific (SQLite driver)
│ ├── src/jsMain/ # JS-specific (IndexedDB driver)
│ └── src/commonTest/ # Shared tests (1,248+)
├── androidApp/ # Android application (Compose)
├── iosApp/ # iOS application (SwiftUI + KMP)
├── desktopApp/ # Desktop application (Compose Desktop)
├── webApp/ # Web application (Kotlin/JS + Wasm)
├── judge/ # Verification scripts for claims
└── docs/ # Technical documentation
All claims are backed by reproducible evidence:
./judge/verify_all.sh # Run all verifications
./judge/verify_offline.sh # Prove zero network calls
./judge/verify_performance.sh # Prove <5ms latency
./judge/verify_accuracy.sh # Prove 87% F1 score
./judge/verify_parity.sh # Prove cross-platform parity| Document | Purpose |
|---|---|
| JUDGE_QUICKSTART.md | 5-minute verification guide |
| ESSAY.md | Competition essay (300 words) |
| docs/ARCHITECTURE.md | System design |
| docs/SHARED_CODE_REPORT.md | KMP code sharing breakdown |
| docs/ML_MODEL.md | ML architecture details |
Copyright 2025-2026 Mehr Guard Contributors
Licensed under the Apache License, Version 2.0
See LICENSE for full text.
Author: Mohammad Raouf Abedini
Email: raoof.r12@gmail.com | mohammadraouf.abedini@students.mq.edu.au
University: Macquarie University, Sydney, Australia
GitHub: @Raoof128
🛡️ Mehr Guard
Scan smart. Stay protected.