【问题标题】:Java ftps connection, TrustManager explaination (using filezilla server)Java ftps 连接、TrustManager 讲解(使用filezilla server)
【发布时间】:2014-06-05 09:15:18
【问题描述】:

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

看到这一切,我不明白为什么要创建证书,因为我们没有传递或返回证书。或者服务器或库是否在内部处理它。有人可以详细解释一下这个问题吗?

【问题讨论】:

    标签: java x509certificate filezilla client-certificates ftps


    【解决方案1】:

    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”。如果您(并且总是)在一个小型隔离网络上,这可能是安全的 - 或者至少欺诈服务器的风险不大于您的客户端或服务器本身“0wned”的风险,从而提供连接的安全性无意义的。或者,如果数据实际上不是私有的,而您只是因为服务器需要它而使用 SSL(这里可能不是真的),或者您喜欢为自己做额外的工作,那么安全性并不重要。

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

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

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

    • 在 Windows 上将该文件命名为后缀 .cer 并双击它以显示详细信息并查看颁发给:和颁发者:

    • 在安装了 Java 的系统上运行 keytool -printcert -file /path/to/that/file 并查看 Owner: 和 Issuer:

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

    您应该使用什么?如果您的 issuer/by 和 subject/owner/to 彼此相等并且与您的服务器名称匹配,那么您就有了一个很好的自签名证书。还要检查有效期(有效期至、有效期至或有效期不超过)以查看它是否会(过早)过期——临时证书通常会这样做。此时,您有两个相互关联的选择要做。首先,是否使用该证书或其他证书:

    • 如果您有一个良好的自签名证书(正确的服务器名称和有效性),您可以通过将其放入/每个客户端的信任库中来使用它。

    • 如果没有,但您拥有(或获得)OpenSSL,您可以重新生成另一个自签名证书,该证书具有您需要的任何名称和有效性,然后将 that 放入服务器 和/每个客户端的信任库。

    • 或者,您可以从 Java 信任的已建立 CA(证书颁发机构)获取证书,而不是任何自签名证书,例如 Verisign、GoDaddy 等。这通常每年或很少花费一些钱,并且需要您证明您对证书中所需域名的“权利”(通过各种方式,例如通过电子邮件发送到您的 MX、您的 DNS 中的数据、网络服务器上的数据等)此外,今天大多数 CA 强制执行最佳实践,即您的 RSA 密钥必须为 2048 位(或更多,但您不需要更多);我不知道 FileZilla 是否更新到足以生成该大小的密钥,如果不是,您必须生成一个新密钥(使用 openssl),然后才能继续从 CA 获取证书。 CA 方法的优点是无需向/每个客户端的信任库添加任何内容。

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

    • 使用 JRE-default 信任库,即文件 jssecacerts(如果存在),否则为 JREHOME/lib/security 中的文件 cacerts,即安装 JRE 的任何位置下的子目录 lib/security。您正在使用的 FTPSClient 可能有一种使用 JRE 默认 SSLContext 的方法,它使用默认信任库,或者您可以传递它 SSLContext.getDefault()。如果这是您需要 SSL 连接的唯一主机,只需使用
      keytool -importcert -keystore jssecacerts -file /path/to/something.cer 和密码 changeit(输入两次)将您的 something.cer PEM 文件从上面放入 jssecacerts。 如果您需要来自同一 JVM 或 JRE 的其他 SSL 连接,尤其是到公共 Internet,请首先将 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;然后像现在一样在SSLContext 中使用TrustManager。这比较复杂,如果上述任何一个更简单的选项适合您,我不推荐它。

    【讨论】:

    • 您的理论解释和链接非常有用。在 filezilla 服务器中,可以选择创建证书,然后创建 .crt 文件。当我打开该文件时, -----BEGIN RSA PRIVATE KEY----- ASCII 字符的长列表-----END RSA PRIVATE KEY----- , -----BEGIN CERTIFICATE- ---- 长长的 ASCII 字符列表-----END CERTIFICATE-----
    • 但我在某处读到我们必须分别提取密钥和证书。这是如何工作的?你能告诉我如何在java中实现整个事情,主要是证书的使用吗?是的,我正在编写 SSL 协议的 ftps 客户端。
    • 这是一个更大的问题,其答案对于评论来说太长了,所以在上面进行了编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多