ARTICLE · 1304979
怎么确认下载的 APK 没被改过:三种验签方法
从一个不熟的网站下了个 APK,装之前想确认它没被动过手脚。
这件事其实有标准答案,而且不难。难的是大部分人第一次听到"验签"两个字,就把它归到"程序员才需要懂"那一类里去了。
其实不用。你只需要理解一件事:改一个字节,签名就会变。剩下的都是工具的事。
一、签名在保护什么
开发者手里有一对密钥。私钥只有他自己有,用来签名;公钥打包在 APK 里,谁都能看到。
签名的时候,他对 APK 内容算一个哈希,用私钥把这个哈希加密,附进包里。安装的时候,系统用公钥解开,重新算一遍哈希,对不上就拒绝。
所以只要有人动过这个包——加一行代码、换一个图标、塞一个 SDK——签名立刻失效。你不需要读懂代码,也能知道它被改过。
原理到这为止就够了。真正容易出错的是下一步。
假设有人自己生成一对新密钥,把包重新签一遍。这个包也能验签通过,只是签名的人变成了他自己。
也就是说,"验签通过"这件事本身没有意义。有意义的只有一件事:这个签名,是不是开发者官方公布的那一个。
这个区别看着小,实际决定成败。大多数教程教到"用工具验一下,显示 Verifies 就放心了",然后就停了。那一步其实没什么用。
二、三种查法
〔入门〕在手机上看
不用电脑,装个「MT 管理器」就能看(它本身是闭源商业软件,这一点你自己权衡)。
在文件管理器里找到 apk,长按,选「查看」或「APK 信息」,找到签名那一栏,里面会列出 SHA-256 和 MD5。
这能看到签名存不存在,也能对比两个包是不是同一个人签的。
但它给不了你"是不是官方的"这个答案。你还得有个官方指纹来对照,而官方指纹在手机上查不到。所以这个方法适合一个场景:你已经知道自己要什么,只是想确认这次下的和上次那个是不是同一个。
〔进阶〕apksigner
有电脑的话,用官方的 apksigner。它是 Android SDK 里的工具,Google 自己也在用,输出是标准格式,可以直接拿去和官方公布的值对。
不需要装整个 Android Studio,只要 Build-Tools。或者干脆只下 apksigner.jar,用 Java 跑,前提是 Java 9 以上。
apksigner verify --print-certs --verbose 你的应用.apk输出大概是这样:
VerifiesVerified using v1 scheme (JAR signing): trueVerified using v2 scheme (APK Signature Scheme v2): trueVerified using v3 scheme (APK Signature Scheme v3): trueNumber of signers: 1Signer #1 certificate DN: CN=Example Inc, O=Example, C=USSigner #1 certificate SHA-256 digest: 1a2b3c4d5e6f...Signer #1 certificate SHA-1 digest: 0a1b2c3d...Signer #1 certificate MD5 digest: 9f8e7d6c...四行有用,其余可以忽略。

v3 方案(密钥轮换)并非所有 App 都有,很多 App 只有 v1+v2,这是正常现象,不代表有问题。
Windows 上如果不想装 SDK,下个 build-tools 压缩包,解压进 build-tools\<版本号>\,直接跑 apksigner.bat 就行。
〔折腾〕三层一起查
如果这个应用涉及账号、支付或者隐私,多花五分钟值得。

第一层查文件完整性。Windows 用 Get-FileHash .\app.apk -Algorithm SHA256,macOS 或 Linux 用 shasum -a 256 app.apk。下载页给了哈希就比一下,对不上说明传输中坏了,重下。
但别把这一层当成安全。哈希对得上不等于安全,攻击者想改包,顺手把哈希一起改了就是。这一层只防损坏,不防篡改。
第二层查签名指纹,也就是拿 apksigner 的输出,去和开发者官方公布的值比。去哪找,下一节说。
第三层查来源。三个问题:这个包是从哪个域名下的;页面上有没有混着"加速下载""高速通道"之类的第三方按钮(有,说明你可能点错了位置);版本号和官方最新版对不对得上。
三层里,第二层才是决定性的。
三、官方指纹去哪找
这是整套流程里最容易卡住的地方。三个可靠来源。
开发者官网。 不少项目会在官网底部或者「Security」页面列出签名指纹,开源项目尤其常见。
GitHub Release。 正规做法是在 Release 说明里附 APK 的 SHA-256 和证书指纹,讲究一点的还会给 GPG 签名文件。反过来说,如果开发者连这个都不提供,那说明他没把供应链安全当回事,这本身就是个信号。
自己装一份,然后提取。 最笨也最稳:从官方商店或官网装一份,用工具导出它的签名指纹,再拿这个值去比对你从第三方下的包。
第三个办法的好处是,你不需要相信任何人的说法,只需要相信你手机上已经装着的那个东西。
四、三个流传很广的误解
"微信、QQ 传过来会改签名。"
不会。传输过程中文件名可能被改,变成 app(1).apk 这种,但内容不变,签名也不变。如果传完发现签名对不上,那是发送方给你的包本来就被动过,跟传输没关系。
"文件大小一样就是原版。"
大小完全可以一样。替换资源文件、改代码段、再把体积补齐,这些都不难。大小只适合用来快速筛掉"明显没下完"的情况,不能当安全依据。
"应用商店扫过毒就安全。"
杀毒引擎靠特征库吃饭,碰上没有前科的新代码基本无能。而且很多行为压根不算病毒——过度收集信息、静默安装、后台常驻,这些杀毒软件一个都不会报。
签名校验回答的是"这个包是不是开发者本人发的",不是"这个包的行为正不正当"。两个问题,别混在一起。
五、做个记录表
如果你经常折腾应用,建议自己维护一张表。

只记前 8 位。碰撞概率可以忽略,但比完整字符串省事太多。
以后每次下新版本,扫一眼前 8 位对得上就装。开头花半小时建这张表,后面几年都能用。
六、最后
验签这件事,本质上不是"我信不信这个网站"。
是"我手上有没有一个可以跟它比的东西"。
没有基准,验签就是走个过场,看到 Verifies 就放心了,而那行字什么也证明不了。有了基准,你就不需要相信任何站点,包括 APKMirror。
这也是为什么这篇花了大半篇幅讲"去哪找官方指纹",而不是讲怎么跑命令。















































































