Android 如何获得APK签名?

Android 如何获得APK签名?,android,certificate,apk,signature,Android,Certificate,Apk,Signature,是否有方法检索用于签署APK的密钥的签名?我用密钥库中的密钥签署了APK。如何以编程方式检索它?您可以使用PackageManager类像这样访问APK的签名 我用它与我的调试密钥的hashcode进行比较,以确定APK是调试APK还是发布APK。包管理器将为您提供任何已安装包的签名证书。然后,您可以打印签名密钥的详细信息,例如 final PackageManager packageManager = context.getPackageManager(); final List<Pa

是否有方法检索用于签署APK的密钥的签名?我用密钥库中的密钥签署了APK。如何以编程方式检索它?

您可以使用PackageManager类像这样访问APK的签名


我用它与我的调试密钥的hashcode进行比较,以确定APK是调试APK还是发布APK。

包管理器将为您提供任何已安装包的签名证书。然后,您可以打印签名密钥的详细信息,例如

final PackageManager packageManager = context.getPackageManager();
final List<PackageInfo> packageList = packageManager.getInstalledPackages(PackageManager.GET_SIGNATURES);

for (PackageInfo p : packageList) {
    final String strName = p.applicationInfo.loadLabel(packageManager).toString();
    final String strVendor = p.packageName;

    sb.append("<br>" + strName + " / " + strVendor + "<br>");

    final Signature[] arrSignatures = p.signatures;
    for (final Signature sig : arrSignatures) {
        /*
        * Get the X.509 certificate.
        */
        final byte[] rawCert = sig.toByteArray();
        InputStream certStream = new ByteArrayInputStream(rawCert);

        try {
            CertificateFactory certFactory = CertificateFactory.getInstance("X509");
            X509Certificate x509Cert = (X509Certificate) certFactory.generateCertificate(certStream);

            sb.append("Certificate subject: " + x509Cert.getSubjectDN() + "<br>");
            sb.append("Certificate issuer: " + x509Cert.getIssuerDN() + "<br>");
            sb.append("Certificate serial number: " + x509Cert.getSerialNumber() + "<br>");
            sb.append("<br>");
        }
        catch (CertificateException e) {
            // e.printStackTrace();
        }
    }
}
final-PackageManager-PackageManager=context.getPackageManager();
最终列表packageList=packageManager.getInstalledPackages(packageManager.GET_签名);
for(PackageInfo p:包装商){
最后一个字符串strName=p.applicationInfo.loadLabel(packageManager.toString();
最终字符串strVendor=p.packageName;
sb.追加(“
”+strName+”/“+strVendor+”
”); 最终签名[]arrSignatures=p.签名; 用于(最终签名签名:ARR签名){ /* *获取X.509证书。 */ 最后一个字节[]rawCert=sig.toByteArray(); InputStream certStream=新的ByteArrayInputStream(rawCert); 试一试{ CertificateFactory=CertificateFactory.getInstance(“X509”); X509Certificate x509Cert=(X509Certificate)certFactory.generateCertificate(certStream); sb.追加(“证书主题:+x509Cert.getSubjectDN()+”
”; sb.追加(“证书颁发者:+x509Cert.getIssuerDN()+”
”; sb.追加(“证书序列号:+x509Cert.getSerialNumber()+”
”; 某人追加(“
”); } 捕获(证书例外e){ //e.printStackTrace(); } } }
我的情况是,我预装了一个使用错误密钥存储的apk。所以直接安装会因为签名不一致而失败。我需要先检查签名以确保它可以顺利安装

这是我的解决方案

如上所述,您可以从已安装的apk获取签名

详情:

Signature sig = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];
第二:获取要比较的releaseApk哈希代码。在我的例子中,我从我的服务器下载了这个apk,并把它放在SDU卡中

Signature releaseSig = context.getPackageManager().getPackageArchiveInfo("/mnt/sdcard/myReleaseApk.apk", PackageManager.GET_SIGNATURES).signatures[0];
最后,比较hashCode

return sig.hashCode() == releaseSig.hashCode;

我已经尝试了上面的代码,它工作得很好。如果hashCode不同,您应该只使用旧的apk,或者如果它是一个系统应用程序,并且设备是根目录的,您可以只使用运行时对其进行签名,然后安装新的签名apk。

您可以使用ant脚本对其进行签名。但这将要求您将密码存储在不安全的地方。我只需要从其中的应用程序获取签名,例如,在我的第一个活动中,我以某种方式获取了我的应用程序签名。到目前为止我还不知道我现在是怎么理解的。我不确定这是否可行。有没有办法获得未安装应用程序的签名?例如,如果我有一个.apk文件,这种方法在严重情况下不能抵抗冲突,请不要使用
hashCode()
。例如,如果您想验证要与之通信的其他应用程序是否使用正确的密钥签名,请使用加密安全哈希(例如SHA256)。@Ruzard Yes,您可以。您需要将未安装的apk推送到程序可以获取apk(如SD卡)的位置,然后使用context.getPackageManager().getPackageAchiveInfo(非安装apk路径,PackageManager.get_签名)。签名[0]获取其哈希代码。并对它们进行比较。好luck@HosseinShahdoost是的,他们已经覆盖了它,但使用起来仍然不安全。计算出的散列由32位组成,这允许轻微的冲突。有关详细信息,请参阅。验证具有相应序列号的文件的命令是:unzip-p[path_to_apk]META-INF/CERT.RSA | keytool-printcertgetPackageArchiveInfo,而不是getPackageAchiveInfo
return sig.hashCode() == releaseSig.hashCode;