我希望这不是重复的。 我目前正在与 Android 上的客户端一起开发基于 netty 的客户端服务器游戏。我试图建立一个安全的登录过程,所以我尝试在 java 套接字之上使用 ssl。
我设法创建了一个自签名证书并使用了 SSL。问题是我发现的示例源代码使用自定义 TrustManagerFactory,它不对证书有效性进行任何检查。由于我不想不允许中间人攻击,所以我搜索了有关 SSL 握手的更多信息,这是我的理解:
- 要启动 SSL session ,客户端向服务器发送请求。
- 拥有证书(.jks 或 .bks)的服务器将公共(public)信息提取到 X509 证书中并将其发送给客户端。
- 客户端检查证书的有效性(在我当前的解决方案中什么都不做)
- 如果检查成功,从证书中获取服务器的公钥,生成一个随 secret 钥,用公钥加密并发送给服务器。
- 服务器使用他的私钥来解密随机生成的 key 。
- 客户端和服务器现在共享相同的随 secret 钥,并且它们使用此 key 开始通信以进行对称加密(如 AES)。
除了我自己的服务器,我不需要接受任何其他人的证书,所以我考虑了 2 个解决方案:
- 在客户端保存 X509 并创建只接受此证书的自定义 TrustManager。该解决方案似乎易于实现但很难维护,因为服务器端的每个证书更改都需要在每个客户端上更新 X509 证书。
- 创建我自己的 CA 证书,用这个证书签署我的 ssl 证书,并以某种方式告诉我的客户只信任所有用我的 CA 签署的证书。
我对 CA 认证的理解是这样的:
- CA 根证书是包含 key 对的普通证书。
- 用 CA 签署证书意味着在正在签署的证书末尾添加一个用 CA 私钥加密的整个证书的散列。
- 此签名包含在 X509 证书中以及有关 CA 的一些信息。
- 为检查证书有效性,客户端生成证书哈希并将其与 X509 证书中包含的解密哈希(使用 CA 公钥)进行比较。
因此,如果我没有弄错所有这些,如果我想实现我的第二个解决方案,我需要向客户提供 CA 证书,以便他可以检查证书。我已经看到可以使用信任库初始化 TrustManager。我认为它必须是与根 CA 不同的证书,因为它的整体安全性取决于我的 CA 私钥的 secret 性。所以我的问题是:
- 此客户端信任库应包含什么以及如何从我的根 CA 生成?
- 我收到红色通知,表示自签名证书的 ssl 引擎已损坏。那么我的第二个解决方案在 Android 上可行吗?
- 如果这可行,如果我看到有人设法以某种方式获取我的私钥,我该如何使我的证书无效?我有关于 crl 的红色信息,但我不知道如何在我的信任库中生成/使用它们?
提前致谢。
最佳答案
我只能回答你的部分问题:
- 信任库应包含您的 CA,您可以使用 key 工具生成它:
http://docs.oracle.com/cd/E19509-01/820-3503/6nf1il6er/index.html - 没问题,您可以使用 java.security.* 和 org.apache.http.* 类在 android 中以与在 java 中相同的方式实现它。一个警告,对于 android 版本 <=2.3,您可能需要实现一种解决方法,因为某些公共(public) CA 丢失并且它不支持错误排序的证书链。如果需要,我可以为您提供更多详细信息。
- 我不知道
编辑:
一个很好的教程:
http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html
关于java - 创建一个信任库以仅验证由 JAVA 中的自定义 CA 签名的证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17994282/