在申请微信支付、支付宝支付的流程中,都要求提交 APK 的签名。
如何获得签名呢?他们都提供了一个 Gen_Signagure_Android.apk,说是安装到安卓手机上,就能够读取第三方应用 APK 的签名。但是,这个 apk 有的手机出于安全控制不允许安装,比如小米手机就安装失败。
那么有没有什么其他的方法获得签名呢?
微信官方的devtools也能从APK读取签名指纹,但流程异常复杂,非常麻烦。有人建议用 jadx,这是个将 APK 包反编译得到 java 代码的强大工具。
为了简单的获取指纹,而安装这些强大而复杂的工具,有点杀鸡用牛刀,过于麻烦了。可以寻找更加简单易用的方法。
经过研究,发现他们所验证的这个32个字节的签名,其实就是 APK 签名证书的 MD5 指纹。
使用命令
keytool -list -v -keystore xxx.keystore
keytool -printcert -jarfile xxx.apk
都可以打印出签名信息,但是,我们注意到这里并没有打印出 MD5 信息。

经过调查,发现是 java8 以后的 keytool 版本已经去掉了 MD5 支持,因为发现 MD5 并不严谨,存在安全问题。虽然MD5已经过时了,但这些申请流程中,出于历史原因还在使用。
既然能够计算出 SHA1 和 SHA256 指纹,是不是也能够有办法计算出 MD5 指纹呢?让我们试试看。
我们都知道 APK 和 IPA 文件格式,其实就是个 zip 文件。我们把 APK 解压,将会得到 META-INF/CERT.RSA。这个文件是包含了签名证书 以及 签名信息。
使用命令:keytool -printcert -file CERT.RSA
我们也可以打印出同样的签名信息来,只不过同样只显示 SHA1 和 SHA256,没有显示 MD5。
那么,能不能通过这个 CERT.RSA 文件获得 MD5 指纹呢?答案是肯定的。
使用 openssl 这个超级牛X 强大的密码工具箱,我们可以从 CERT.RSA 文件中提取出 签名证书(也就是PKI证书的公钥),并提取出指纹。
经过推敲,用如下的一系列命令,就能够打印出签名证书的指纹。
方法一:直接读取 keystore 的证书:
keytool -exportcert -keystore xxx.keystore | openssl dgst -md5
方法二,从 APK 包中提取证书:

最后,为了便于使用,我把这一系列命令,封装为一个 python 命令行程序,并发布到 pypi 上。在 Mac 或者 Linux 电脑上,通过 pip 安装就可以直接使用了。
python3 -m pip install apk-signature
apk-signature myapp.apk
效果如下:

这个命令行工具因为用到了mkdir, unzip, rm 这些命令,在Windows 上不能直接用,不过参考上面的这些命令,安装 windows 版本的 openssl,应该不难写个 bat 来完成这件事情。
全文完。