夜雨聆风学习资料网

ARTICLE · 1304979

怎么确认下载的 APK 没被改过:三种验签方法

怎么确认下载的 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。

这也是为什么这篇花了大半篇幅讲"去哪找官方指纹",而不是讲怎么跑命令。

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料