Android将当前包的签名与debug.keystore进行比较

| 就像我们所做的一样,当应用程序处于开发模式(构建)时,我会使用debug.keystore签名的应用程序(默认情况下)。当它投入生产时,我们用我们的私钥对其进行签名。 是否有任何方法可以在运行时确定当前包是使用debug.keystore签名的(处于开发模式)还是已用我们的私钥签名(处于生产模式)。 我已经尝试过类似的东西
    PackageManager packageManager = getPackageManager();
    try {
        Signature[] signs = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures;
        for (Signature signature : signs) {
            Log.d(TAG, \"sign = \" + signature.toCharsString());
        }
    } catch (NameNotFoundException e) {
        e.printStackTrace();
    }
我不知道下一步该怎么做?这是这样做的正确方法吗?如何获得可比的debug.keystore签名? 我知道存在MD5 Fingerprint
keytool -list -keystore ~/.android/debug.keystore
,但在Signature类中没有类似“ md5 Fingerprint”的方法。 由于MapView Key,Logging,LicenseChecker和类似的东西,我想这样做。     
已邀请:
PackageInfo
中的签名似乎命名不正确,因为tha字段不包含程序包签名,但包含签名者X509证书链。请注意,(大多数情况下)此链似乎仅限于一个单一的自签名证书。 根据Android开发人员页面“签署应用程序”,调试签名证书是使用以下DN生成的:generated3ѭ 因此,很容易测试应用程序是否已在调试模式下签名:
private static final X500Principal DEBUG_DN = new X500Principal(\"CN=Android Debug,O=Android,C=US\");
/* ... */
Signature raw = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];
CertificateFactory cf = CertificateFactory.getInstance(\"X.509\");
X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));
boolean debug = cert.getSubjectX500Principal().equals(DEBUG_DN);
    
基于Jcs的答案,我们使用它在运行时查找谁构建了正在运行的程序包:
private enum BuildSigner {
    unknown,
    Joe,
    Carl,
    Linda
}

private BuildSigner whoBuiltThis() {
    try {
        PackageManager packageManager = getPackageManager();
        PackageInfo info = packageManager.getPackageInfo(getPackageName(),
                PackageManager.GET_SIGNATURES);
        Signature[] signs = info.signatures;
        CertificateFactory cf = CertificateFactory.getInstance(\"X.509\");
        X509Certificate cert = (X509Certificate)cf.generateCertificate(
                new ByteArrayInputStream(signs[0].toByteArray()));
        PublicKey key = cert.getPublicKey();
        int modulusHash = ((RSAPublicKey)key).getModulus().hashCode();
        switch (modulusHash) {
            case 123456789:
                return BuildSigner.Joe;
            case 424242424:
                return BuildSigner.Carl;
            case -975318462:
                return BuildSigner.Linda;
        }
    } catch (Exception e) {
    }

    return BuildSigner.unknown;
}
对于任何涉及的证书,您只需要查找一次哈希并将其添加到列表中即可。 “一次性查找哈希”的最简单方法是在显示just6ѭ的switch语句之前添加弹出烤面包,编译您的应用程序,运行它,写下哈希,删除烤面包代码,然后将哈希添加到清单。 另外,在实现此功能时,我创建了一个小样板应用程序,其中包含一个活动和一个主布局中带有ID
tv
的single7ѭ,并将其放入活动中:
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    int hash = 0;
    try{
        PackageManager packageManager = getPackageManager();
        PackageInfo info = packageManager.getPackageInfo(
                \"com.stackexchange.marvin\", PackageManager.GET_SIGNATURES);
        Signature[] signs = info.signatures;
        CertificateFactory cf = CertificateFactory.getInstance(\"X.509\");
        X509Certificate cert = (X509Certificate) cf.generateCertificate(
                new ByteArrayInputStream(signs[0].toByteArray()));
        PublicKey key = cert.getPublicKey();
        hash = ((RSAPublicKey) key).getModulus().hashCode();
    }catch(Exception e){}

    TextView tv = ((TextView)findViewById(R.id.tv));
    tv.setText(\"The Stack Exchange app\'s signature hash is \" + hash + \".\");
    tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 24);
}
(将ѭ10更改为您的应用程序的名称),编译了此微型应用程序,并将APK发送给所有相关的开发人员,要求他们在开发设备上运行它,并让我知道显示的哈希值。     

要回复问题请先登录注册