Skip to content

Can this phone be trusted?

Device-integrity detection for Android — hardware-attested, signed, and encrypted.. Detection only: the device reports, your backend decides.

Android integration Backend verification

Home

Six languages. One verdict.

  • Kotlin — the reference


    The original backend verifier, published on Maven Central as tech.thessemaj:verifier-kotlin. Scan + token flows, zero dependencies.

    ▶ Quick start

  • Python


    Pip-installable port with the full token path and the scan-verification flow. Runs the same rooted-Pixel fixture, grades it the same.

    ▶ Quick start

  • TypeScript / Node


    Feature-packaged npm module with a flat facade — token path complete, scan flow on the roadmap.

    ▶ Quick start

  • Go


    Stdlib-only module: crypto/ecdh X25519, AES-GCM, crypto/x509 chain verification, embedded registry and pinned roots.

    ▶ Quick start

  • PHP


    PSR-4 package on ext-openssl + ext-sodium, self-contained test runner — no phpunit dependency.

    ▶ Quick start

  • Ruby


    Gemspec-packaged port with a pure-Ruby RFC 7748 X25519 where the host OpenSSL binding falls short.

    ▶ Quick start

  • Rust


    Crate-packaged port on the pure-Rust stack: dalek X25519, aes-gcm, p256/p384 ECDSA, rsa — zero OpenSSL linkage.

    ▶ Quick start

Three principles

  • Detection only


    The device reports; the backend decides. Nothing is killed, blocked or degraded on-device — anything the app could enforce, a rooted attacker can remove.

  • Hardware-bound sessions


    Hardware attestation runs once per session, keyed to the session id your backend issued. The attested key signs every later scan — a captured token is worthless anywhere else.

  • Opaque on the wire


    Tokens carry INTEL_XXXX codes, not explanations. Detector names, probe mechanisms and evasion semantics never leave the device; your backend resolves them from the registry.

Verify a token in 30 seconds

val verifier = ScanVerifier()
val result = verifier.verifyScan(token, sessionId, serverPrivateKey)
when (result.decision) {
    Decision.TRUSTWORTHY -> allow()
    Decision.COMPROMISED -> stepUp(result.blockingSignals)
    Decision.REJECT      -> deny()
}
from deviceintelligence_verifier import TokenVerifier

result = TokenVerifier().verify(token_hex, issued_nonce)
if result.decision.value == "TRUSTWORTHY":
    allow()
import { TokenVerifier } from "./src/index.js";

const result = new TokenVerifier().verify(tokenHex, issuedNonce);
if (result.decision === "TRUSTWORTHY") allow();
import verifier "github.com/iamjosephmj/DeviceIntelligence/verifier-go"

res, _ := verifier.NewTokenVerifierBundled().Verify(tokenHex, issuedNonce)
if res.Decision == verifier.DecisionTrustworthy {
    allow()
}
use DeviceIntelligenceVerifier\TokenVerifier;

$result = (new TokenVerifier())->verify($tokenHex, $issuedNonce);
if ($result['decision'] === 'TRUSTWORTHY') allow();
require "deviceintelligence_verifier"

result = DeviceIntelligenceVerifier::TokenVerifier.new.verify(token_hex, issued_nonce)
allow if result.decision == "TRUSTWORTHY"
use deviceintelligence_verifier::{decision, TokenVerifier};

let result = TokenVerifier::bundled()?.verify(&token_hex, &issued_nonce);
if result.decision == decision::TRUSTWORTHY {
    allow();
}

What the device checks

  • Hardware attestation


    Keymaster KeyDescription chains verified against pinned Google roots, StrongBox vs TEE assurance, challenge-bound freshness.

  • Verified boot


    The TEE's own word on boot state and lock — a spoofer's self-report is cross-checked against hardware and flagged as INTEL_0055.

  • Hook frameworks


    Inline prologues, GOT entries, JNIEnv tables, sealed memfds, linker<->maps divergence, behavioral syscall lies — mechanism-independent evidence.

  • Root & clones


    su binaries, Magisk artifacts, init mount namespaces, daemon sockets, test-keys builds, foreign APK mappings.

  • Emulators


    Translated environments, CPU re-routing anomalies, hypervisor evidence, VM platform markers — probes that cannot fire on genuine silicon.

  • Package tampering


    Live APK vs build-time baseline: signature, entries, dex provenance, installer identity.

Prove it

Every port runs the same rooted-Pixel capture (KernelSU + TrickyStore) and grades it COMPROMISED, check-for-check. CI runs all six suites in parallel on every push:

The suites

Deep dive: the verification specification, the signal catalogue, and the verifier ports page carry the full contract and per-language coverage.