1

我需要在两个桌面 Java 应用程序之间进行通信,最好的方法是使用 SSL(以防止嗅探器)。我控制客户端和服务器,所以自签名是可以的。

我的问题是是否可以通过编程方式从头开始制作和使用证书(即最终用户不必亲自做任​​何事情)。

如果这是可能的,你能给我一些指示吗?

4

2 回答 2

4

我的问题是是否可以通过编程方式从头开始制作和使用证书(即最终用户不必亲自做任​​何事情)。

在考虑生成证书(以编程方式或非编程方式)之前,您需要决定如何验证它们。在两个桌面应用程序的上下文中,验证服务器证书的传统方法可能不适合。

证书的目的是提供一种验证远程方身份的方法,以防止中间人攻击。验证方使用它已经信任的东西进行验证;不这样做会使使用证书毫无意义。

在传统模型中(使用固定服务器),服务器证书是 PKI 的一部分,由 CA 颁发。客户端根据其信任的一组 CA 证书验证其真实性(通常使用RFC 5280中描述的规则,并验证证书对于正在查找的主机名是否有效(如何完成取决于协议,但最好和历史实践在RFC 6125中进行了描述)。这两个步骤都是防止 MITM 攻击所必需的。这类似于使用护照验证某人的身份:您想要检查护照是否真实并且来自您信任的权威,并且您想要检查该名称(或图片)与您正在寻找的名称(或您面前的脸)相匹配。

在两个桌面应用程序之间建立通信时,您肯定会遇到两个方面的问题:如何让客户端验证证书是由您信任的实体颁发的,并且是颁发给您要与之通信的实体的。如果您在任何一方都没有以编程方式生成证书,那么它肯定会是自签名的,如果没有其他交换方式(独立于此 SSL/TLS 通信),这将使从另一方验证其真实性变得困难。此外,桌面往往没有固定的主机名,因此基于 DNS(甚至是 IP 地址)的标识符在这种情况下可能不够用。

您需要想办法以远程方可以验证它信任它的方式发布证书,并考虑一种识别方案以确保证书属于正确的实体(这通常是证书的主题 DN 或主题备用名称扩展名)。

一旦你做出这些决定,你就可以使用BouncyCastleorg.bouncycastle.x509.X509V3CertificateGenerator生成你的证书(一个 X.509 v3 证书应该允许你为证书添加扩展,例如用于密钥使用目的,如果你需要的话)。BouncyCastle wiki上有各种示例(对于 v1、v3 和/或自签名,即 Subject = Issuer)。我想说不幸的是,使用它很容易(信任的管理方面是最难的)。

如果这两个桌面应用程序实际上都是更集中的应用程序的一部分,则您可以根据应用程序中生成的证书请求 (CSR) 运行颁发此证书的服务。中央服务器将有效地运行您自己的 CA,并且您的桌面应用程序将信任该 CA。根据您组织的复杂性,有可用的工具来执行此操作,或者您也可以使用 BouncyCastle 来实现它,使用相同的类(如果您实现 CRL/OSCP 以便能够撤销证书,那就更好了)。在这种情况下,您可以让您的应用程序生成一个 CSR 并将其提交给您的中央 CA。可以使用 BouncyCastle 生成 CSRPKCS10CertificationRequest. 同样,您的 CA 如何使用外部信息验证 CSR 来自正确的一方,这也是一个管理问题,也许您可​​以将其与电子邮件验证方案或类似的东西联系起来。

生成证书后,您将能够使用Java 的 JSSE作为您的 SSL/TLS 堆栈(通常使用SSLSocket)。您可能必须使用 customX509TrustManager来实现证书验证(如果您无法使用传统的 CA 模型,则取决于您设计验证证书的方案的方式)。check*只要确保您不使用在他们的方法中不做任何事情的信任管理器;有很多这样的例子:在这种情况下,如果你不做任何事情来验证它们,你可能根本不使用证书(这会使连接容易受到 MITM 攻击)。

于 2012-09-09T17:47:47.393 回答
1

您可以使用基于 JCE 的解决方案和SSLSocket、jdk6的文档及其实现:SSLSocketImpl。

Java SSL SSH:

您有Jsch lib 可以使用 SSH 协议连接到任何服务器。

SSL 的 Java 工具箱:

你有充气城堡。查看他们的资源文档。wiki 提供了一些最新版本的有用示例:

ContentSigner sigGen = ...;
PublicKey publicKey = ....;

Date startDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
Date endDate = new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000);

X509v1CertificateBuilder v1CertGen = new JcaX509v1CertificateBuilder(
          new X500Principal("CN=Test"), 
          BigInteger.ONE, 
          startDate, endDate, 
          new X500Principal("CN=Test"), 
          publicKey);

X509CertificateHolder certHolder = v1CertGen.build(sigGen);
于 2012-09-09T14:21:46.450 回答