13 KiB
Binary Artifact Analysis
Tangem Android Wallet — Official Release APK vs. Build from Audited Source
| Subject | Comparison of Tangem's official v6.1.2 release APK against a build produced from the audited source |
| Companion to | AUDIT.md — static source review of commit 358144ee61a |
| Analysis date | 17 August 2026 |
| Analysis type | Static binary inspection (manifest, signing, package structure). No decompilation, no execution |
| Objective | Determine whether the officially distributed binary can be confirmed to originate from the audited source |
1. Executive Summary
The official APK cannot be verified as originating from the audited source, and no available technique would allow it. This is a structural property of how Tangem builds and hardens its release artifact, not a deficiency of this analysis or an indication of wrongdoing.
What can be established is weaker but not worthless: every externally observable property of the official binary that could be compared against a build from the audited source matches. That rules out crude substitution or repackaging. It does not, and cannot, rule out a targeted modification concealed beneath the protection layer.
The comparison additionally surfaced two factual errors in AUDIT.md, both of which overstate the security posture of the shipped application. They are recorded in §5 and have been corrected in the audit report.
Verdict
UNVERIFIABLE — CONSISTENT. Provenance of the official binary cannot be established by any means available to a third party. All comparable attributes are consistent with the audited source. Absence of contradiction is not evidence of correspondence.
2. Artifacts Compared
| Official release | Build from audited source | |
|---|---|---|
| Filename | app-release-protected-1819-6.1.2.apk |
app-google-debug.apk |
| Origin | github.com/tangem/tangem-app-android releases, tag v6.1.2 |
./gradlew :app:assembleGoogleDebug at 358144ee61a |
| Size | 134,544,995 bytes | 176,908,283 bytes |
| SHA-256 | 6ed4ac317f2f5bdccd5bb1cec9d6733207261e6b4f823a4de883e646872166a1 |
5df4c81755bc423ed39e92499830d789b309561211c62091585fa9038adfe5cd |
| Package | com.tangem.wallet |
com.tangem.wallet.debug |
| Version | 6.1.2 (code 1819) |
1.0.0-SNAPSHOT (code 1) |
| Build type | release, minified, DexProtector-hardened |
debug, unminified, unprotected |
| Signer | L=Zug, O=Tangem AG |
Committed dummy debug keystore |
| Archive entry dates | 2026-08-13 | 2026-08-17 |
The size difference is expected and runs counter to intuition: the debug build is larger because it is not minified by R8, despite carrying no protection layer.
3. Why Provenance Cannot Be Established
Four independent obstacles apply. Any one alone would be sufficient to defeat verification.
3.1 The release is commercially hardened
The official APK ships Licel DexProtector:
lib/arm64-v8a/libdexprotector.so 446,117 bytes
lib/armeabi-v7a/libdexprotector.so 394,517 bytes
assets/assets.dat 229,499 bytes
assets/ict.dat 10,853 bytes
DexProtector encrypts and obfuscates DEX bytecode. The transformation is keyed per build and is explicitly designed to prevent the analysis that verification would require. Comparing bytecode between the two artifacts is not merely impractical — it is precluded by design.
3.2 The compared artifacts are different build types
The official build passes through R8 minification, obfuscation, and resource shrinking. The reference build does not. Class names, method signatures, and the DEX file layout diverge for reasons entirely unrelated to source content: 54 DEX files versus 68.
3.3 The source tree does not correspond to the released version
The repository carries no version of its own. AppConfig.versionCode is 1, and
VersionNameProvider derives the name from the current git branch, falling back to
1.0.0-SNAPSHOT. Both values are injected by CI via -PversionCode / -PversionName.
Consequently nothing in the tree identifies which release a given commit produced. The evidence indicates the audited commit is newer than v6.1.2: archive entries in the official APK are dated 2026-08-13, whereas the audited commits are dated 2026-08-14. The two artifacts therefore do not represent the same source state, and could not be expected to match even in principle.
3.4 The build is not reproducible by a third party
Independent of the above, an outside party cannot reconstruct the official build:
core/ui/ds-tokensis a submodule gitlink with no.gitmodulesmapping anywhere in the repository's 16,087-commit history, so it cannot be resolved (see AUDIT.md O-3)- All third-party API keys in
config_prod.jsonarePLACEHOLDER; the official build embeds real values, compiled in at build time byGenerateEnvironmentConfigTask - Release signing requires a keystore that is deliberately not published
Tangem publishes no reproducible-build attestation, and the artifact's construction is incompatible with one.
4. Consistency Findings
The following were compared and match. Each is a property an attacker repackaging or substituting the application would find difficult to preserve.
4.1 Permission set — identical
Both APKs declare exactly 23 permissions. After normalising the debug package prefix, a sorted diff of the two sets is empty.
This is the most informative single result. The comparison was made against a binary built from the audited source, so any permission present in Tangem's distributed build but not produced by that source would be a direct indicator of divergence. There is none.
Both sets also exclude location and microphone permissions, confirming that the
tools:node="remove" stripping described in AUDIT.md §3.6 is genuine and survives into the shipped
artifact.
4.2 Native libraries — identical, plus protection runtime
| Count | Detail | |
|---|---|---|
| Build from audited source | 14 | see below |
| Official release | 16 | the same 14, plus libdexprotector.so and libalice.so |
libTrustWalletCore.so · libsecp256k1-jni.so · libTrezorCrypto.so · libargon2.so
libblst.so · libsqlcipher.so · libuniffi_yttrium.so · libtoolChecker.so
libtensorflowlite_jni.so · libbarhopper_v3.so · libjnidispatch.so
libimage_processing_util_jni.so · libandroidx.graphics.path.so · libsurface_util_jni.so
The audited source reproduces the official release's native library set exactly. The only additions
are the protection layer. libalice.so was not independently identified; it appears only in the
protected build alongside libdexprotector.so, which is consistent with it forming part of the
DexProtector runtime, but this was not confirmed.
4.3 Build configuration and identity
targetSdkVersion36 andcompileSdkVersion36 in both, matching the source configuration- Package
com.tangem.wallet(reference build carries the expected.debugsuffix) - Official APK signed by
L=Zug, O=Tangem AG, certificate SHA-256e0fe798927cf94709b9d439c9ce728a90a2891698cdff31a4c4d63435b946748, coherent with Tangem AG's registration in Zug, Switzerland
Note on the signing certificate: this establishes only that the holder of that key signed the artifact. It is a first-observation baseline, not an identity proof. Its value is comparative — future releases can be checked against this digest to detect a signing-key change.
5. Discrepancies Against AUDIT.md
Both findings below arise from the same root cause: the audit examined the source tree, and its conclusions were phrased as though they described the shipped application. Neither indicates malicious behaviour. Both have been corrected in AUDIT.md.
D-1 — Permission set understated (AUDIT.md §3.6)
The audit lists nine permissions as the "complete permission set across all manifests" and states
that external storage and RECEIVE_BOOT_COMPLETED are absent.
The nine are accurate for the hand-written manifests (app/src/main/ and app/src/huawei/), which
were verified to declare exactly that set. However the merged manifest — in Tangem's release and
in the build from the audited source alike — contains 23. The fourteen not accounted for:
READ_EXTERNAL_STORAGE · WRITE_EXTERNAL_STORAGE · WRITE_SETTINGS
RECEIVE_BOOT_COMPLETED · FOREGROUND_SERVICE · USE_FINGERPRINT · POST_NOTIFICATIONS
BIND_GET_INSTALL_REFERRER_SERVICE · ACCESS_ADSERVICES_ATTRIBUTION
ACCESS_ADSERVICES_AD_ID · c2dm.RECEIVE · DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION
com.samsung.android.mapsagent.permission.READ_APP_INFO
com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA
These are introduced by manifest merging from bundled third-party SDKs — the same mechanism the
audit correctly credits Tangem for defending against with tools:node="remove". The characterisation
"permissions MINIMISED" and "the set contains nothing a wallet does not require" is not supported by
the artifact as shipped. WRITE_SETTINGS and RECEIVE_BOOT_COMPLETED in particular warrant
explanation rather than omission.
D-2 — "No native code" is true of the repository, false of the application (AUDIT.md §3.1)
The audit states "No .so libraries, no JNI, no NDK build inputs," and answers No to the
methodology question "Does it ship native binaries or opaque blobs?"
This is correct for the source tree — no .so file is committed. It is incorrect for the
application, which bundles fourteen native libraries even in the unprotected build (§4.2).
The distinction is material because several are security-critical: libTrustWalletCore.so,
libsecp256k1-jni.so, and libTrezorCrypto.so perform key derivation and signing; libargon2.so
provides key-stretching; libsqlcipher.so provides at-rest database encryption. These arrive
through the pre-built Maven dependencies that AUDIT.md §6.1 places outside the review's scope, so
the audit's scope statement does technically cover them. But a reader reaching "ships native
binaries: No" in the summary table will draw the opposite conclusion about the application they
are installing.
6. What This Analysis Does and Does Not Establish
Does establish:
- The official v6.1.2 APK is signed by Tangem AG and structured as the audited source predicts
- Its permission surface and native library set are exactly reproduced by building the audited source, with no unexplained additions
- Gross tampering — repackaging, permission injection, substitution of a different application — is ruled out
- The privacy hardening claimed in AUDIT.md §3.6 is present in the distributed artifact
Does not establish:
- That the official APK was built from the audited source, or from any particular source
- That the DEX bytecode is free of modification. DexProtector renders this unexaminable
- Anything about the pre-built Tangem SDKs, which perform mnemonic encryption and at-rest key storage and remain unreviewed (AUDIT.md §6.1)
- That any future release will share these properties
A user installing the official APK is extending trust to Tangem's build pipeline and signing key. Nothing available to a third party can substitute for that trust. This analysis narrows the range of undetected substitutions; it does not eliminate it.
7. Method
All inspection used Android SDK build-tools 36.0.0.
# Manifest, version, permissions
aapt2 dump badging <apk>
# Signing certificate
apksigner verify --print-certs <apk>
# Package structure, native libraries, DEX count
unzip -l <apk>
Permission sets were extracted, normalised for the debug package prefix, sorted, and compared with
diff. Native library sets were compared with comm after stripping ABI directory components.
No decompilation, deobfuscation, or execution was performed. No attempt was made to defeat DexProtector.
8. Limitations
- Static inspection of archive metadata only. Application behaviour was not observed.
- Version mismatch. The reference build derives from a commit dated one day after the official artifact. Differences attributable to intervening source changes cannot be distinguished from differences attributable to anything else.
- Reference build was not fully faithful. It was produced with
verifyDesignTokensskipped (theds-tokenssubmodule is unresolvable) and withPLACEHOLDERAPI keys. Neither affects the manifest or native library comparisons on which the findings rest. - Single point in time. Applies to v6.1.2 build 1819 only. Re-verification is required for every subsequent release, and the certificate digest in §4.3 is the recommended anchor.
Binary analysis of app-release-protected-1819-6.1.2.apk against a reference build of commit
358144ee61a. Companion to AUDIT.md; findings D-1 and D-2 have been applied to that report.