Java ftps连接,TrustManager解释(使用filezilla服务器)

时间:2014-06-05 09:15:19

标签: java x509certificate filezilla client-certificates ftps

我已经编写了一个程序(显然是从网上COPIED,并根据我的需要进行了一些修改!),使用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 Server中设置ftps的配置时,我必须创建证书。

看到这一切,我没有理解证书创建的原因,因为我们没有传递或返回证书。或者服务器或库是否在内部处理它。有人可以就此问题彻底解释我。

1 个答案:

答案 0 :(得分:2)

getAcceptedIssuers仅用于(Java)SSL / TLS服务器。你显然是在写#34;客户。

大多数案例中的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绕过了与正确的服务器交谈的所有烦人的坚持。它实际上说#34;我的数据是如此私密,必须加密以防止人们窃取它,但我非常高兴将它发送到由访问我的网络的小偷运行的虚假服务器,或者它上面的东西,或者我经常使用的DNS"。如果您(并且将始终如此)在一个小型隔离网络上,这可能是安全的 - 或者至少欺诈性服务器的风险不会大于您的客户端或服务器本身的风险" 0wned"从而使连接的安全性变得毫无意义。或者,如果数据实际上不是私有的,并且您只是因为服务器需要它而使用SSL(可能在这里不正确),或者您喜欢为自己做额外的工作,那么安全性就不重要了。

编辑了解更多信息/问题:

好的,该文件包含PEM格式' RSA PRIVATE KEY'和'证书'正是我所说的服务器所需要的:证书和匹配的私钥。 (BEGIN xxx包围5个破折号的格式,base64数据,然后END xxx类似地很久以前为PEM定义,即使PEM本身已经放弃,仍然使用格式。)对这些内容使用后缀.crt是不寻常的有点混乱; FileZilla选择了那个还是你呢?在任何情况下,客户只需要一个证书,不应该有私钥,所以你需要提取'什么,但首先你需要看看你有什么。

您拥有什么?除非FileZilla为您与CA进行过互动,并且可能会收到您已经注意到的付款,否则此证书几乎肯定是自签名 ,即使用自己的密钥和名称签名,而不是由CA根据CA的名称签名。自签名证书通常不受广泛信任,需要管理更多工作,但如果此环境仅适用于您自己或像小型企业这样的有限群体,则自签名证书就足够了。同样重要的是"主题"证书中的名称是:对于正确检查的SSL / TLS连接,证书中的名称必须与您请求连接的名称匹配;通常这是一个域名,但它可以是一个你不需要域名功能的IP地址(例如你自己经营的服务器从不移动)。还有其他选项可能不适用于此处。要查看您拥有的内容,请将证书部分(从dash-BEGIN CERTIFICATE行直至并包括dash-END行)复制到另一个文件,然后执行以下操作之一对其进行解码:

  • 在Windows名称上带有后缀.cer的文件,然后双击它以显示详细信息,并查看颁发给:并发布者:

  • 在安装了Java的系统上运行keytool -printcert -file /path/to/that/file并查看所有者:和发布者:

  • 在具有OpenSSL的系统上(Linux,其他人可能)运行openssl x509 -in /that/file -noout -text并查看主题:和发行人:

您应该使用什么?如果您的发行者/由和主题/所有者/彼此相等并且与您的服务器名称相匹配,则您拥有良好的自签名证书。还要检查有效日期(有效期,有效期或有效期之后)以确定它是否会很快过期 - 特别证书通常会这样做。此时,您有两个相互关联的选择。首先,是否使用该证书:

  • 如果你有一个好的自签名证书(正确的服务器名称和有效性),你可以把它放在/每个客户的信任存储区中来使用它。

  • 如果没有,但你有(或得到)OpenSSL,你可以重新生成另一个自签名证书,它具有你需要的任何名称和有效性,并且你将 放在服务器< em>和 /每个客户的信任存储。

  • 或者代替任何自签名证书,您可以从Java信任的已建立的CA(证书颁发机构)获得证书,例如Verisign,GoDaddy等。这通常每年花费一些钱或很少,并要求您证明你的&#34;对&#34;到证书中你想要的域名(通过各种方式,例如发送到你的MX的电子邮件,DNS中的数据,网络服务器上的数据等)。此外,今天大多数CA都强制执行RSA密钥必须为2048位的最佳做法(或更多,但你不需要更多);我不知道FileZilla是否足以生成大小的密钥,如果没有,您必须生成一个新密钥(使用openssl),然后才能继续从CA获取证书。 CA方法的优点是不需要添加到/每个客户端的信任存储区。

如何信任它?在客户端,如上所述,您不需要为真正的CA方法做任何事情。但对于自我设计的方法, 使用包含FTPS客户端的Java SSL客户端,该自签名证书必须位于客户端使用的信任库中,此处有以下几种方法:

  • 使用JRE默认信任库,如果文件jssecacerts存在,则为cacerts文件JREHOME/lib/security,即lib/security下的文件SSLContext。您的JRE安装位置。您正在使用的FTPSClient可能有一种方法可以使用使用默认信任库的JRE默认SSLContext.getDefault(),或者您可以将其传递给keytool -importcert -keystore jssecacerts -file /path/to/something.cer。如果这是您需要SSL连接的唯一主机,只需将您的something.cer PEM文件从上面放入jssecacerts与
    changeit和密码-alias myfilezilla(输入两次)。 如果您需要来自同一JVM或JRE的其他SSL连接,尤其是公共Internet,首先将cacerts复制到jssecacerts,并在-importcert上指定keytool -importcert -keystore /path/to/mytrust -file /path/to/something.cer(或唯一的变体,仅限字母和数字)。

  • 覆盖默认信任库。通过javax.net.ssl.trustStore创建一个包含(仅)您的证书的密钥库,并将/ path / to / mytrust放入客户端或与您的客户端一起,或者您(以及任何其他用户)将容易记住的某个位置与您的客户端相关联。然后将系统属性System.setProperty(n,v)设置为JVM中的该文件。有几种方法可以做到这一点:在命令行中始终使用-D或在代码中调用java.security.KeyStore(在第一次创建SSL套接字之前);在某些应用程序环境中,还有其他系统属性配置或管理功能。

  • 编写您自己的信任库。创建一个CertificateFactory并使用包含您的证书的数据加载它 - 直接(通过.setCertificateEntryjavax.net.ssl.TrustManager读取证书)或加载您之前使用keytool创建的文件,如上所示;然后用你的密钥库创建一个真实的(不是nobbled).initTrustManager;然后以与现在相同的方式在SSLContext中使用{{1}}。这更复杂,如果上述任何一个更简单的选项适合您,我都不推荐它。