Invariant SDK Documentation
Technical reference for the Invariant Hardware Attestation SDK. This library provides a cryptographic interface to the Android Keystore System and StrongBox Security Element.
Overview
The Invariant SDK enables mobile applications to cryptographically verify that a client device is a physical Android handset, ensuring it is not an emulator, a server-farmed instance, or a rooted environment running instrumentation tools.
Unlike behavioral analysis or fingerprinting (which are probabilistic), Invariant uses deterministic hardware attestation. It generates a non-exportable key pair inside the device's Trusted Execution Environment (TEE) and validates the chain of trust against the Google Hardware Root.
System Architecture
The verification process follows a challenge-response protocol designed to prevent replay attacks and ensure freshness.
Challenge Acquisition
The SDK requests a cryptographic nonce from the Invariant API. This nonce is valid for 5 minutes.
Hardware Signing
The SDK invokes the Android Keystore to generate a temporary, non-exportable key pair (EC P-256). The nonce is embedded into the key's Attestation Certificate extension.
Attestation
The device returns an X.509 Certificate Chain signed by the hardware root (Google/Titan M).
Verification
The SDK transmits the chain and signature to Invariant's Rust backend. The backend parses the ASN.1 structure, verifies the signature against the nonce, and validates the Root of Trust.
Security Model & Threat Assumptions
THREATS MITIGATED
- Emulator Farming: Detection of virtualized environments (Bluestacks, AWS Device Farm).
- Instrumentation: Detection of hooked environments (Frida, Xposed) via integrity checks.
- Man-in-the-Middle: Prevented via TLS pinning and signature verification.
- Replay Attacks: Prevented via server-issued nonces.
OUT OF SCOPE
- Device Theft: We certify the device is genuine, not that the user holding it is the owner.
- Analog Gap: We cannot prevent a human from physically operating a device farm (though cost makes this prohibitive).
Installation
Add the SDK to your project's dependencies. The SDK requires Android SDK 21+ (Android 5.0), though hardware attestation guarantees are strongest on Android 9+ (API 28).
dependencies: invariant_sdk: ^1.0.4 http: ^1.2.0
Initialization
Initialize the SDK once at the root of your application, typically in `main.dart` or your dependency injection setup.
sk_test_demo. The SDK defaults to the Invariant Testnet Node.import 'package:invariant_sdk/invariant_sdk.dart';
void main() {
// Initialize with the Testnet Key
Invariant.initialize(
apiKey: "sk_test_demo",
// Default: http://16.171.151.222:3000 (Invariant Testnet)
);
runApp(MyApp());
}Verify Device
Call `verifyDevice()` at critical checkpoints (Sign Up, Login, or High-Value Transaction). This method is asynchronous and performs network IO.
try {
final result = await Invariant.verifyDevice();
if (result.isVerified) {
print("Device Trusted: ${result.riskTier}");
// Proceed with transaction
} else {
print("Device Rejected: ${result.riskTier}");
// Block or require Step-Up Auth
}
} catch (e) {
// Handle network or system errors (Fail Open or Closed based on policy)
}Response Reference
The `InvariantResult` object contains the deterministic assessment of the device's hardware security posture.
| Field | Type | Description |
|---|---|---|
| isVerified | boolean | True if the attestation chain is valid, rooted, and matches the nonce. |
| riskTier | string | The classification of the environment (see table below). |
| riskScore | double | 0.0 (Safe) to 100.0 (Compromised). Derived from OS integrity signals. |
| identityId | string? | Ephemeral session ID useful for server-side audit logs. |
Risk Tiers
Pattern: Shadow Mode
For initial integration, we strongly recommend the Shadow Mode pattern. This involves calling the SDK and logging the result without blocking the user.
This allows you to establish a baseline of your traffic quality (e.g., "What % of my users are actually on Emulators?") before turning on active blocking.
// 1. Perform check silently
final result = await Invariant.verifyDevice();
// 2. Attach risk data to your existing analytics event
Analytics.logEvent("user_signup_attempt", parameters: {
"user_id": "12345",
"inv_tier": result.riskTier, // e.g. "PHYSICAL_TEE"
"inv_verified": result.isVerified
});
// 3. Allow user to proceed regardless of result (for now)Pattern: Active Enforcement
Once baselines are established, you can enforce policies based on the `riskTier`.
Strict Policy (Fintech / Crypto)
Block all `EMULATOR` and `SOFTWARE_ONLY`. Require `PHYSICAL_TEE` or `STRONGBOX` for money movement.
Permissive Policy (Social / Gaming)
Allow `PHYSICAL_TEE`. Flag `EMULATOR` for manual review or CAPTCHA challenge.
Error Handling
The SDK may throw exceptions during the hardware handshake or network call. Robust applications should implement a Fail-Open or Fail-Closed strategy depending on risk appetite.
| Error Type | Cause | Recommended Action |
|---|---|---|
| HARDWARE_FAILURE | Device Keystore is broken or busy. Common on low-end devices. | Retry once. If fails, Fallback to SMS auth. |
| NETWORK_ERROR | Unable to reach Invariant API to verify nonce. | Fail Open (Allow user) or Queue for later verification. |
| REJECTED_BY_POLICY | Device is valid but blocked by server-side blacklists (e.g. known farm ID). | Block immediately. |
Privacy & Data Minimization
Invariant is a Zero-PII (Personally Identifiable Information) system. We verify the device, not the user.
- No Biometrics: We do not access FaceID or Fingerprint data.
- No Hardware IDs: We do not collect IMEI, MAC Addresses, or Phone Numbers.
- Key Isolation: The private key generated for attestation never leaves the device's Secure Enclave.
- Data Transmission: Only the X.509 Certificate Chain and the signed Nonce are sent to the server.