年龄验证作为大规模监控基础设施
Age Verification as Mass Surveillance Infrastructure

原始链接: https://tboteproject.com/surveillancefindings/

## Persona 钱包 SDK:揭露广泛的监控能力 对 Persona 钱包 APK (v1.14.0) 及其相关网络资源进行的独立分析,揭示了一系列广泛的监控行为。该 SDK 集成到 Roblox 等应用程序中,缺乏证书固定,允许通过 MITM 代理轻松拦截数据。 关键的是,**所有遥测数据都使用硬编码的、公开可用的 AES-256 密钥进行“加密”**,使得加密失效。 Persona 在 **七个分析服务** 中跟踪用户——包括 Sentry(100% 会话跟踪)、Amplitude、Datadog 和 Mixpanel——收集详细的行为和交互数据。该平台支持 **14 个国家/地区的 43 种验证类型**,包括 Worldcoin 的虹膜扫描等生物识别数据,并与众多第三方数据提供商集成以进行风险评估(Chainalysis、Equifax 等)。 该 SDK 使用 WebRTC 进行自拍验证期间的实时视频流,执行设备端面部分析,并可以通过 Vonage 静默验证电话号码。 它还可以读取电子护照芯片并支持 26 种政府身份证类型。 Persona 采用 **服务器驱动架构**,动态调整每个用户的验证流程,并包括防篡改措施和调试器检测。 最后,在数据传输*之前*执行浏览器端的年龄和性别估计。

一场 Hacker News 的讨论围绕着在线年龄验证系统的影响,与一篇关于它们可能成为大规模监控基础设施的文章相关(tboteproject.com)。 核心争论在于平衡在线安全——特别是对儿童的保护——与隐私问题。一些人认为年龄验证是遏制社交媒体和大型科技公司危害的必要步骤(得到民意调查的支持,民调倾向于对儿童进行限制),而另一些人则认为这是一种越权行为,会带来深远的影响。 评论员指出,年龄验证并不等同于简单地禁止未成年人,家长控制是更可取的解决方案。一个主要担忧是政府监控的扩大,许多人认为公众尚未完全意识到这些系统会追踪和监控在线活动的程度。 讨论承认互联网格局正在发生变化,越来越多的非技术用户需要“保护”,但警告要提防“保姆国家”和潜在的专制控制。
相关文章

原文

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 {"events": <json_array>}, encrypts with AES-256-GCM using a 12-byte random IV, then Base64-encodes the ciphertext and sends it as {"e": "<base64_blob>"}. 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
Filetracking-events-2.35.2.aar → TrackingEventUtilsKt.java, line 22
SHA-256048e9971ef932d8dac568b5d5b271e4cacaa443f32049a8dff519bd2dc1154d6
APK packagecom.withpersona.app.reusablepersonas v1.14.0 (version code 1001380, target SDK 35)
APK manifest SHA-2560daf3d5292e143d4a636e8575810849128e77f491d814d5e058ce68947d16fc1
Reproducejadx -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
Filenetwork-core-2.35.2.aar → NetworkCoreModule.java, lines 185–227
SHA-256df16712972d5d19d6a71da68aa9fa912257b98c0dbac6c03698fca489b729126
What to look forThe okhttpClient() method builds an OkHttpClient without calling certificatePinner(). The builder chain is: addNetworkInterceptor → readTimeout → writeTimeout → connectTimeout → addInterceptor (loop) → build(). No pinning step exists.
Reproducejadx -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() {
            public final Response intercept(Interceptor.Chain chain) {
                // ... adds Persona-Version, Persona-Device-*, VTDGJLGG headers ...
                return chain.proceed(builderHeader3.build());
            }
        });
    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:

ServicePlatformDetail
Persona TelemetryAndroid + WebAES-encrypted events to tg.withpersona.com, 15 event types
Sentry (3 projects)Android + Web + Marketing100% session tracing, user interaction tracking, view hierarchy capture
AmplitudeWebProduct analytics, behavioral tracking, conversion funnels
Datadog RUMWebReal User Monitoring, page loads, interactions, network requests
FingerprintJS v3.3.0WebDevice fingerprinting, contains ad network tracking URLs
MixpanelAndroidMobile product analytics
Firebase AnalyticsAndroidGoogle 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
SourceDecompiled AndroidManifest.xml <meta-data> elements
APK packagecom.withpersona.app.reusablepersonas v1.14.0
Sentry DSN[email protected]/4506939573993472
Reproducejadx -d out persona-wallet.apk && grep -E "sentry|sample-rate|user-interaction|attach-view" out/resources/AndroidManifest.xml

Manifest entries:

io.sentry.dsn = https://[email protected]/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
SourceDecompiled class files and .properties files from APK
APK packagecom.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
Filesna-impl-2.35.2.aar → VonageSnaClient.java (59 lines)
SHA-256137a1d8aa0d77282bed76ec51b9851a24c554b429d36b7f3b7e4ba877f7766fb
APK packagecom.withpersona.app.reusablepersonas v1.14.0
Module filesVonageSnaClient.java, VonageSnaClientFactory.java, VonageSnaResponse.java, GeneratedJsonAdapter.java (4 files total)
Reproducejadx -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 3x3 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 GroupContents
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:

TypeSystemCountry
VerificationDigitalIdWorldIdWorldcoin/World ID (iris biometric)Global
VerificationDigitalIdFranceIdentiteFrance IdentiteFrance
VerificationDigitalIdEDoAppeDoApp digital identityEstonia
VerificationDigitalIdFinnishTrustNetworkFinnish Trust NetworkFinland
VerificationDigitalIdIdiniDIN (banking ID)Netherlands
VerificationDigitalIdItsMeitsme digital IDBelgium/Netherlands
VerificationDigitalIdMitIdMitID (national ID)Denmark
VerificationDigitalIdOneIdOneID digital identityUnited Kingdom
VerificationDigitalIdSwedishBankIdSwedish BankIDSweden
VerificationDigitalIdConnectIdConnectIDAustralia
VerificationCertificateKoreaKorean certificate verificationSouth Korea
VerificationBankPennydropBank account micro-depositUniversal
VerificationQesInfocertQualified Electronic Signature (eIDAS)EU
VerificationVerifiableCredentialW3C Verifiable CredentialUniversal
VerificationMdocMobile 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:

IntegrationCompanyData
ReportChainalysisAddressScreeningChainalysisCrypto wallet sanctions screening
ReportCoinbaseCheckCryptoRiskCoinbaseCryptocurrency transaction risk
ReportEquifaxOneviewEquifaxCredit bureau data
ReportFinraBrokerCheckFINRASecurities broker/advisor check
ReportSecActionLookupSECSecurities enforcement actions
ReportSentilinkApplicationRiskSentilinkSynthetic identity fraud detection
ReportTrmWalletScreeningTRM LabsCrypto compliance screening
ReportMxAccountMXFinancial account aggregation
ReportKyckrBusinessLookupKyckrGlobal company registry data
ReportMiddeskBusinessLookupMiddeskBusiness 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:

ServiceKey/IdentifierStatus
AES Telemetry4ERbfREmnh82jvK5QaXOv8jZ3OQq9hKg5o/Hbb3l9bk=Active (decryption verified)
Amplitude API8f9fcc63055c35a7ba867e38e0738939Active (ingested test event)
Sentry WebDSN key 233a1fa0... / project 5579484Active
Sentry MarketingDSN key e4d8556f... / project 4508775074496512Active
Sentry AndroidDSN key ad039950... / project 4506939573993472Active
SDK TokenF4SGT2MWWFC6NH5CUPY4LF2LVYActive

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.

联系我们 contact @ memedata.com