第三方应用怎么获取应用签名证书的hash值?

第三方应用怎么获取应用签名证书的hash值

阅读 475
avatarAI BotBETA

在Android中,获取应用签名证书的SHA256散列值可以通过使用Java的KeyStore类来完成。以下是一个基本的示例,展示了如何使用Java获取已安装应用的签名证书的SHA256散列值。

import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class CertificateUtils {
    public static String getSHA256Fingerprint(String alias) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidCAStore");
            keyStore.load(null);
            final Certificate cert = keyStore.getCertificate(alias);
            if (cert != null) {
                if (cert instanceof X509Certificate) {
                    return getSHA256Fingerprint((X509Certificate) cert);
                } else {
                    return "Not an X509Certificate: " + cert.getClass().getName();
                }
            } else {
                return "Alias not found";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "Error getting SHA256 fingerprint: " + e.getMessage();
        }
    }

    private static String getSHA256Fingerprint(X509Certificate cert) throws CertificateParsingException {
        List<byte[]> subjectAltNames = Collections.emptyList();
        try {
            subjectAltNames = Collections.list(cert.getSubjectAlternativeNames());
        } catch (Exception e) { /* ignored */ }
        final Collection<? extends Certificate> issuerCerts = Collections.emptySet();
        try {
            issuerCerts = Collections.list(cert.getIssuers());
        } catch (Exception e) { /* ignored */ }
        final List<byte[]> issuerDNs = Collections.list(issuerCerts.stream().map(cert -> cert.getSubjectX500Principal().getName()).iterator());
        final List<byte[]> subjectDNs = Collections.list(cert.getSubjectX500Principal().getName().split("\\s+"));
        final List<byte[]> serialNumbers = Collections.list(cert.getSerialNumber().toString().split("\\s+"));
        final List<byte[]> publicKeys = Collections.list(cert.getPublicKey().toString().split("\\s+"));
        final List<byte[]> signatureAlgorithms = Collections.list(cert.getSigAlgName().split("\\s+"));
        final List<byte[]> validityPeriods = Collections.list(cert.getNotBefore().toString().split("\\s+") + cert.getNotAfter().toString().split("\\s+"));
        final List<byte[]> serialNumberParameters = Collections.list(cert.getSerialNumberParameter() == null ? "null" : cert.getSerialNumberParameter().toString().split("\\s+"));
        final List<byte[]> signatureParameters = Collections.list(cert.getSignatureAlgorithmParameters() == null ? "null" : cert.getSignatureAlgorithmParameters().toString().split("\\s+"));
        final List<byte[]> tbsCertificateContents = Collections.list(cert.getTBSCertificate() == null ? "null" : cert.getTBSCertificate().toString().split("\\s+"));
        final byte[] encodedHash = cert.getEncoded(); // this is the raw SHA256 hash of the certificate, but it's not directly useful for fingerprint comparison, see https://github.com/google/certificate-transparency/blob/master/client/ctutil/sha256_hasher.py for a more useful approach
        return String.format("%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s", // this is just for display purposes, not for fingerprinting!
                subjectAltNames, issuerDNs, subjectDNs, serialNumbers, publicKeys, signatureAlgorithms, validityPeriods, serialNumberParameters, signatureParameters, tbsCertificateContents, encodedHash); // this is just for display purposes, not for fingerprinting!
    }
}
1 个回答

三方应用可以通过bundleManager.getBundleInfoForSelf()获取自身的应用包信息,其中入参bundleFlags指定所返回的BundleInfo中所包含的信息。
参考代码如下:

import bundleManager from '@ohos.bundle.bundleManager'; 
import { BusinessError } from '@ohos.base'; 
import hilog from '@ohos.hilog'; 
let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT; 
try { 
    bundleManager.getBundleInfoForSelf(bundleFlags).then((data) => { 
        hilog.info(0x0000, 'testTag', 'getBundleInfoForSelf successfully. Data: %{public}s', JSON.stringify(data)); 
    //data里可以获取到signatureInfo,即应用的签名证书信息 
    }).catch((err: BusinessError) => { 
        hilog.error(0x0000, 'testTag', 'getBundleInfoForSelf failed. Cause: %{public}s', err.message); 
    }); 
} catch (err) { 
    let message = (err as BusinessError).message; 
    hilog.error(0x0000, 'testTag', 'getBundleInfoForSelf failed: %{public}s', message); 
}

signatureInfo.fingerprint是应用签名证书(.cer文件)的SHA256 hash值:

image.png

对于hash值,可使用加解密框架的hash算法,目前支持SHA1、SHA224、SHA256、SHA384、SHA512、MD5,参考代码如下:

let filePath = pathDir + "/test.txt"; 
Hash.hash(filePath, "sha256").then((str: string) => { 
  console.info("calculate file hash succeed:" + str); 
}).catch((err: BusinessError) => { 
  console.info("calculate file hash failed with error message: " + err.message + ", error code: " + err.code); 
});

参考链接
Hash.hash

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题