TrustedTime
TrustedTime is a high-integrity, production-grade time guardian for Flutter. It provides a tamper-proof UTC clock anchored to hardware monotonic oscillators, ensuring your app's temporal logic remains perfect even if the system clock is manipulated.
Architecture • Contributing • Security • Changelog
Unlike DateTime.now(), which depends on the user-modifiable system clock, TrustedTime synchronizes with trusted network time sources and anchors that time to the device’s hardware monotonic clock — ensuring timestamps remain correct even if users change their device time or go offline.
Why TrustedTime?
Many apps rely on time for correctness and security:
- Trial expirations
- Subscription billing
- Ticket validity
- Rate limiting
- Audit logging
- Token expiration
Unfortunately, system time is untrusted — users can move it forward or backward at will.
TrustedTime solves this by providing a secure virtual clock that:
✅ Works offline after first sync ✅ Detects clock tampering automatically ✅ Persists across app restarts ✅ Has near-zero runtime overhead ✅ Works across Android, iOS, Web, and Desktop
Platform Support
| Android | iOS | Web | macOS | Windows | Linux |
|---|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Features
- Tamper-Proof Time: Anchors network UTC to hardware monotonic uptime.
- Multi-Source Consensus: Quorum-based resolution via NTP and HTTPS.
- Secure Persistence: Encrypted state recovery across app restarts.
- High Performance: Synchronous, zero-latency access with <1μs overhead.
- Offline Ready: Continues providing trusted time without connectivity once anchored.
- Integrity Monitoring: Real-time event streams for clock jumps and reboots.
Installation
Add TrustedTime to your pubspec.yaml via CLI:
flutter pub add trusted_time
Platform-Specific Setup
Android
Ensure your AndroidManifest.xml (usually found in android/app/src/main/AndroidManifest.xml) includes the Internet permission:
<uses-permission android:name="android.permission.INTERNET" />
iOS / macOS / Windows / Linux / Web
No additional setup or permissions are required. The library automatically leverages native APIs for monotonic timing and secure storage.
Quick Start
1️⃣ Initialize once at app startup
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Await initialization to ensure hardware monotonic anchoring is established.
await TrustedTime.initialize();
runApp(MyApp());
}
2️⃣ Get trusted time anywhere
final now = TrustedTime.now();
final unixMs = TrustedTime.nowUnixMs();
final iso = TrustedTime.nowIso();
3️⃣ Check trust state
if (TrustedTime.isTrusted) {
// Time is verified and safe to use
} else {
// Still syncing or integrity lost
}
4️⃣ Listen for tampering
TrustedTime.onIntegrityLost.listen((_) {
print('System clock changed or device rebooted');
});
5️⃣ Force resync if needed
await TrustedTime.forceResync();
Common Use Cases
Ticketing & Access Control
Prevent users from activating passes early or extending them by changing device time.
Trials & Subscriptions
Ensure “7-day trials” are exactly 7 days — even if the user adjusts their clock or goes offline.
Anti-Fraud & Compliance
Use trusted timestamps for audit logs, transaction signing, and security-critical workflows.
Rate Limiting & Cooldowns
Prevent cooldown bypass attacks caused by local clock manipulation.
How It Works (Simple Explanation)
TrustedTime establishes a Trust Anchor:
- It queries multiple network time sources (NTP + HTTPS).
- It filters bad or slow sources using a quorum algorithm.
- It stores the verified network time alongside the device’s monotonic uptime.
- From then on, it computes:
trustedNow = (currentUptime - uptimeAtSync) + networkTimeAtSync
Because monotonic uptime cannot be changed by the user, this clock remains accurate even if:
- The system time is modified
- The device goes offline
- The app is restarted
Only a device reboot resets uptime — which TrustedTime detects and automatically resynchronizes.
Advanced Configuration
await TrustedTime.initialize(
config: TrustedTimeConfig(
refreshInterval: Duration(hours: 12),
ntpServers: ['time.google.com', 'pool.ntp.org'],
httpsSources: ['https://www.google.com', 'https://www.cloudflare.com'],
maxLatency: Duration(seconds: 2),
minimumQuorum: 2,
persistState: true,
),
);
Platform Behavior
Android
- Uses
SystemClock.elapsedRealtime()(hardware monotonic clock) - Detects manual time and timezone changes automatically
- No setup required
iOS
- Uses
ProcessInfo.systemUptime - Detects system clock changes automatically
- No setup required
Web & Desktop
- Uses HTTPS time sources
- Uses browser/OS monotonic timers
- Works offline after sync
Performance
| Operation | Cost |
|---|---|
TrustedTime.now() |
< 1μs |
| Initial sync | ~100–500ms |
| Memory overhead | ~50 KB |
| Background CPU | Zero when idle |
TrustedTime performs no background polling and uses zero timers once synced.
Security Model
TrustedTime protects against:
| Threat | Protected |
|---|---|
| Manual clock change | ✅ |
| Offline replay | ✅ |
| Trial extension | ✅ |
| System time rollback | ✅ |
| App restart abuse | ✅ |
| Network MITM (single server) | ✅ |
Limitations:
- Requires internet on first launch
- Cannot protect against hardware-level clock manipulation
Comparison
| Capability | DateTime.now() |
flutter_time_guard |
flutter_kronos |
TrustedTime |
|---|---|---|---|---|
| Trusted timestamps | ❌ | ❌ | ⚠️ Basic | ✅ |
| Offline after sync | ❌ | ⚠️ Limited | ✅ | ✅ |
| Detects clock tampering | ❌ | ✅ | ⚠️ Partial | ✅ |
| Multi-source consensus | ❌ | ❌ | ❌ | ✅ |
| HTTPS fallback | ❌ | ❌ | ❌ | ✅ |
| Drift/uncertainty metadata | ❌ | ❌ | ❌ | ✅ |
| Cross-platform | ⚠️ | ⚠️ | ❌ | ✅ |
Zero-latency now() |
❌ | ❌ | ❌ | ✅ |
License
MIT License.
Credits
Inspired by:
- Google Spanner TrueTime model
- NTP RFC 5905
Libraries
- trusted_time
- A Flutter plugin for obtaining a highly-trusted, tamper-proof current time.
- trusted_time_platform_interface