项目中需要通过后台上传APK判断合法性,因此用到用PHP获取安卓apk签名来验证,网上搜到的方法一般是通过java的keytool工具来获取。但是对于有些生产环境没有JAVA环境又不能装JAVA环境来说需要另外的方式。方法二将会给出笔者总结的方式。
方法一
所需工具:aapt,Android SDK中的工具,只有一个exe,可以直接运行。
keytool,JDK中的工具,需要安装JDK环境。
需要提供目标应用的apk
1、获取包名
- window运行命令行
- 切换到aapt所在目录
- aapt.ext dump badging 【apk路径】 > 【内容输出到本地文档】
- 打开输出的文档,package: name='com.pakgname.swbg'中的''中间的就是包名。
例如:aapt.exe dump badging C:\Users\Administrator\Desktop\demo-apk-1.0.1.8791.apk > C:\Users\Administrator\Desktop\1.txt
获取到的包名是com.pakgname.swbg
2、获取签名
- 将原有的应用扩展名(后缀)改为.rar
- 修改后解压缩
- 打开解压后的目录,进入到META-INF文件夹下,找到一个CERT.RSA的文件
- window运行命令行
- 切换到keytool所在目录
- keytool -printcert -file 【.RSA文件的路径】 > 【内容输出到本地文档】
- SHA1:后面的就是签名(哈希)值
例如
keytool -printcert -file C:\Users\Administrator\Desktop\demo-apk-1.0.1.8791\META-INF\CERT.RSA > C:\Users\Administrator\Desktop\2.txt
SHA1: 56:BD:02:6B:9D:53:D7:F5:32:B2:BC:BD:BB:34:5B:F1:CD:EF:7F:C0
服务器端,可将命令目录换成对应即可,下面给出PHP中自己封装的方法
获取apk包的签名
/**
* 获取安卓APK包的签名
*
* @param string $filename apk包路径+名称
*
* @return string 检测到签名返回签名 没有检测到 返回空
*/
function getHash($filename)
{
$java = getenv('JAVA_HOME');
if ($java) {
$keytoolpath = $java . '/bin/keytool';
$cmd = "unzip -p {$filename} META-INF/CERT.RSA | {$keytoolpath} -printcert | grep SHA1: | /usr/bin/awk '{ print $2 }'";
$res = trim(shell_exec($cmd));
shell_exec("rm -rf {$filename}");
return $res;
} else {
shell_exec("rm -rf {$filename}");
return '';
}
}
获取apk包的包名
这里借助github开源的类apkparser
在项目composer.json中执行下面命令或修改composer.json引入即可
composer require tufanbarisyildirim/php-apk-parser
/**
* 获取安卓APK 包名 PackAgeName
*
* @param string $filename apk包路径+名称
*
* @return string 包名
*/
function getPkgName($filename)
{
$apk = new \ApkParser\Parser($filename);
$manifest = $apk->getManifest();
$permissions = $manifest->getPermissions();
return $manifest->getPackageName();
}
方法二
方法二适用于没有JAVA环境的情况下,一般linux都会有openssl环境。
原理:通过分析方法一中,发现apk包解压之后,里面会有.rsa签名证书,此证书是一个符合pki体系的x509证书,通过openssl命令即可查看信息。
//不依赖JAVA环境,借助openssl获取APK签名
function getHash($filename)
{
$awk = '/usr/bin/awk';
$grep = '/usr/bin/grep';
$unzip = '/usr/bin/unzip';
$openssl = '/usr/bin/openssl';
$greprsa_cmd = "{$unzip} -l {$filename} | {$grep} META-INF/ | {$grep} SF | {$awk} -F '/' '{print $2}'";
$res = shell_exec($greprsa_cmd);
$result = explode('.', $res);
$rsaname = $result['0'];
$cmd = "{$unzip} -p {$filename} META-INF/" . $rsaname . ".RSA | {$openssl} pkcs7 -inform DER -print_certs | {$openssl} x509 -noout -fingerprint -sha1 -inform pem | {$awk} -F '=' '{print $2}'";
$res = trim(shell_exec($cmd));
shell_exec("rm -rf {$filename}");
return $res;
}
```php