让 Java 只接受一个 SSL 证书
我有一个 java 小程序,它加载一些预安装的本机代码扩展以在浏览器中显示自定义内容。其中一些内容可能包括由 JVM 加载的本机代码。显然,这是一个安全问题。我想强制所有内容仅来自授权服务器。
我为实现这一目标所遵循的途径是创建一个仅包含一个 SSL 证书的密钥库。我设置了密钥库位置和密码并打开了调试输出。
System.setProperty("javax.net.ssl.keyStore", "C:\\keys\\keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
System.setProperty("javax.net.debug", "ssl");
我的印象是,这意味着 JVM 将只能访问一个密钥库文件,从而访问其中的一个密钥。事实上,除了我添加的一个密钥之外,SSL 调试信息还列出了类似 75 个 CA 密钥的内容。显然,这不会阻止任何人向我们发送不受信任的代码。
有没有办法告诉 SSL 系统只使用单个证书?我应该使用完全不同的方法吗?
更新: 更改 cacerts 文件并不是真正的选择。 JVM 应继续为使用它的其他应用程序正常运行。有没有办法在运行时选择不加载该文件?我正在查看 TrustManager 和 KeyManager 类,但我不太明白如何使用它们。
I've got a java applet that loads some pre-installed native code extensions to display custom content in the browser. Some of this content may include native code to be loaded by the JVM. Obviously, this is a security concern. I'd like to enforce that all content comes only from authorized servers.
The path I've been following to accomplish this is to create a keystore that contains just one SSL certificate. I set the keystore location and password and turned on debug output.
System.setProperty("javax.net.ssl.keyStore", "C:\\keys\\keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
System.setProperty("javax.net.debug", "ssl");
I was under the impression that this would mean that the JVM would have access to only the one keystore file and consequently the one key inside it. In fact, the SSL debug info lists something like 75 CA keys in addition to the one key I added. Clearly, this isn't going to keep anyone from sending us untrusted code.
Is there a way to tell the SSL system to only use a single certificate? Should I be using a completely different approach?
Update:
Changing the cacerts file isn't really an option here. The JVM should continue to function normally for other applications using it. Is there a way, at runtime, to elect not to load that file? I'm looking at the TrustManager and KeyManager classes but I don't really understand how to use them.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您需要设置 javax.net.ssl.trustStore 系统属性以指向其中包含您的一个证书的密钥库。密钥库用于您的身份验证凭据,而不是您的同行的。
You need to set the
javax.net.ssl.trustStore
system property to point to a keystore with your one certificate in it. The keystore is for your authentication credentials, not your peer's.这里的问题本身就是错误的。证书只是身份证明。您不授权证书,您授权身份。如果同一个客户端提出新证书怎么办?
正确的答案是安装一个
HandshakeCompletedListener
来检查对等方身份。信任库仅用于身份验证,即他们是否是他们所说的那个人。你所做的是授权,这是完全不同的事情。您不应使用信任库(或任何 PKI 机制)进行授权。The very question is wrong here. A certificate is only a proof of identity. You don't authorize certificates, you authorize identities. What if the same client comes up with a new certificate?
The correct answer is to install a
HandshakeCompletedListener
that checks the peer identity. The truststore is only there for authentication, i.e. is that person who they said they were. What you are doing is authorization, which is a different thing completely. You shouldn't use the truststore (or any PKI mechanism) for authorization.您还可以使用 JRE 安装全局密钥库,这是存储所有 CA 的位置。尝试重命名它,看看会发生什么。
You also have the global keystore installed with the JRE, which is where all the CA's are stored. Try to rename it and see what happens.
您仍然“看到”位于
java.home/jre/lib/security
中的系统范围 JREcacerts
文件的 CA 证书,这是正常的。现在,引用 keytool 文档关于这个文件:
就您而言,如果您确实想要的话,用您自己的密钥存储完全替换
cacerts
可能比删除所有 75 个条目更容易。如果不是,那么您确实应该使用不同的方法(为什么不限制或硬编码授权服务器列表?)。You still "see" the CA certificates of the system-wide JRE
cacerts
file located injava.home/jre/lib/security
, which is normal.Now, quoting the keytool documentation about this file:
In your case, it might be easier to entirely replace the
cacerts
with your own key store instead of removing all 75 entries if this is really what you want. If not, then you should use a different approach indeed (why don't you just restrict or hard code the list of authorized servers?).