在 Android 4+ (ICS) 中为 aSmack 使用 Android TrustStore

Posted

技术标签:

【中文标题】在 Android 4+ (ICS) 中为 aSmack 使用 Android TrustStore【英文标题】:Using the Android TrustStore for aSmack in Android 4+ (ICS) 【发布时间】:2012-06-01 12:30:14 【问题描述】:

我不是密钥库方面的专家,很难理解其中的细微差别,但这就是我能做到的:

在使用 here 找到的 asmack 构建创建 xmpp 连接时,仍然需要更改信任库,通常,例如网络上的多个 sources,使用这些命令完成

ConnectionConfiguration config = new ConnectionConfiguration(host, Integer.parseInt(port), service);
config.setTruststorePath("/system/etc/security/cacerts.bks");
config.setTruststorePassword("changeit");
config.setTruststoreType("bks");
XMPPConnection connection = new XMPPConnection(connConfig);
connection.connect();

这适用于较旧的 android 版本,但在 ICS 下他们更改了一些内容,现在不再更改。现在的路径不同了。

显然是this can be fixed,但我不知道该怎么做。

显然,需要一种根据 SDK 版本返回路径的方法,该方法返回设置 sdk 路径所需的字符串,因为您不能只将密钥库本身返回到 xmpp 连接。

参考this,该方法如下所示:

private String getTrustStorePath() 

 String path = System.getProperty("javax.net.ssl.trustStore");

 if (path == null) 
 
  if ( Build.VERSION.SDK_INT >= 14 ) 
  
   //THIS IS THE PART I DONT KNOW
   path="";
  
  else
  
   path = "/system/etc/security/cacerts.bks";
  

  return path;

Here 一位评论者说,在 Android 下,“4.x;/etc/security/cacerts.bks 被替换为目录 /etc/security/cacerts/,其中包含作为单独 PEM 编码文件的证书。”但是,我不知道这有什么相关性(如果有的话)。

我还检查了使用 xmpp 和 asmack 的两个项目的代码(gtalksms 和 yaxim,但没有看到他们如何避免这个问题。

【问题讨论】:

我目前也在调查这个问题。我们最近有changed how we detect the truststore path on GTalkSMS,因为它也可以是seen here。但我很确定这还不够…… 【参考方案1】:

试试这个:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
    connectionConfiguration.setTruststoreType("AndroidCAStore");
    connectionConfiguration.setTruststorePassword(null);
    connectionConfiguration.setTruststorePath(null);
 else 
    connectionConfiguration.setTruststoreType("BKS");
    String path = System.getProperty("javax.net.ssl.trustStore");
    if (path == null)
        path = System.getProperty("java.home") + File.separator + "etc"
            + File.separator + "security" + File.separator
            + "cacerts.bks";
    connectionConfiguration.setTruststorePath(path);

请参阅https://github.com/Flowdalic/asmack/wiki/Truststore 和http://nelenkov.blogspot.com/2011/12/ics-trust-store-implementation.html 的一些背景说明。

【讨论】:

嗨,我用上面的 Jellybean 代码,所以它工作正常,我也可以验证用户。但是我也看到了一个从proceedTLSReceived抛出的异常java.lang.NullPointerException,它又调用ServerTrustManager。它为 configuration.getTruststorePath() 崩溃。有什么想法吗? @anaargund 我也看到了同样的问题。 ICS 和 JellyBean。 @Geebs 我解决了。我从 asmack 网站下载了最新版本的 jar 文件。我之前遇到过问题,因为我使用的是一些旧的 jar 文件。刚开始用最新的,大部分问题都解决了。 如何创建信任存储路径和那些背景,请解释这些东西@Phillip【参考方案2】:

ICS 中的信任存储不再位于单个 .bks 文件中,而是位于 /system/etc/security/cacerts 目录中的单独 PEM 编码文件中。用户添加的证书可以放在/data/misc/keychain/cacerts-added。更多详情请见here

您的证书文件必须命名为:subject-hash.N 其中 N 是从 0 开始的连续整数(通常只有 0,但如果已使用 0,则为 1,等等)。

要获取证书的主题哈希,您可以像这样使用 openssl: openssl x509 -noout -subject_hash_old -in my-cert-file.pem

【讨论】:

谢谢,但是如何配置连接,如果不再存在,则需要设置信任库的路径? jivesoftware.smack.ConnectionConfiguration 需要使用 setTruststorePath,因为最终结果需要是 XMPP 连接。 或者,换个方向:我可以在不设置信任存储的情况下创建连接吗?可以说是不受信任的连接。 你试过菲利普的答案吗?在 ICS 中您不需要设置信任存储路径,只需设置信任存储类型“AndroidCAStore”即可。 是的,我试过了,它(几乎)工作了(我认为错误出在我周围的代码中)。我现在进一步减少了它,没有使用任何类型的信任或加密。基本上是here 所示的最低限度。这当然缺乏任何安全性,但现在似乎可以让我从事其他工作......

以上是关于在 Android 4+ (ICS) 中为 aSmack 使用 Android TrustStore的主要内容,如果未能解决你的问题,请参考以下文章

Android 4 ICS Ice Cream Sandwich - 包含表单的 iframe

使用 AsyncTask 的 Android ICS 和 MJPEG

带有 SQLite 的 Android 应用程序在 ICS 中运行,但在 Jelly Bean 中不运行 - IllegalStateException

ICS 4.0.3 上的 ActionBar 和 Fragments

是否可以在 Intel 语法中为 AMD 处理器编写 ASM 代码?

如何使用适用于 Gingerbread 和 Froyo 的 ICS UI 创建 Android 应用程序?