java - Java ftps连接,TrustManager说明(使用Filezilla服务器)

标签 java x509certificate filezilla client-certificates ftps

我已经编写了一个程序(显然是从网络上复制的,并根据我的需要进行了一些修改!),用于使用apache ftp api以及通过使用Filezilla服务器创建本地服务器来进行文件下载/上传。
一切都很好。问题是我没有得到我们必须创建信任管理器的部分。

码:

FTPSClient ftpsClient= null;
SSLContext sslContext = SSLContext.getInstance(protocol);
TrustManager tm = new X509TrustManager() {
    public X509Certificate[] getAcceptedIssuers() {
        System.out.println("getAcceptedIssuers------");
        return null;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        // TODO Auto-generated method stub
        System.out.println("checkClientTrusted------");
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        // TODO Auto-generated method stub
        System.out.println("checkServerTrusted------");
    }
};

    sslContext.init(null, new TrustManager[] { tm }, null);//new SecureRandom());
    ftpsClient = new FTPSClient(true, sslContext);


public X509Certificate [] getAcceptedIssuers()此方法根据文档返回证书发行者授权机构的列表,该列表可用于对等身份验证。但是在代码中,该方法返回null。

同样,在Filezilla服务器中设置ftp的配置时,我必须创建一个证书。

看到这一切,我不明白为什么创建证书,因为我们没有通过或返回证书。还是服务器或库在内部处理它。有人可以彻底向我解释这个问题。

最佳答案

getAcceptedIssuers仅用于(Java)SSL / TLS服务器。您显然是在“编写”客户端。

在大多数情况下,SSL / TLS服务器需要证书和匹配的私钥。有些人将它们视为一件事,因为它们或多或少是一起创建的,但事实并非如此。通常,应该为每个服务器生成(创建)该对,但这并不总是必需的或必需的。我不特别知道FileZilla服务器。 SSL / TLS中有一些用于服务器的选项,它们不使用证书(或“静态”预生成的密钥)并且不进行身份验证,但是通常会禁用(或完全未实现)这些选项,因为实际上导致的连接经常被颠覆。相反,客户端也可以选择使用证书+私钥进行身份验证,通常称为“双向”或“相互”身份验证,但是很少使用。

回到通常情况,作为SSL / TLS“握手”的一部分,服务器提供一个证书,该证书标识由CA(或通常是多个CA的“链”)签名的服务器,客户端可以将其验证为受信任的服务器,并使用握手协议中的私钥有两种方式之一。在这两种情况下,这都证明所到达的服务器是正确的服务器-或更确切地说,提供了证据来使CA确信正确的服务器具有该密钥对,并且从那时起,就不知道该密钥已被泄露。有关更多详细信息,请参见https://security.stackexchange.com/questions/20803/how-does-ssl-work https://security.stackexchange.com/questions/1779/how-does-an-ssl-server-prove-its-identity https://security.stackexchange.com/questions/6737/what-is-an-ssl-certificate-intended-to-prove-and-how-does-it-do-it

您的“信任任何人” TrustManager会绕过所有与正确服务器通信的烦人的坚持。它说:“实际上,我的数据是如此私有,必须加密以防止人们窃取它,但我非常高兴将其发送到由可以访问我的网络或其中的某些东西的小偷运行的假服务器上,或经常使用的DNS”。如果您(并且将始终)处于小型隔离网络中,则这可能是安全的-或至少,欺诈性服务器的风险不大于您的客户端或服务器本身被“拥有”的风险,从而确保连接的安全性无意义的。或者,如果数据实际上不是私有的,而您只是因为服务器要求它而使用SSL(这里可能不是真的),或者您喜欢自己进行额外的工作,那么安全性就不那么重要了。

编辑其他信息/问题:

好的,包含PEM格式的“ RSA PRIVATE KEY”和“ CERTIFICATE”的文件正是我所说的服务器所需要的:证书和匹配的私钥。 (很早以前就为PEM定义了BEGIN xxx周围有5个破折号,base64数据和END xxx的格式,即使PEM本身已被放弃,该格式仍在使用。)对这些内容使用后缀.crt是不常见的,有点混乱是FileZilla选择的还是您?无论如何,客户端仅需要证书,并且不应该具有私钥,因此您确实需要“提取”某些东西,但是首先您需要查看所拥有的东西。

你有什么?除非FileZilla为您与CA进行交互并且可能从您那里收到付款(您会注意到),否则该证书几乎可以肯定是自签名的,即使用自己的密钥和名称签名,而不是由CA用CA的名义签名。通常,自签名证书不受广泛信任,并且需要管理更多工作,但是,如果此环境仅适合您本人或像小型企业这样的少数群体,则自签名证书就足够了。证书中的“主题”名称是什么也很重要:对于正确检查的SSL / TLS连接,证书中的名称必须与您请求连接的名称相匹配;通常这是一个域名,但也可以是您不需要域名功能的IP地址(例如,您自己运行的服务器永远不会动)。还有其他选项可能在这里不适用。要查看所拥有的内容,请仅将证书部分(从破折号的“ BEGIN CERTIFICATE”行开始,包括破折号的“ END”行)复制到另一个文件,然后执行以下操作之一对其进行解码:


在Windows上,用后缀.cer命名该文件,然后双击该文件以显示详细信息,然后查看“颁发给:”和“颁发者:”
在装有Java的系统上,运行keytool -printcert -file /path/to/that/file并查看Owner:和Issuer:
在具有OpenSSL的系统(Linux,可能还有其他)上,运行openssl x509 -in /that/file -noout -text并查看Subject:和Issuer:


你应该用什么?如果您的颁发者/作者和主题/所有者/彼此相等并且与服务器名称匹配,那么您将拥有一个良好的自签名证书。还要检查有效期(有效期,有效期至或有效期不晚),以查看其是否会很快过期(临时证书)。此时,您有两个相互关联的选择。首先,是使用该证书还是其他证书:


如果您具有良好的自签名证书(正确的服务器名称和有效性),则可以通过将其放入每个客户端的信任库中来使用它。
如果不是,但是您拥有(或获得)OpenSSL,则可以重新生成另一个具有所需名称和有效性的自签名证书,并将其放入服务器和每个客户端的信任库中。
或代替任何自签名证书,您可以从Java信任的已建立CA(证书颁发机构)那里获取证书,例如Verisign,GoDaddy等。这通常每年或很少花费一些钱,并且要求您证明自己对“证书”的“权利”您想要在证书中使用的域名(通过各种方式,例如发送给MX的电子邮件,DNS中的数据,Web服务器上的数据等)。此外,当今大多数CA强制执行最佳做法,即RSA密钥必须为2048位(或更多) ,但您不需要更多);我不知道FileZilla是否足够最新以生成该大小的密钥,否则,必须先生成一个新密钥(使用openssl),然后才能继续从CA获取证书。 CA方法的优点是无需向每个客户端的信任库添加任何内容。


如何信任它?如前所述,在客户端,您无需为真正的CA方法做任何事情。但是对于自签名方法,
对于包含FTPS客户端的Java SSL客户端,该自签名证书必须位于客户端使用的信任库中,这里有几种方法:


请使用JRE默认信任库,如果存在,则为文件jssecacerts,否则为cacerts中的文件JREHOME/lib/security,即JRE安装在任何位置的子目录lib/security。您正在使用的FTPSClient可能有一种使用默认信任库的JRE默认SSLContext的方法,也可以将其传递给SSLContext.getDefault()。如果这是您需要SSL连接的唯一主机,只需将您的something.cer PEM文件从上方放入jssecacerts中,
keytool -importcert -keystore jssecacerts -file /path/to/something.cer和密码changeit(输入两次)。
如果您需要来自同一JVM或JRE的其他SSL连接,尤其是到公共Internet的SSL连接,则首先将cacerts复制到jssecacerts,并且在-importcert上还指定-alias myfilezilla(或唯一的变体,仅字母和数字)。
覆盖默认信任库。创建一个包含(仅)由keytool -importcert -keystore /path/to/mytrust -file /path/to/something.cer生成的证书的密钥库,然后将/ path / to / mytrust放入客户端或与客户端一起放置,或者将您(和任何其他用户)容易记住的某个位置与客户端关联。然后将系统属性javax.net.ssl.trustStore设置为JVM中的该文件。有几种方法可以执行此操作:始终在命令行上使用-D或在代码中调用System.setProperty(n,v)(在第一次创建SSL套接字之前);在某些应用程序环境中,还有其他系统属性配置或管理功能。
编写自己的信任库。创建一个java.security.KeyStore并用包含证书的数据加载它-直接(通过CertificateFactory.setCertificateEntry读取证书)或加载先前使用keytool先前创建的文件(如上所述);然后创建一个真实的(没有空位的)javax.net.ssl.TrustManager,并用您的密钥库创建它;然后以与现在相同的方式在.init中使用该TrustManager。这比较复杂,如果上面的两个较简单的选项都适合您,我不建议这样做。

关于java - Java ftps连接,TrustManager说明(使用Filezilla服务器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24056173/

相关文章:

java - 创建文件后是否可以自动上传到网络服务器?

macos - Windows Azure 和 FileZilla FTP

java - Joda 可以使用阿拉伯数字格式化阿拉伯语言区域的日期吗?

java - Spring-MVC 对 REST 客户端的验证响应

java - 连接到 Heroku clearDB mySql

security - 可以让x509Certificate不过期吗?如果是这样,怎么办?<EOM>

c# - Web Api 中的自签名证书始终为空

c# - 偶尔从 X509Certificate2 获取私钥时出现异常 "Invalid Provider type specified"或 "Key does not exist"

java - 在 CancelAll 之后删除队列中剩余的请求

shell - FileZilla 打破 rbash 和 scponly chrooting