Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/222.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android将当前包的签名与debug.keystore进行比较_Android_Apk_Signature - Fatal编程技术网

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

Android将当前包的签名与debug.keystore进行比较,android,apk,signature,Android,Apk,Signature,和我们所做的一样,我有一个应用程序,当它处于开发模式(构建)时,由debug.keystore(默认情况下)签名。当它投入生产时,我们用私钥对其进行签名。 是否有任何方法可以在运行时确定当前包是使用debug.keystore签名的(处于开发模式)还是使用私钥签名的(处于生产模式) 我试过类似的东西 PackageManager packageManager = getPackageManager(); try { Signature[] signs = pack

和我们所做的一样,我有一个应用程序,当它处于开发模式(构建)时,由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指纹
keytool-list-keystore~/.android/debug.keystore
,但在签名类中没有类似“MD5指纹”的方法。
我之所以要这样做,是因为MapView密钥、日志记录、LicenseChecker以及类似的东西。

PackageInfo中的签名似乎没有很好的命名,因为该字段不包含包签名,而是包含签名者X509证书链。请注意,(大多数情况下)此链似乎仅限于一个自签名证书

根据Android开发者页面,调试签名证书是使用以下DN生成的:
CN=Android debug,O=Android,C=US

因此,很容易测试应用程序是否已在调试模式下签名:

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);
基于,我们使用此选项在运行时查找谁构建了运行包:

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;
}
对于任何涉及的证书,您只需查找一次哈希并将其添加到列表中

“一次查找散列”最简单的方法可能是在显示
moduleushash
的switch语句之前添加一个弹出的toast,编译应用程序,运行它,写下散列,删除toast代码并将散列添加到列表中

或者,当我实现此功能时,我创建了一个带有单个活动和单个
TextView
的小型样板应用程序,在主布局中使用ID
tv
,将其放入活动中:

@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);
}

(将
com.stackexchange.marvin
更改为您应用程序的名称),编译此迷你应用程序,并将APK发送给所有相关开发人员,要求他们在其开发设备上运行,并让我知道显示的哈希值。

现在我使用1个静态布尔值,每次发布生产版本时都必须更改该值。碰巧我忘了(
DEBUG\u DN
的类型为
X500Principal
。这是一个X.500名称的容器。它是否足够高效,可以在创建应用程序类时运行?感谢提供信息…但是如何查找证书的哈希?它是证书中“密钥别名”字符串的哈希吗?