我尝试从Android连接到localhost中的Apache Vysper XMPP服务器。我使用Smack框架来执行XMPP操作:
AbstractXMPPConnection connection = new XMPPTCPConnection("bigdestroyer", "", ip);
try {
connection.setPacketReplyTimeout(10000);
connection.connect();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
}
但是我收到了这个错误:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException:信任锚 未找到证书路径。
我猜这与SSL证书有关,但我不知道自己该做什么。你能救我吗?
我试图在cert
文件夹中放置assets
文件(与服务器相同)并以这种方式创建连接:
XMPPTCPConnectionConfiguration connectionConfiguration = configuration.setConnectTimeout(10000)
.setUsernameAndPassword("admin", "admin")
.setHost(ip)
.setServiceName(ip)
.setKeystorePath("file:///android_asset/bogus_mina_tls.cert")
.build();
XMPPTCPConnection connection = new XMPPTCPConnection(connectionConfiguration);
但它仍然无法奏效。有什么建议吗?
答案 0 :(得分:2)
KeystorePath应指向密钥库,而不是简单的证书。 Android默认使用KeystoreType BKS,因此您应该创建一个并将证书导入其中,如http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/所述
keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret
如果您不想弄乱命令行,也可以使用Portecle(http://portecle.sourceforge.net/)执行此操作。
答案 1 :(得分:1)
Android Training可能会解决这个问题:
验证服务器证书的常见问题这可能由于多种原因而发生,包括:
- 颁发服务器证书的CA未知
- 服务器证书未经CA签名,但已自签名
- 服务器配置缺少中间CA
醇>以下部分讨论如何解决这些问题 保证与服务器的连接安全。
未知的证书颁发机构
在这种情况下,发生SSLHandshakeException是因为您有CA. 不受系统信任。可能是因为你有一个 来自新的CA的证书,但尚未受到Android或您的信任 应用程序在没有CA的旧版本上运行。更常见的是CA. 未知因为它不是公共CA,而是由公司CA发布的私人CA. 政府,公司或教育等组织 机构供自己使用。
幸运的是,您可以教HttpsURLConnection来信任特定的集合 CA.这个程序可能有点复杂,所以下面是一个 从InputStream获取特定CA的示例,使用它 创建一个KeyStore,然后用于创建和初始化 的TrustManager。 TrustManager是系统用于验证的内容 来自服务器的证书,并通过从KeyStore创建一个 一个或多个CA--这些CA将是唯一受其信任的CA. 的TrustManager。
给定新的TrustManager,该示例初始化一个新的SSLContext 它提供了一个SSLSocketFactory,可用于覆盖默认值 来自HttpsURLConnection的SSLSocketFactory。这样连接就会 使用您的CA进行证书验证。
以下是完整使用组织CA的示例 华盛顿大学:
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);
使用了解您的CA的自定义TrustManager,系统是 能够验证您的服务器证书来自可信任的 发行者。
警告:很多网站都描述了一个糟糕的替代解决方案 安装一个什么都不做的TrustManager。如果你这样做,你可能会 以及不加密你的沟通,因为任何人都可以 使用DNS技巧攻击公共Wi-Fi热点上的用户 发送您的用户'通过他们自己的代理交换流量 是你的服务器。然后攻击者可以记录密码等 个人资料。这是有效的,因为攻击者可以生成一个 证书和 - 没有实际验证它的TrustManager 证书来自可靠的来源 - 您的应用可能正在谈论 对任何人。所以不要这样做,甚至不是暂时的。你总能做到 您的应用程序信任服务器证书的颁发者,所以就这样做。
该页面继续提供其他可能性,但这个似乎可能是最相关的。
答案 2 :(得分:0)
有两种方法可以解决您的问题:
通过让受信任的第三方签署证书来修复您的服务器。
让您的客户accept the self-signed certificate you are using right now。