【问题标题】:Android compare signature of current package with debug.keystoreAndroid 将当前包的签名与 debug.keystore 进行比较
【发布时间】:2011-09-01 14:50:53
【问题描述】:

正如我们所做的那样,当它处于开发模式(构建)时,我有一个由 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 Key、Logging、LicenseChecker 和类似的东西。

【问题讨论】:

  • 现在我使用 1 个静态布尔值,每次我进行生产发布时都必须更改它。事情发生了,我忘记了。 :(

标签: android apk signature


【解决方案1】:

基于Jcs' answer,我们使用它在运行时找出谁构建了运行包:

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

对于任何涉及的证书,您只需找到一次哈希并将其添加到列表中。

“查找哈希一次”的最简单方法可能是在显示 modulusHash 的 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 发送给所有相关的开发者,要求他们在他们的开发设备上运行它并让我知道显示的哈希值。

【讨论】:

  • 感谢您的信息...但是如何找到证书的哈希值?它是证书中“密钥别名”字符串的哈希吗?
【解决方案2】:

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

根据 Android 开发者页面Signing Your Applications,使用此 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);

【讨论】:

  • DEBUG_DN 的类型为 X500Principal。这是 X.500 名称的容器
  • 在应用类的onCreate上运行是否足够高效?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多