Tag Archives: ftps

Transferring File Using FTPS in Java

Here’s a sample code on setting up FTPS file transfer in Java. Make sure you have setup SSLContext trusting the FTPS server’s certificate.

SSLContext sslContext = /* setup SSLContext */
FTPSClient ftps = new FTPSClient(true, sslContext);
ftps.connect(hostname, port);

// Timeout exception will be raised if no response received after 20s
ftps.setDataTimeout(20000);

// Authenticate
ftps.user("ftp_user")
ret = ftps.pass("ftp_pass");

// Define protection buffer size and protocol. Following are the default for implicit FTP (FTPS)
ftps.parsePBSZ(0);
ftps.execPROT("P");

// Set passive mode and file transfer type
ftps.type(FTP.BINARY_FILE_TYPE);
ftps.enterLocalPassiveMode();

// Remote path where file will be downloaded from
ftps.changeWorkingDirectory("/remote/path");

// Retrieve a file called "file.txt" from remote server
FileOutputStream local = new FileOutputStream("file.txt");
ftps.retrieveFile("file.txt", local);

This code uses commons-net package, make sure it is included in maven dependencies:


  commons-net
  commons-net
  3.3

The actual FTPS code will vary greatly depending on your FTPS server setup. The above assumes FTPS server is running in passive mode with normal username / password authentication.

Trusting X509 Base64 PEM SSL Certificate in Java

If you ever find yourself having to establish SSL connection with untrusted server (eg: because the server’s cert is not chained to 3rd party CA (internal / testing servers)), you’ll probably use -Djavax.net.ssl.trustStore and -Djavax.net.ssl.trustStorePassword.

While this method works great for jvm-wide configuration, it’s a bit tricky if you want to apply it to specific class / method only. Also if you ever had to dynamically update the trust certificate, it might be harder to get this method working

Trusting Certificate Using SSLContext

Supposed you have a X.509 SSL certificate in Base 64 encoded PEM format like below:

-----BEGIN CERTIFICATE-----
MIIDBzCCAe+gAwIBAgIJAI1DCiDwQMQ0MA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV
BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNDA0MzAyMjU1NTZaFw0yNDA0MjcyMjU1
NTZaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAOjZRpPtBBrOE32MV2X1HlTmLFE3977o4k97CYZetgxZ
guLy+dPBaJ6fA3pjhkqXbICtsaBewAjnlvUgUilc0quwklepw9Sd9L6M9NgyCFGf
G1AFA8wEJwmtxA7TnDNjuqATqbLUOe2douuQ9Krttd5zbGB2vDO1Chc4GYb1pUxV
wTAdk+bXrpoeP/82LEYjcYq2UTXs/cUnzDAOzOCXcCugx2Rh2EdS/S6oXgOYv/BD
q1jVj3AojcJuJixW/BGWwvw/hkBof0RzrnJNqHnO3PWfc0LhOeqKwOhMZ9dV2p0m
v5X221nrBMwOZRDJBWybE5YuWmAt6ci2BtHgn3l4ClcCAwEAAaNQME4wHQYDVR0O
BBYEFBFwLKrHXhSyapQbXp/2E/R1VT0XMB8GA1UdIwQYMBaAFBFwLKrHXhSyapQb
Xp/2E/R1VT0XMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAMRaPuv
lFTZpAn8lCqom0Af8+3OGEPUEYPOReE0xG7Ph+OSPhlI860C0QwiZn0PR3L+QK2F
d1g9GndfJATgyjqbhebKXO1b0OAQfGIPsEHsCtT+4myFNHnYmHKqnX1NrUXpjzcP
4uHpVU7Nomz+f4WjH+cACL4PrlldPtXXOsn7vFdZrYunitHTvslWe3RoQCkHRc93
3OKx4Xh2Vy1wCrfkZYd8Q1y55jysxwitYhQAYwv9GyL/pj5jzB5PxLAZbDRznK5E
CbqiKbfbcAEpbxceXG0YmVYY/kEzXKPxUw99GH/hkUTFhCT03unx7LWtYI5BG5o+
QCVuzU8kMeiOFkQ=
-----END CERTIFICATE-----

You can trust this by setting up a SSLContext:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream certFile = new FileInputStream("mycert.crt");
Certificate ca = cf.generateCertificate(certFile); // this is java.security.cert.Certificate;

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

TrustManager trustManager = TrustManagerUtils.getDefaultTrustManager(keyStore);
SSLContext sslContext = SSLContextUtils.createSSLContext("TLS", null /*keyManager*/, trustManager);

Here the certificate above is placed on mycert.crt file on java work directory. On SSLContextUtils.createSSLContext the keyManager param is set to null because we don’t need present any private keys. The TrustManagerUtils and SSLContextUtils came from commons-net package so you’ll need to add that dependency to your pom.xml:


  commons-net
  commons-net
  3.3

SSLContext has a getSocketFactory() method which you can use to setup a SSLSocket which will verify against mycert.crt

SSLSocketFactory socketFactory = sslContext.getSocketFactory();
Socket socket = socketFactory.createSocket("dev.mycompany.com", 1234);

You can also pass SSLContext directly to some other libraries for it to trust your cert, below is ftps example using commons-net

FTPSCLient ftps = new FTPSClient(true, sslContext);