简体   繁体   English

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

[英]Java ftps connection, TrustManager explaination (using filezilla server)

I have written a program (obviously COPIED from the net, and modified it little according to my needs!) for file download/upload using apache ftp api and by creating a local server using Filezilla server. 我已经编写了一个程序(显然是从网络上复制的,并根据我的需要进行了少量修改!),用于使用apache ftp api以及通过使用Filezilla服务器创建本地服务器来进行文件下载/上传。 Everything is working FINE . 一切都很好 The problem is I didn't get the part where we have to create a trust manager. 问题是我没有得到我们必须创建信任管理器的部分。

Code: 码:

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() this method according to the documentation returns the list of certificate issuer authorities which are trusted for authentication of peers . public X509Certificate [] getAcceptedIssuers()此方法根据文档返回证书发行者授权机构的列表,该列表可用于对等身份验证 But here in the code, the method is returning null. 但是在代码中,该方法返回null。

Also while setting the configuration for ftps in the Filezilla Server, I had to create a certificate. 同样,在Filezilla服务器中设置ftp配置时 ,我必须创建一个证书。

Seeing all this I didn't get why the certificate was created as we are not passing or returning the certificate. 看到所有这些,我不明白为什么创建证书,因为我们没有通过或返回证书。 Or does the server or library handles it internally. 还是服务器或库在内部处理它。 Can someone explain me thoroughly about this issue. 有人可以彻底向我解释这个问题。

getAcceptedIssuers is used only for a (Java) SSL/TLS server. getAcceptedIssuers仅用于(Java)SSL / TLS服务器。 You are apparently "writing" a client. 您显然是在“编写”客户端。

An SSL/TLS server in most cases requires a certificate and matching private key . 大多数情况下,SSL / TLS服务器需要证书和匹配的私钥 Some people treat these as one thing, because they are created more-or-less together, but they aren't. 有些人将它们视为一件事,因为它们或多或少是一起创建的,但事实并非如此。 Typically that pair should be generated (created) for each server, but that isn't always necessary or required; 通常, 应该为每个服务器生成(创建)该对,但这并不总是必需的或必需的。 I don't know for FileZilla server in particular. 我不特别知道FileZilla服务器。 There are options in SSL/TLS for the server to not use a certificate (or "static" pregenerated key) and not be authenticated, but these are generally disabled (or completely unimplemented) because the resulting connections are in practice too often subverted. SSL / TLS中有一些选项可以让服务器不使用证书(或“静态”预生成密钥)并且不进行身份验证,但是通常会禁用(或完全未实现)这些选项,因为实际上导致的连接经常被颠覆。 Conversely there are options for the client to also authenticate with a certificate+privatekey, often called "two-way" or "mutual" authentication, but they are rarely used. 相反,客户端也可以使用证书+私钥进行身份验证的选项,通常称为“双向”或“相互”身份验证,但是很少使用。

Returning to the usual case, as part of the SSL/TLS "handshake" the server presents a certificate which identifies the server signed by a CA (or usually a "chain" of multiple CAs) that the client can verify as trusted, and uses the privatekey in the handshake protocol in one of two ways. 回到通常情况,作为SSL / TLS“握手”的一部分,服务器提供一个证书,该证书标识由CA(或通常是多个CA的“链”)签名的服务器,客户端可以将其验证为受信任的服务器,并使用握手协议中的私钥有两种方式之一。 In either case this proves that the server reached is the right one -- or more exactly that evidence was provided to convince a CA the right server had that key(pair), and the key isn't known to have been compromised since. 在这两种情况下,这都证明所到达的服务器是正确的服务器-或更确切地说,提供了证据来证明CA正确的服务器具有该密钥(对),并且从那以后就不知道该密钥已被泄露。 For more detail see 有关更多详细信息,请参见
https://security.stackexchange.com/questions/20803/how-does-ssl-work 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/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 https://security.stackexchange.com/questions/6737/what-is-an-ssl-certificate-intended-to-prove-and-how-does-it-do-it

Your "trust anybody" TrustManager bypasses all this annoying insistence on talking to the right server. 您的“信任所有人” TrustManager绕过了所有与正确的服务器通信的烦人的坚持。 It says in effect "my data is so private it must be encrypted to prevent people from stealing it, but I'm perfectly happy to send it to a fake server run by a thief who got access to my network, or something on it, or often the DNS I use". 它说:“实际上,我的数据是如此私人,必须加密以防止人们窃取它,但我非常高兴将其发送到由可以访问我的网络或其中的某些东西的小偷运行的假服务器上,或经常使用的DNS”。 If you are (and always will be) on a small isolated network this may be safe -- or at least the risk of a fraudulent server is no greater than the risk your client or server is itself "0wned" thus rendering security of the connection meaningless. 如果您(并且将始终)处于小型隔离网络中,则这可能是安全的-或至少,欺诈性服务器的风险不大于您的客户端或服务器本身被“拥有”的风险,从而确保连接的安全性无意义的。 Or if the data is in fact not private and you're just using SSL because the server demands it (presumably not true here) or you enjoy making extra work for yourself, then security is unimportant. 或者,如果数据实际上不是私有的,而您只是因为服务器需要它而使用SSL(这里可能不是真的),或者您喜欢自己进行额外的工作,那么安全性就不那么重要了。

EDIT for additional info/question: 编辑其他信息/问题:

Okay, that file containing PEM-format 'RSA PRIVATE KEY' and 'CERTIFICATE' is exactly what I said a server needs: a certificate and matching private key. 好的,包含PEM格式的“ RSA PRIVATE KEY”和“ CERTIFICATE”的文件正是我所说的服务器所需要的:证书和匹配的私钥。 (The format with BEGIN xxx surrounded by 5 dashes, base64 data, then END xxx similarly was defined long ago for PEM and even though PEM itself has been abandoned the format is still used.) Using the suffix .crt for these contents is unusual and a bit confusing; (很早以前就为PEM定义了BEGIN xxx加上5个破折号,base64数据和END xxx的格式,即使PEM本身已被放弃,该格式仍在使用。)对这些内容使用后缀.crt是不常见的,有点混乱 did FileZilla choose that or did you? FileZilla选择了还是您? In any case, the client(s) need only a cert and should NOT have the privatekey so you do need to 'extract' something, but first you need to see what you have. 无论如何,客户端仅需要证书,并且不应该具有私钥,因此您确实需要“提取”某些东西,但是首先您需要查看所拥有的东西。

What do you have? 你有什么? Unless FileZilla interacted with a CA for you and probably got payment from you which you would have noticed, this certificate is almost certainly self-signed , that is, signed using its own key and name rather than signed by a CA under the CA's name. 除非FileZilla为您与CA进行交互并且可能从您那里收到付款(您会注意到),否则该证书几乎可以肯定是自签名的 ,即使用其自己的密钥和名称签名,而不是由CA用CA的名义签名。 Selfsigned certs generally are not widely trusted and more work to manage, but if this environment is only for yourself or a limited group of people like a small business, a selfsigned cert can be adequate. 通常,自签名证书不受广泛信任,并且需要管理更多工作,但是如果此环境仅适合您本人或像小型企业这样的少数群体,则自签名证书就足够了。 It also matters what the "subject" name in the certificate is: for a properly checked SSL/TLS connection the name in the cert must match the name you request connection to; 证书中的“主题”名称是什么也很重要:对于正确检查的SSL / TLS连接,证书中的名称必须与您请求连接的名称相匹配; usually this is a domain name but it can be an IP address where you don't need the features of a domain name (eg a server you run yourself that never moves). 通常这是一个域名,但也可以是不需要域名功能的IP地址(例如,您自己运行的服务器永远不会动)。 There are also other options probably not applicable here. 还有其他选项可能在这里不适用。 To see what you have, copy only the certificate part (from the dash-BEGIN CERTIFICATE line through and including the dash-END line) to another file and do one of the following to decode it: 要查看所拥有的内容,请将证书部分(从破折号的“ BEGIN CERTIFICATE”行开始,包括破折号的“ END”行)复制到另一个文件,然后执行以下操作之一对其进行解码:

  • on Windows name that file with suffix .cer and double-click it to display the details and look at Issued to: and Issued by: 在Windows上,用后缀.cer命名该文件,然后双击该文件以显示详细信息,然后查看“颁发给:”和“颁发者:”

  • on a system with Java installed run keytool -printcert -file /path/to/that/file and look at Owner: and Issuer: 在安装了Java的系统上,运行keytool -printcert -file /path/to/that/file并查看Owner:和Issuer:

  • on a system with OpenSSL (Linux, others maybe) run openssl x509 -in /that/file -noout -text and see Subject: and Issuer: 在具有OpenSSL的系统(Linux,可能还有其他系统)上,运行openssl x509 -in /that/file -noout -text并查看Subject:和Issuer:

What should you use? 你应该用什么? If you have issuer/by and subject/owner/to equal to each other and matching the name of your server, you have a good self-signed cert. 如果您的签发人/签发人和主题/所有者/彼此相等且与服务器名称匹配,则您具有良好的自签名证书。 Also check the validity date (valid to, valid until, or validity not-after) to see if it will expire (too) soon -- ad-hoc certs often do. 还要检查有效期(有效期,有效期至或不迟于有效期),以查看其是否会很快过期(即临时证书)。 At this point you have two interlinked choices to make. 此时,您有两个相互关联的选择。 First, whether to use that cert or another: 首先,使用该证书还是其他证书:

  • if you have a good selfsigned cert (correct server name and validity) you can use it by putting it in the trust store of the/each client. 如果您具有良好的自签名证书(正确的服务器名称和有效性),则可以通过将其放在每个客户端的信任存储中来使用它。

  • if not, but you have (or get) OpenSSL, you can re-generate another selfsigned cert which has whatever name and validity you need, and you put that in the server and the trust store of the/each client. 如果没有,但你必须(或获得)的OpenSSL,你可以重新生成另一个自签名证书具有您所需要的任何名称和效度,你服务器的信任存储/每个客户端。

  • or instead of any selfsigned cert you can get a cert from an established CA (Certificate Authority) that Java trusts, such as Verisign, GoDaddy etc. This usually costs some money every year or few, and requires you prove your "right" to the domain name you want in the certificate (by various means such as email to your MX, data in your DNS, data on webserver, etc.) In addition most CAs today enforce a best practice that your RSA key must be 2048 bits (or more, but you don't need more); 或代替任何自签名证书,您可以从Java信任的已建立CA(证书颁发机构)那里获得证书,例如Verisign,GoDaddy等。这通常每年或很少花费一些钱,并且要求您证明自己对“您想要在证书中使用的域名(通过各种方式,例如发送给MX的电子邮件,DNS中的数据,Web服务器上的数据等)。此外,当今大多数CA强制执行最佳做法,即RSA密钥必须为2048位(或更多) ,但您不需要更多); I don't know if FileZilla is up-to-date enough to have generated the key that size and if not, you must generate a new key (with openssl) before you can proceed to get the cert from the CA. 我不知道FileZilla是否足够最新才能生成该大小的密钥,否则,必须先生成一个新密钥(使用openssl),然后才能继续从CA获取证书。 The advantage of the CA approach is nothing needs to be added to the trust store of the/each client. CA方法的优点是无需向每个客户端的信任库添加任何内容。

How to trust it? 如何信任它? On the client side, as noted, you don't need to do anything for the real-CA approach. 如前所述,在客户端,您无需为真正的CA方法做任何事情。 But for the selfsigned approach, with a Java SSL client including an FTPS client, that selfsigned certificate must be in the truststore the client uses, and there are several methods here: 但是对于自签名方法,对于包含FTPS客户端的Java SSL客户端,该自签名证书必须位于客户端使用的信任库中,这里有几种方法:

  • use the JRE-default truststore, which is the file jssecacerts if it exists and otherwise the file cacerts in JREHOME/lib/security ie the subdirectory lib/security under whatever location your JRE is installed at. 使用JRE默认的信任,这是文件jssecacerts是否存在以及否则文件cacertsJREHOME/lib/security即子目录lib/security的任何位置安装在你的JRE下。 The FTPSClient you are using probably has a way to use the JRE default SSLContext which uses the default truststore, or you can pass it SSLContext.getDefault() . 您正在使用的FTPSClient可能有一种使用JRE默认SSLContext ,该方法使用默认的信任库,也可以将其传递给SSLContext.getDefault() If this is the only host you need SSL connection to, just put your something.cer PEM file from above into jssecacerts with 如果这是您需要SSL连接的唯一主机,只需将您的something.cer PEM文件从上方放入jssecacerts中,
    keytool -importcert -keystore jssecacerts -file /path/to/something.cer and password changeit (entered twice). keytool -importcert -keystore jssecacerts -file /path/to/something.cer和密码changeit (输入两次)。 If you need other SSL connections from the same JVM or JRE, especially to the public Internet, first copy cacerts to jssecacerts and on the -importcert also specify -alias myfilezilla (or a unique variant, letters and digits only). 如果您需要来自同一JVM或JRE的其他SSL连接,特别是到公共Internet的SSL连接,则首先将cacerts复制到jssecacerts,并且在-importcert上还指定-alias myfilezilla (或唯一的变体,仅字母和数字)。

  • override the default truststore. 覆盖默认信任库。 Create a keystore containing (only) your cert by keytool -importcert -keystore /path/to/mytrust -file /path/to/something.cer and either put that /path/to/mytrust in or with your client, or someplace that you (and any other users) will easily remember is associated with your client. 通过keytool -importcert -keystore /path/to/mytrust -file /path/to/something.cer创建一个(仅包含)您的证书的密钥库,然后将该/ path / to / mytrust放入您的客户端或与您的客户端放在一起,您(以及任何其他用户)将很容易记住与您的客户相关联。 Then set system property javax.net.ssl.trustStore to that file in your JVM. 然后将系统属性javax.net.ssl.trustStore设置为JVM中的该文件。 There are several ways to do that: always -D on the command line or call System.setProperty(n,v) in your code (before the first SSL socket creation); 有几种方法可以执行此操作:始终在命令行上使用-D或在代码中调用System.setProperty(n,v) (在第一次创建SSL套接字之前); in some application environments there are other system-property configuration or management features. 在某些应用程序环境中,还有其他系统属性配置或管理功能。

  • code your own truststore. 编写自己的信任库。 Create a java.security.KeyStore and load it with data containing your cert -- either directly (read the cert through a CertificateFactory and .setCertificateEntry ) or by loading a file that you previously created with keytool as above; 创建一个java.security.KeyStore并使用包含证书的数据加载它-直接(通过CertificateFactory.setCertificateEntry读取证书),或者通过加载先前使用上述keytool创建的文件; then create a real (not nobbled) javax.net.ssl.TrustManager and .init it with your keystore; 然后创建一个真正的(不nobbled) javax.net.ssl.TrustManager.init与您的密钥存储它; then use that TrustManager in your SSLContext in the same way you have now. 然后以与现在相同的方式在SSLContext中使用该TrustManager This is more complicated and I don't recommend it if either of the simpler options above works for you. 这比较复杂,如果上面的两个简单选项都对您有用,我不建议您这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM