在Android 4+(ICS)中使用Android TrustStore来支持aSmack

3
我不是密钥库方面的专家,很难理解其中的细微差别,但我已经做了这么多:
在使用asmack构建创建xmpp-连接时 here,仍然需要更改truststore,通常来说,根据网上多个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下,他们改变了一些东西,现在不再适用。路径现在不同了。
显然这可以修复,但我毫无头绪。
显然需要一个方法根据SDK版本返回路径,以返回所需的字符串来设置sdk-path,因为您不能只将密钥库本身返回到xmpp连接中。
参考这个,该方法如下:
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;
}

这里 有一位评论者说,在Android“4.x; /etc/security/cacerts.bks被替换成包含单个PEM编码文件的证书的目录/etc/security/cacerts/。”但是,我不知道这与任何相关性(如果有的话)。

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


我目前也正在调查这个问题。我们最近已经更改了在GTalkSMS上检测信任存储路径的方式,具体可以在这里看到(https://github.com/Flowdalic/asmack/wiki/Truststore)。但我相信这还不够... - Flow
2个回答

1
ICS中的信任存储不再是单个.bks文件,而是在/system/etc/security/cacerts目录中分别以PEM编码的文件形式存在。用户添加的证书可以放置在/data/misc/keychain/cacerts-added中。更多详细信息请参见此处
您的证书文件必须命名为: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连接。 - Lukas Ruge
或者,换个方向:我能否在不设置信任存储的情况下创建连接?可以说是一个不受信任的连接。 - Lukas Ruge
你尝试过Phillip的答案吗?在ICS中,您不需要设置信任库路径,只需要信任库类型“AndroidCAStore”。 - rustyx
是的,我尝试过了,它(几乎)起作用了(我认为错误在于我的周围代码)。我现在进一步简化了它,不使用任何类型的信任库或加密。基本上只使用最少量的代码,如此处所示:http://www.igniterealtime.org/builds/smack/docs/latest/documentation/connections.html。当然,这缺乏任何安全性,但似乎暂时可以工作,让我可以继续处理其他事情... - Lukas Ruge

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上使用了上面的代码,所以它运行良好,我也可以验证用户。但是我还看到了一个捕获的异常java.lang.NullPointerException。它是从proceedTLSReceived抛出的,这又调用了ServerTrustManager。它在configuration.getTruststorePath()处崩溃。有什么想法吗? - anargund
@anargund 我也遇到了同样的问题。ICS和JellyBean。 - Geebs
@Geebs,问题已解决。我从asmack网站下载了最新版本的jar文件。之前出现问题是因为我使用了一些旧的jar文件。一旦我开始使用最新的版本,大部分问题都得到了解决。 - anargund
如何创建信任存储路径以及相关背景,请向Phillip解释这些内容。 - Karthick M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接