使用xmpp时,避免在android中“接受未知证书”警告

时间:2013-12-12 12:55:36

标签: android ssl

我正在尝试搜索XMPP。我从here获得了代码。它工作正常,我能够连接到服务器。但它显示像这样的警报窗口

Warning for connection

如果我点击“始终”或“一次”它正在接受,我可以显示联系人和聊天消息....

有没有办法停止此警报,我可以直接连接到服务器吗?

3 个答案:

答案 0 :(得分:9)

此消息由MemorizingTrustManager(MTM)显示,这是一个Android库,旨在提高“私有云”SSL安装的安全性/可用性权衡。

每当您连接到服务器时,MTM都会发出此警告,该服务器的证书不是由某个Android OS受信任的根CA颁发的,如自签名证书或CACert证书。

如果在单击“始终”后再次显示该消息,则这是MTM中的错误(可能是由于SSL服务器名称不匹配),应通过github报告。

编辑:如果您创建的应用只与一台服务器通信,并且您事先知道服务器的证书,则应将MTM替换为AndroidPinning,以确保无人可以对你的连接进行中间人攻击。

免责声明:我是MTM的作者和yaxim的主要成员。

答案 1 :(得分:3)

获取由证书颁发机构签名的证书。忘记所有编码解决方案。

答案 2 :(得分:2)

  

有没有办法停止此警报,我可以直接连接到服务器吗?

如果你写这个连接到kluebook.com的应用程序,我不清楚。我想你做到了,但不明确。

假设您编写了应用程序并知道要连接的服务器(kluebook.com),则应提供自定义TrustManager来处理此问题。您可以在OWASP's Certificate and Public Key Pinning示例中找到与预期服务器证书一起使用的自定义TrustManger的代码。它可以固定,因为您知道证书或公钥是什么,并且没有必要信任像CA这样的其他人。

如果您没有先验知识,那么您信任首次使用并遵循密钥连续性策略,寻找证书或公钥的突然变化。在这种情况下,首次使用的信任应包括习惯性的X509检查。

固定是整体安全多元化战略的一部分。一本关于这个主题的好书是彼得古特曼的Engineering Security

您看到的提示是策略的一个方面 - 即首次使用信任(TOFU)策略。提示具有边际价值,因为用户不知道如何回应它,因此他们只需单击是以关闭该框以便他们可以继续他们正在做的事情。 Peter Gutmann在Engineering Security撰写了关于用户心理学(包括安全性UI研究)的精彩文章。

来自OWASP's Certificate and Public Key Pinning的第6.1节:

public final class PubKeyManager implements X509TrustManager
{
  private static String PUB_KEY = "30820122300d06092a864886f70d0101...";

  public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
  {
    if (chain == null) {
      throw new IllegalArgumentException("checkServerTrusted: X509Certificate array is null");
    }

    if (!(chain.length > 0)) {
      throw new IllegalArgumentException("checkServerTrusted: X509Certificate is empty");
    }

    if (!(null != authType && authType.equalsIgnoreCase("RSA"))) {
      throw new CertificateException("checkServerTrusted: AuthType is not RSA");
    }

    // Perform customary SSL/TLS checks
    try {
      TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
      tmf.init((KeyStore) null);

      for (TrustManager trustManager : tmf.getTrustManagers()) {
        ((X509TrustManager) trustManager).checkServerTrusted(chain, authType);
      }
    } catch (Exception e) {
      throw new CertificateException(e);
    }

    // Hack ahead: BigInteger and toString(). We know a DER encoded Public Key begins
    // with 0x30 (ASN.1 SEQUENCE and CONSTRUCTED), so there is no leading 0x00 to drop.
    RSAPublicKey pubkey = (RSAPublicKey) chain[0].getPublicKey();
    String encoded = new BigInteger(1 /* positive */, pubkey.getEncoded()).toString(16);

    // Pin it!
    final boolean expected = PUB_KEY.equalsIgnoreCase(encoded);
    if (!expected) {
      throw new CertificateException("checkServerTrusted: Expected public key: "
                + PUB_KEY + ", got public key:" + encoded);
      }
    }
  }
}

您可以从OpenSSL的s_client获取预期的公钥,但您必须知道该端口。我无法从众所周知的SSL端口(如5223)获得响应,而5222没有安全服务:

$ openssl s_client -connect kluebook.com:5222
CONNECTED(00000003)
140735088755164:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:766:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 322 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

获得公钥后,请将其重新插入TrustManager的{​​{1}}。