🔥 Discover this trending post from Hacker News 📖
📂 **Category**:
📌 **What You’ll Learn**:
Independent decompilation of the Persona Wallet APK v1.14.0 (SDK v2.32.3, built March 11, 2026) and analysis of the web inquiry bundle from cdn.withpersona.com (inquiry-main.js, 1.8MB) reveals the full scope of Persona’s surveillance capabilities. The APK was obtained from APKPure and decompiled with jadx 1.5.5. The Roblox APK v2.714.1091 was decompiled separately to confirm the SDK integration. All findings are from publicly available APKs and client-side JavaScript served to every user. New
SDKHardcoded AES-256-GCM Telemetry Encryption Key
Every copy of the Persona SDK contains a hardcoded AES-256-GCM encryption key in TrackingEventUtilsKt.java line 22:
4ERbfREmnh82jvK5QaXOv8jZ3OQq9hKg5o/Hbb3l9bk=
All telemetry events are “encrypted” with this key before transmission to POST https://tg.withpersona.com/t. Since the key is embedded in every publicly downloadable APK, anyone can decrypt the payloads. The encryption pipeline serializes events to JSON, wraps them as ⚡, encrypts with AES-256-GCM using a 12-byte random IV, then Base64-encodes the ciphertext and sends it as 🔥. This is obfuscation, not security. A standalone Python decryptor was built and verified in round-trip testing.
Primary source Decompiled from Persona Wallet APK v1.14.0 | jadx 1.5.5 | 2026-03-31
| File | tracking-events-2.35.2.aar → TrackingEventUtilsKt.java, line 22 |
| SHA-256 | 048e9971ef932d8dac568b5d5b271e4cacaa443f32049a8dff519bd2dc1154d6 |
| APK package | com.withpersona.app.reusablepersonas v1.14.0 (version code 1001380, target SDK 35) |
| APK manifest SHA-256 | 0daf3d5292e143d4a636e8575810849128e77f491d814d5e058ce68947d16fc1 |
| Reproduce | jadx -d out persona-wallet.apk && grep -n "4ERbfREmnh82jvK5" out/**/TrackingEventUtilsKt.java |
Decompiled source (lines 18–22):
public final class TrackingEventUtilsKt {
private static final int GCM_TAG_LENGTH_BITS = 128;
private static final int GCM_IV_LENGTH_BYTES = 12;
private static final int AES_KEY_LENGTH_BYTES = 32;
private static final String TEST_OBFUSCATION_KEY = "4ERbfREmnh82jvK5QaXOv8jZ3OQq9hKg5o/Hbb3l9bk=";
SDKZero Certificate Pinning
The SDK does not implement certificate pinning. The OkHttpClient builder creates a standard client without certificatePinner(). Combined with the hardcoded AES key, a standard MITM proxy with a user-installed CA certificate can capture and decrypt all Persona telemetry from any app that embeds the SDK.
Primary source Decompiled from Persona SDK network-core-2.35.2.aar | jadx 1.5.5 | 2026-03-31
| File | network-core-2.35.2.aar → NetworkCoreModule.java, lines 185–227 |
| SHA-256 | df16712972d5d19d6a71da68aa9fa912257b98c0dbac6c03698fca489b729126 |
| What to look for | The okhttpClient() method builds an OkHttpClient without calling certificatePinner(). The builder chain is: addNetworkInterceptor → readTimeout → writeTimeout → connectTimeout → addInterceptor (loop) → build(). No pinning step exists. |
| Reproduce | jadx -d out persona-wallet.apk && grep -rn "certificatePinner\|CertificatePinner" out/ – returns zero results |
Decompiled source (lines 185–227, abbreviated):
public final OkHttpClient okhttpClient(...) {
OkHttpClient.Builder builderAddNetworkInterceptor =
new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() 💬);
TimeUnit timeUnit = TimeUnit.MINUTES;
OkHttpClient.Builder builderConnectTimeout = builderAddNetworkInterceptor
.readTimeout(1L, timeUnit)
.writeTimeout(1L, timeUnit)
.connectTimeout(1L, timeUnit);
Iterator it = set.iterator();
while (it.hasNext()) {
builderConnectTimeout.addInterceptor((Interceptor) it.next());
}
return builderConnectTimeout.build();
// No certificatePinner() call anywhere in this chain.
}
SDKSeven Simultaneous Analytics Services
A user going through Persona verification is tracked by seven analytics services at the same time:
| Service | Platform | Detail |
|---|---|---|
| Persona Telemetry | Android + Web | AES-encrypted events to tg.withpersona.com, 15 event types |
| Sentry (3 projects) | Android + Web + Marketing | 100% session tracing, user interaction tracking, view hierarchy capture |
| Amplitude | Web | Product analytics, behavioral tracking, conversion funnels |
| Datadog RUM | Web | Real User Monitoring, page loads, interactions, network requests |
| FingerprintJS v3.3.0 | Web | Device fingerprinting, contains ad network tracking URLs |
| Mixpanel | Android | Mobile product analytics |
| Firebase Analytics | Android | Google analytics integration |
The Android SDK’s Sentry configuration sets io.sentry.traces.sample-rate = 1 (100% of sessions), io.sentry.traces.user-interaction.enable = true, and io.sentry.attach-view-hierarchy = true. Every user session is fully traced with interaction recording and UI hierarchy capture.
Primary source AndroidManifest.xml metadata from Persona Wallet APK v1.14.0 | jadx 1.5.5 | 2026-03-31
| Source | Decompiled AndroidManifest.xml elements |
| APK package | com.withpersona.app.reusablepersonas v1.14.0 |
| Sentry DSN | ad039950...@o175220.ingest.us.sentry.io/4506939573993472 |
| Reproduce | jadx -d out persona-wallet.apk && grep -E "sentry|sample-rate|user-interaction|attach-view" out/resources/AndroidManifest.xml |
Manifest entries:
io.sentry.dsn = https://ad039950...@o175220.ingest.us.sentry.io/4506939573993472
io.sentry.traces.sample-rate = 1 // 100% of sessions traced
io.sentry.traces.user-interaction.enable = true // taps, clicks, gestures
io.sentry.attach-view-hierarchy = true // full UI tree on errors
Sentry integration classes found in decompiled bytecode:
ActivityLifecycleIntegration - tracks activity start/stop/resume/pause
FragmentLifecycleIntegration - tracks fragment lifecycle
UserInteractionIntegration - captures user taps and gestures
NetworkBreadcrumbsIntegration - logs network connectivity changes
ViewHierarchyEventProcessor - captures view hierarchy snapshots
io.sentry.android.replay.* - session replay (record and replay user sessions)
Primary source Mixpanel and Firebase classes from Persona Wallet APK v1.14.0 | jadx 1.5.5 | 2026-03-31
| Source | Decompiled class files and .properties files from APK |
| APK package | com.withpersona.app.reusablepersonas v1.14.0 |
| Reproduce (Mixpanel) | jadx -d out persona-wallet.apk && find out/ -path "*mx_com.mixpanel*" -name "*.java" | wc -l |
| Reproduce (Firebase) | jadx -d out persona-wallet.apk && find out/ -name "firebase-*.properties" |
Mixpanel SDK (repackaged as mx_com.mixpanel.android.mpmetrics):
Key classes found:
mx_com.mixpanel.android.mpmetrics.MixpanelAPI
mx_com.mixpanel.android.mpmetrics.AnalyticsMessages
mx_com.mixpanel.android.mpmetrics.MixpanelActivityLifecycleCallbacks
mx_com.mixpanel.android.mpmetrics.PersistentIdentity
mx_com.mixpanel.android.mpmetrics.SystemInformation
20+ files total. mx_com prefix = repackaged/embedded build.
SystemInformation collects:
- Device model, OS version, screen dimensions
- Mobile carrier name
- Bluetooth status
- NFC status
Firebase / Google Data Transport:
firebase-annotations.properties
firebase-components.properties
firebase-encoders-json.properties
com.google.android.datatransport.cct.internal.ClientInfo
Firebase component registrars loaded at startup
SDKSilent Network Authentication via Vonage
The SDK can silently verify a user’s phone number through the mobile carrier with zero user interaction. The PhoneNumberSna component uses Vonage (Ericsson subsidiary) to make an HTTP request over the device’s cellular connection. The carrier intercepts the request and verifies that the SIM card’s phone number matches the number encoded in the URL. The request follows up to 10 redirects through carrier authentication infrastructure. Results are auto-submitted to Persona’s backend with countdown=0, meaning the verification happens instantly. The user never sees, touches, or approves the carrier-level verification.
From the decompiled source: the PhoneNumberSnaComponent implements AutoSubmitableComponent. When verification completes, UiState.Displaying.AutoSubmit fires with countdown=0 and the form is submitted immediately.
Primary source Decompiled from Persona SDK sna-impl-2.35.2.aar | jadx 1.5.5 | 2026-03-31
| File | sna-impl-2.35.2.aar → VonageSnaClient.java (59 lines) |
| SHA-256 | 137a1d8aa0d77282bed76ec51b9851a24c554b429d36b7f3b7e4ba877f7766fb |
| APK package | com.withpersona.app.reusablepersonas v1.14.0 |
| Module files | VonageSnaClient.java, VonageSnaClientFactory.java, VonageSnaResponse.java, GeneratedJsonAdapter.java (4 files total) |
| Reproduce | jadx -d out persona-wallet.apk && grep -rn "VGCellularRequestClient\|startCellularGetRequest" out/ |
Decompiled source (key methods):
public VonageSnaClient(Context context, SilentNetworkAuthConfig config, Moshi moshi) {
this.config = config;
this.moshi = moshi;
VGCellularRequestClient.Companion.initializeSdk(context);
}
public SnaClient.Response performSilentNetworkAuth() throws Exception {
if (!SnaUtils.INSTANCE.isValidSnaCheckUrl(this.config.getCheckUrl())) {
return new SnaClient.Response.Error(...);
}
JSONObject result = VGCellularRequestClient.Companion.getInstance()
.startCellularGetRequest(
new VGCellularRequestParameters(
this.config.getCheckUrl(), // URL from Persona server
MapsKt.emptyMap(), // headers
MapsKt.emptyMap(), // query params
this.config.getMaxRedirects() // follows up to N carrier redirects
), false);
// Carrier validates SIM -> returns success/failure JSON
}
SDKWebRTC Live Video Streaming
During selfie capture, the SDK streams live video to webrtc-consumer.withpersona.com via WebRTC TURN connections. The server receives continuous video, not just captured frames. An optional recordAudio flag enables audio recording during the stream. The SDK’s VideoCaptureMethod priority prefers Stream (WebRTC) first, falling back to Upload only if streaming is unavailable.
On-device face detection uses Google ML Kit to extract: bounding box, Euler angles (pitch, rotation, tilt), smile probability, left/right eye open probability, 10 face landmarks, and 15 face contour types. A 3×3 brightness grid divides the face region into 9 zones and computes per-zone luminance to detect flat paper or screen reflections. All anti-spoofing analysis is delegated to the server. The terms anti_spoof, active_liveness, passive_liveness, and depth do not appear in the SDK codebase.
SDKNFC Passport Chip Reading
The SDK implements ICAO 9303 BAC/PACE protocol for reading e-passport chips. Data groups read from the chip:
| Data Group | Contents |
|---|---|
| DG1 (MRZ) | Name, nationality, document number, date of birth, expiry, sex |
| DG2 (Facial Photo) | JPEG2000/JPEG facial biometric photo stored on the chip |
| DG14 (Chip Auth Keys) | ChipAuthenticationPublicKeyInfo, ChipAuthenticationInfo |
| SOD (Security Object) | Signed hashes of all data groups for tamper detection |
The data groups are server-configurable via PassportNfcReaderConfig.enabledDataGroups. The server can request additional data groups at any time. Terminal Authentication (EAC-TA) is not implemented, meaning the passport chip cannot verify whether Persona is an authorized reader. Chip Authentication is supported but the absence of Terminal Authentication means the chip has no way to refuse data extraction.
43 Verification Types Across 14 Countries
The web inquiry bundle contains the complete Persona platform entity registry, expanding well beyond the February 2026 leak. 15 verification types were not present in the leaked source or the Android SDK:
| Type | System | Country |
|---|---|---|
| VerificationDigitalIdWorldId | Worldcoin/World ID (iris biometric) | Global |
| VerificationDigitalIdFranceIdentite | France Identite | France |
| VerificationDigitalIdEDoApp | eDoApp digital identity | Estonia |
| VerificationDigitalIdFinnishTrustNetwork | Finnish Trust Network | Finland |
| VerificationDigitalIdIdin | iDIN (banking ID) | Netherlands |
| VerificationDigitalIdItsMe | itsme digital ID | Belgium/Netherlands |
| VerificationDigitalIdMitId | MitID (national ID) | Denmark |
| VerificationDigitalIdOneId | OneID digital identity | United Kingdom |
| VerificationDigitalIdSwedishBankId | Swedish BankID | Sweden |
| VerificationDigitalIdConnectId | ConnectID | Australia |
| VerificationCertificateKorea | Korean certificate verification | South Korea |
| VerificationBankPennydrop | Bank account micro-deposit | Universal |
| VerificationQesInfocert | Qualified Electronic Signature (eIDAS) | EU |
| VerificationVerifiableCredential | W3C Verifiable Credential | Universal |
| VerificationMdoc | Mobile driver’s license (ISO 18013-5) | US states |
Persona now has integration with 15 digital identity systems across 14 countries, including Worldcoin’s iris biometric World ID. The platform also supports Aadhaar (India, 1.4 billion enrolled), Serpro (Brazil, 220 million), PhilSys (Philippines, 92 million), Singpass (Singapore), and ECBSV (US SSA Social Security number verification).
47 Report Types with 16 Third-Party Integrations
The web bundle reveals 47 distinct report types. The following third-party data integrations were not previously documented:
| Integration | Company | Data |
|---|---|---|
| ReportChainalysisAddressScreening | Chainalysis | Crypto wallet sanctions screening |
| ReportCoinbaseCheckCryptoRisk | Coinbase | Cryptocurrency transaction risk |
| ReportEquifaxOneview | Equifax | Credit bureau data |
| ReportFinraBrokerCheck | FINRA | Securities broker/advisor check |
| ReportSecActionLookup | SEC | Securities enforcement actions |
| ReportSentilinkApplicationRisk | Sentilink | Synthetic identity fraud detection |
| ReportTrmWalletScreening | TRM Labs | Crypto compliance screening |
| ReportMxAccount | MX | Financial account aggregation |
| ReportKyckrBusinessLookup | Kyckr | Global company registry data |
| ReportMiddeskBusinessLookup | Middesk | Business entity verification |
Persona connects to Chainalysis and TRM Labs for crypto wallet screening, Equifax for credit bureau data, FINRA and the SEC for securities enforcement, Sentilink for synthetic identity detection, MX for financial account aggregation, and Kyckr for global company registries. The platform processes far more than identity verification.
26 Government ID Types
The SDK supports 26 distinct government ID types, including country-specific documents: Japan MyNumber Card (myn), Singapore/Malaysia NRIC (nric), Philippines OFWID (ofw), Philippines UMID (umid), Philippines NBI Clearance (nbi), and India PAN Card (pan). US and Canadian driver’s licenses are parsed via an AAMVA PDF417 barcode reader that extracts 13 fields: first name, middle name, last name, sex, street address, city, state, postal code, ID number, issue date, expiration date, date of birth, and country.
Roblox: FacialAgeEstimation Module
Decompilation of the Roblox APK v2.714.1091 confirms the full Persona SDK is embedded under the internal module name com.roblox.universalapp.facialageestimation. The integration bridge at com.roblox.client.personasdk passes verification results through a JNI (Java Native Interface) bridge directly into Roblox’s C++ game engine. The DisablePauseSessionInPersonaFlow feature flag prevents users from pausing or backgrounding the app during verification, ensuring the continuous WebRTC video stream is not interrupted.
Roblox’s manifest includes permissions for camera, audio recording, NFC, biometric authentication, fingerprint, Bluetooth, and contacts (READ_CONTACTS, unusual for a game). The full 21-endpoint API surface and all surveillance capabilities documented above are available inside Roblox, an app where 67% of users are under 16.
SDKServer-Driven Architecture
The Persona client is a stateless renderer. The server dictates every step, every component, and every transition via 38 UI component types and 12 inquiry states. There is no hardcoded step sequence in the SDK. The server can dynamically insert, reorder, or skip any step for any user based on risk scoring, template configuration, or real-time decisions. This means the verification pipeline experienced by one user can be completely different from another, and users have no way to predict or audit what data collection steps will be triggered.
SDKAnti-Tampering and Debugger Detection
Every API request is signed with four obfuscated headers: NHMJLNRS (HMAC-SHA256 hash of JWT sub, timestamp, and request body), STPBWSBB (Unix timestamp), DNLGNZLZ (secondary hash incorporating header values), and TLJLGGDG (list of signed header names). A fifth header, VTDGJLGG, reports whether a debugger is attached to the process via Debug.isDebuggerConnected(). This flag is included in the signed header set, making it tamper-evident. Google Play Integrity verification runs with up to 5 retries and a 1-second delay between attempts.
All Analytics Keys Exposed and Active
The following keys are embedded in publicly served client-side code. All were confirmed active through testing:
| Service | Key/Identifier | Status |
|---|---|---|
| AES Telemetry | 4ERbfREmnh82jvK5QaXOv8jZ3OQq9hKg5o/Hbb3l9bk= |
Active (decryption verified) |
| Amplitude API | 8f9fcc63055c35a7ba867e38e0738939 |
Active (ingested test event) |
| Sentry Web | DSN key 233a1fa0... / project 5579484 |
Active |
| Sentry Marketing | DSN key e4d8556f... / project 4508775074496512 |
Active |
| Sentry Android | DSN key ad039950... / project 4506939573993472 |
Active |
| SDK Token | F4SGT2MWWFC6NH5CUPY4LF2LVY |
Active |
Sentry organization ID is o175220. All three Sentry DSNs map to the same organization. The web inquiry bundle also contains Datadog RUM application ID and client token, and an Osano CMP (consent management) account identifier.
Browser-Side Age and Gender Estimation
The web verification flow loads faceapi.js (1.3MB), which includes an age_gender_model for client-side age and gender estimation. This ML model runs in the browser before any data is sent to Persona’s servers. The document OCR module (microblink.js, 91KB) performs MRZ reading directly in the browser.
{💬|⚡|🔥} **What’s your take?**
Share your thoughts in the comments below!
#️⃣ **#Surveillance #Findings #Age #Verification #Mass #Surveillance #Infrastructure**
🕒 **Posted on**: 1775475506
🌟 **Want more?** Click here for more info! 🌟
