How to use FTPSClient and keys in PuTTY format - java

I need to connect to remote server via FTPS (implicit or explicit). I successfully connected to server via FileZilla. Also I tested code to retrieve file from public ftp: ftp.mozilla.org
Now I need the same code for ftps. I have problem with private key and KeyStore
String keyPath = "src/test/resources/keys/thekey.ppk";
FTPSClient client = new FTPSClient();
FileOutputStream fos = null;
try {
KeyStore ks = KeyStore.getInstance("JKS"); //
FileInputStream fis = new FileInputStream(keyPath);
ks.load(fis, "".toCharArray());//java.io.IOException: Invalid keystore format
fis.close();
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
.getDefaultAlgorithm());
kmf.init(ks, "".toCharArray());
System.out.println("connecting to 1.1.1.1...");
client.setDefaultTimeout(10000);
client.connect("1.1.1.1", 2190);
System.out.println("loggin in...");
System.out.println("login: " + client.login("login", "pass"));
String remoteDir = "/pub/downloaded/";
String remoteFileName = "testMsg.txt";
String localFileName = "testMsg.local.txt";
fos = new FileOutputStream(localFileName);
System.out.println("retrieving file...");
boolean isRetrieved = client.retrieveFile(remoteDir + remoteFileName, fos);
System.out.print("File: " + remoteDir + remoteFileName + "; IsRetrieved: " + isRetrieved + "\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
Keys were generated in PuTTY format. What else options can I put here KeyStore.getInstance("JKS").
If ommit the part with KeyStore than code reach line with client.retrieveFile and suspends for a long time.
Need help to import keys, plz.

FTPS stands for FTP-over-SSL. SSL uses X.509 certificates for authentication (we omit other rarely used methods now). Putty is SSH/SFTP client (where SFTP stands for SSH File Transfer Protocol) and putty keys are SSH keys. Consequently you can't use SSH keys for SSL authentication.

Related

Why does my TCP connection lock up over OpenVPN?

Problem
I'm transferring a file that's from 1Mb to 100Mb over a TCP connection from Android 4.4.4 client to a server using java.net.socket and javax.net.ssl.SSLSocket. Without OpenVPN it works as expected, but with it java.net.socket TCP connection locks up every time at the end while javax.net.ssl.SSLSocket locks up sometimes.
My current solution to this problem is to change the "buffer size" to 10 bytes (see code) on client side.
I already tried changing the MTU, MSSFIX and FRAGMENT values in OpenVPN configuration file.
Set Up
I've made a local network with a WiFi compatible router. Router is not connected to the internet. My Android client is connect via WiFi. I have an eth connection to my computer on which I'm running my java server and Xubuntu on virtualbox with openvpn. Virtualbox is connected with a bridge adapter. Android client can connect to openvpn server and can ping other clients on the network. The current MTU on all machines is 1500 (default).
Goal
I'm benchmarking the time impact of OpenVPN on plain text and secure socket connections.
Questions
Why does my plain text transfer fails every time, but secure socket transfers fails sometimes?
Why does changing the "buffer size" solves my problem?
If I set the "buffer size" to 10 bytes and send the data over secure socket I will receive 10 bytes at the server side. But if I send the data with the same buffer size over plain socket I receive more than 10 bytes. Is this the result of padding?
Is there a better way of transferring data from Android to a server via sockets?
Client Code (Plain text)
protected void nonsecure_transfer(String ip, int port, int fileno) {
Socket sock;
try {
sock = new Socket(ip, port);
// sendfile
final InputStream is;
switch (fileno){
case 0:
is = getResources().openRawResource(R.raw.test1mb);
break;
case 1:
is = getResources().openRawResource(R.raw.test10mb);
break;
case 2:
is = getResources().openRawResource(R.raw.test100mb);
break;
default: is = getResources().openRawResource(R.raw.test1mb);
break;
}
BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());
int buffer_size = Integer.parseInt(buffersize.getText().toString());
byte buffer[] = new byte[buffer_size];
int count = 0;
while ((count = is.read(buffer)) > 0) {
os.write(buffer, 0, count);
}
os.flush();
sock.close();
} catch (UnknownHostException e) {
log.append("Error \n" + e);
} catch (IOException e) {
log.append("Error \n" + e);
}
Server Code (Plain text)
protected void handleConnection(Socket server) throws Exception {
InputStream is = server.getInputStream();
FileOutputStream fos = new FileOutputStream(...);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte buffer[] = new byte[8129];
int count = 0;
int size = 0;
while ((count = is.read(buffer)) > 0)
{
bos.write(buffer, 0, count);
}
bos.flush();
bos.close();
is.close();
}
Client Code (Secure)
protected void secure_transfer(String ip, int port, int fileno) throws IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, KeyManagementException {
String passphrase = "test123";
KeyStore ks = KeyStore.getInstance("BKS");
InputStream keyin = getResources().openRawResource(R.raw.server_keystore);
ks.load(keyin, "test123".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
clientKeyStore.load(getResources().openRawResource(R.raw.client_keystore), passphrase.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientKeyStore, passphrase.toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket)
socketFactory.createSocket(new Socket(ip, port), ip, port, false);
socket.startHandshake();
try {
// sendfile
final InputStream is;
switch (fileno){
case 0:
is = getResources().openRawResource(R.raw.test1mb);
break;
case 1:
is = getResources().openRawResource(R.raw.test10mb);
break;
case 2:
is = getResources().openRawResource(R.raw.test100mb);
break;
default: is = getResources().openRawResource(R.raw.test1mb);
break;
}
BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream());
int buffer_size = Integer.parseInt(buffersize.getText().toString());
byte buffer[] = new byte[buffer_size];
int count = 0;
while ((count = is.read(buffer)) > 0) {
os.write(buffer, 0, count);
}
os.flush();
socket.close();
} catch (UnknownHostException e) {
log.append("Error \n" + e);
} catch (IOException e) {
log.append("Error \n" + e);
}
}
Server Code (Secure)
public void listen() throws Exception {
try {
String passphrase = "test123";
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("server_keystore.jks"),"test123".toCharArray());
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, "test123".toCharArray());
SSLContext sslcontext =
SSLContext.getInstance("TLS");
sslcontext.init(kmf.getKeyManagers(), null, null);
ServerSocketFactory ssf =
sslcontext.getServerSocketFactory();
SSLServerSocket serverSocket = (SSLServerSocket)
ssf.createServerSocket(9999);
while (true) {
SSLSocket s = (SSLSocket) serverSocket.accept();
handleConnection(s);
s.close();
}
} catch (IOException ioe) {
System.out.println("IOException: " + ioe);
ioe.printStackTrace();
System.exit(1);
} catch (GeneralSecurityException e) {
System.out.println("GeneralSecurityException: " + e);
e.printStackTrace();
System.exit(1);
}
}
int packet = 0;
protected void handleConnection(Socket server) throws Exception {
InputStream is = server.getInputStream();
FileOutputStream fos = new FileOutputStream(...);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte buffer[] = new byte[8129];
int count = 0;
int size = 0;
while ((count = is.read(buffer)) > 0)
{
bos.write(buffer, 0, count);
}
bos.flush();
bos.close();
is.close();
}
OpenVPN config
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh2048.pem
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
;client-to-client
;duplicate-cn
keepalive 10 120
tls-auth ta.key 0 # This file is secret
key-direction 0
cipher AES-128-CBC # AES
auth SHA256
;comp-lzo
persist-key
persist-tun
mssfix 1500
Link Info (xubuntu - openvpn)
enp0s3 Link encap:Ethernet HWaddr 08:00:27:19:55:dc
inet addr:192.168.1.216 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fdbb:8432:3a7c:0:3290:af79:3a93:dcfd/64 Scope:Global
inet6 addr: fe80::c133:9666:4062:e40f/64 Scope:Link
inet6 addr: fdbb:8432:3a7c::52c/128 Scope:Global
inet6 addr: fdbb:8432:3a7c:0:f8b3:90c2:1d8f:f21e/64 Scope:Global
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:162659 errors:0 dropped:0 overruns:0 frame:0
TX packets:63868 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:214361110 (214.3 MB) TX bytes:18496915 (18.4 MB)
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.8.0.1 P-t-P:10.8.0.2 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:9932 errors:0 dropped:0 overruns:0 frame:0
TX packets:7518 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:13666203 (13.6 MB) TX bytes:423228 (423.2 KB)
Link Info (java server)
en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 00:26:08:e8:d3:36
inet 192.168.1.194 netmask 0xffffff00 broadcast 192.168.1.255
media: autoselect
status: active

JSchException: UnknownHostKey

I'm trying to use Jsch to establish an SSH connection in Java.
I have set "StrictHostKeyChecking" to yes. I understand that the hostkey of the server has to be obtained before hand and store in the hostkey file
before the first attempt to connect to the server. How can I get the HostKey of the server. My code produces the following exception:
com.jcraft.jsch.JSchException: UnknownHostKey: ASY-PC
RSA key fingerprint is 22:fb:ee:fe:18:cd:aa:9a:9c:78:89:9f:b4:78:75:b4
How can I make connection with StrictHostKeyChecking Yes.
Here is my code.
package sshexample;
import com.jcraft.jsch.*;
import java.io.*;
public class SSHexample
{
public static void main(String[] args)
{
String user = "user";
String password = "password";
String host = "192.168.100.103";
int port=22;
try
{
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "yes");
System.out.println("Establishing Connection...");
session.connect();
System.out.println("Connection established.");
System.out.println("Crating SFTP Channel.");
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
}catch(Exception e) {
e.printStackTrace();
}
}
You have to supply a KnownHostKeys file by calling following function
jsch.setKnownHosts(new FileInputStream(knownHostsFile));
this file should have all the the known hosts' fingerprints separated by new lines.
for example
hostname,10.1.1.120, ssh-rsa AAAAC3NzaC1yc2EAAAADAQABAAABAQCi5b647581SwC0uUDQw1ENjKSz3rhJMRRZEgIjHylvF4fbuAEzj645YoAf9SItb51MhetFAJrq98jYsHpedSm3IoMG+aR/P1CjsBz1RtJKlfR2NfYDCZ7Dyx11P8FnJbwbYif/GeG0xEujekwF1pyL0tNPmf0H4/GPR4mwrv/llGlB3Lo3BzxrGtl4f4X/oSHDoo7FrQkDwqOfeSM++3vPPHxyVO5zhFJ5u9f7M/uuxUeHS+YS5JWAI7NLXKgbiM9dluGzZU/6Awo3ux4x5ojL+kf29JEVxK+o6GfW2bIW+LhgIGZNThnN5nHzBVfNNHvQ7KC5ic0h2z2gbVpwJr1h
you can obtain this key from server by using any sftp client however following command may help if you are using linux or unix
ssh-keyscan -t rsa 10.1.1.120
After a few minutes of testing i found a solution for this. If you don't want to use the default knownHost File, just create your own
This how the file could look:
192.168.0.1 ssh-rsa
AAAAC3NzaC1yc2EAAAADAQABAAABAQCi5b647581SwC0uUDQw1ENjKSz3rhJMRRZEgIjHylvF4fbuAEzj645YoAf9SI
tb51MhetFAJrq98jYsHpedSm3IoMG+aR/P1CjsBz1RtJKlfR2NfYDCZ7Dyx11P8FnJbwbYif
/GeG0xEujekwF1pyL0tNPmf0H4/GPR4mwrv/llGlB3Lo3BzxrGtl4f4X
/oSHDoo7FrQkDwqOfeSM++3vPPHxyVO5zhFJ5u9f7M/uuxUeHS+YS5JWAI7NLXKgbiM9dluGzZU
/6Awo3ux4x5ojL+kf29JEVxK+o6GfW2bIW+LhgIGZNThnN5nHzBVfNNHvQ7KC5ic0h2z2gbVpwJr1h
And all those entries are separated by new lines. You get the RSA key that you want by asking your session:
session=null;
com.jcraft.jsch.Channel channel =null;
try{
ssh=new JSch();
ssh.setKnownHosts("test");
session=ssh.getSession(userTextField.getText(),ip,22);
session.setPassword(passwordField1.getText());
System.out.println(session.getHostKey());
session.connect();
channel=session.openChannel("sftp");
channel.connect();
ChannelSftp sftp=(ChannelSftp) channel;
System.out.println(sftp.getHome());
for (Object o : sftp.ls(sftp.getHome())) {
System.out.println(((ChannelSftp.LsEntry)o).getFilename());
}
} catch (JSchException e1) {
e1.printStackTrace();
addHost(session.getHostKey().getKey());
} catch (SftpException e1) {
e1.printStackTrace();
}
}
private void addHost(String key){
try {
FileWriter tmpwriter=new FileWriter("test",true);
tmpwriter.append(ip + " ssh-rsa " + key+"\n");
System.out.println(ip + " ssh-rsa " + key);
tmpwriter.flush();
tmpwriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
So session.getHostKey().getKey() is what you want to call to get the key.
You also need to call session.connect(); before you ask for the key and handle it in the catch.
As most the of the answers suggest you have to provide know host file but fail to address how to get it. You simply need to SSH to the host.
Eg ssh user#192.168.100.103
when prompted provide password. For first time connection it will you to save the hosts ssh key fingerprint. Once you are connected you can find your known_host file at
user/.ssh/known_hosts
For me on windows path is C:\Users\athakur\.ssh\known_hosts. You can directly use this file. Or edit the file and pick up entry from it corresponding to your IP address which would look something like
192.168.100.103 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA1UsgiLH5hjIScZlqPA4kNhPoXAX00mMv65N8qTvYd1D1M5DwWtTTcxK4w0wGKKVA7RERzWbtjPpSomJwT1LofZr+qafLdiEvhirIXVYHSWZqp6zTJW0jzk3p07ugjoHV3YUWKDzOaiFuOMslt8hD7pZv8nhOYfxBZdsVHdukYRP8MADXC0ZgOD5ZYZ0EglaQJYPG7n73PSMZWZT/oafUcx6bFiRF4QsXaguWuu6umX9gaV7VvoyMJg+kxPAKnGDFY7If61AG7vAchUUhlQ44SB1FFr25y+qeUg2NGqAxH/Z/ZAfvZ+pDv3Cd9s+KCnEIqxyxY/sPQ2zCvwf0Z9fTeQ==
Note : Host machines SSH fingerprint (based on hosts public key that you can find at /etc/ssh/ssh_host_rsa_key.pub) may change in SSH is reinstalled in that machine. Or you may encounter MIM attack (even it is for testing sake). In such cases you will have to pick new entry in same way mentioned above.
Maybe it's no more relevant but in my case, the similar problem was happened with docker-compose.yml in container, that was build from spring-boot application that 100 % worked locally
config-service:
image: <host>/<bla>-config-service:<version>
hostname: config-service
ports:
- 3000:3000
depends_on:
- discovery
environment:
- CONSUL_HOST=discovery
- CONSUL_PORT=<port>
- CONFIG_GIT_URI=git#<host>:<group>/<repository>.git
- CONFIG_GIT_BRANCH=development
volumes:
- ~/.ssh/:/root/.ssh/:ro
Solution was to apply hack on ~/.ssh folder.
chcon -Rt svirt_sandbox_file_t ~/.ssh
After that I suppose volumes was correctly mapped between docker container and local machine, and described exception was gone.
Based on #nothing-to-know answer, the following method can be very handy:
public static String getHostKey(String hostName, int port, String userName, char[] password) {
JSch ssh;
Session session = null;
String hostKey = "";
try {
ssh = new JSch();
session = ssh.getSession(userName, hostName, port);
session.setPassword(new String(password));
if (session.getHostKey() != null) {
hostKey = session.getHostKey().getHost() + " " + session.getHostKey().getType() + " " + session.getHostKey().getKey();
}
session.connect();
} catch (JSchException e1) {
hostKey = session.getHostKey().getHost() + " " + session.getHostKey().getType() + " " + session.getHostKey().getKey();
} finally {
session.disconnect();
return hostKey;
}
}

Issues with apache commons ftp client timeout

I'm doing a ftp file download from a server with help from an Apache library (commons.net ver 3.2). The download was fine and I received all the file that I needed and saved them in a folder. The problem that I have is with the timeouts because when the connection is interrupted while I'm downloading I need an error message that shows me that the connection has been lost, but I have found difficulties doing this, I have searched countless forums including this one and I have tried many ways to solve this but no one have result yet! The code that I have is as follows:
public void doSomething(String ip, int port, String user, String pass, String server, String remotePath, String localPath) {
int tenseconds = 10 * 1000;
int thirtyseconds = 30 * 3000;
Socket s4 = new Socket();
java.net.InetSocketAddress adr = new java.net.InetSocketAddress("213.0.17.234", 21);
s4.connect(adr, thirtyseconds);
FTPClient client = new FTPClient();
org.apache.commons.vfs2.FileSystemOptions fileSystemOptions = null;
String key = FtpFileSystemConfigBuilder.getInstance().getEntryParser(fileSystemOptions);
try {
client.setConnectTimeout(tenseconds);
client.setDefaultTimeout(thirtyseconds);
client.connect(ip, port);
client.setSoTimeout(thirtyseconds);
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
throw new FileSystemException("vfs.provider.ftp/connect-rejected.error");
}
client.enterLocalPassiveMode();
boolean login = client.login(user, pass);
URL url = new URL("ftp://" + user + ":" + pass + "#" + server + remotePath + ";type=i");
URLConnection urlc = url.openConnection();
urlc.setConnectTimeout(1000);
InputStream is = urlc.getInputStream();
BufferedWriter bw = new BufferedWriter(new FileWriter(localPath));
int c;
client.setSoTimeout(tenseconds);
client.setControlKeepAliveTimeout(10000);
while ((c = is.read()) != -1) {
urlc.getConnectTimeout();
bw.write(c);
}
long t2 = System.currentTimeMillis();
System.out.println(t2);
JOptionPane.showMessageDialog(null, "se cargo el primer fichero!", "información", JOptionPane.INFORMATION_MESSAGE);
if (login) {
FTPFile[] files = client.listFiles();
for (FTPFile file : files) {
if (file.getType() == FTPFile.DIRECTORY_TYPE) {
System.out.println("ftp file: " + file.getName() + ";" + FileUtils.byteCountToDisplaySize(file.getSize()));
} else if (file.getType() == FTPFile.FILE_TYPE) {
System.out.println("ftp file: " + file.getName() + ";" + FileUtils.byteCountToDisplaySize(file.getSize()));
}
}
is.close();
bw.close();
client.setSoTimeout(tenseconds);
client.logout();
client.disconnect();
}
} catch (IOException e) {
StringWriter sw0 = new StringWriter();
PrintWriter p0 = new PrintWriter(sw0, true);
e.printStackTrace(p0);
System.out.println("connection probably lost");
JOptionPane.showMessageDialog(null, "Error: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
I have tried all the things a could find a have read that the setdefaulttimeout is used to activate all the timeouts, connectiontiomeout is used to wait for connections and getsotimeouts is used when we are downoading a file but it doesn't work I have tried give it 5 seconds so it will not download the file but it doesn't work, I have read that there are some issues whit connectiontimeouts and that we should use socketfactory, so I creaded a socket factory as well and I tried but it didn't work and I have reach a point where I'm a little bit desperade so I´m asking you for help I all so tried client.setControlKeepAliveTimeout(10000); to establish an alive timeout but it didn't work! :(

Java - Sending certificate through socket

i need to send a v3certificate from the server to the client using socket.
To do this:
server side, i generate a certificate which i encode with base64.encode , then i send it to the client.
Client side, i receive the string which contain the certificate,
Server code:
X509Certificate certificate = ...;
sendAnswer(new String(certificate.getEncoded()));
public static void sendAnswer(String ans) {
try {
s.shutdownInput();
PrintWriter output = new PrintWriter(s.getOutputStream(), true);
output.println(new String(Base64.encode(ans.getBytes())));
output.close();
} catch (IOException ex) {
Logger.getLogger(serverThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
Client code
String value = sendMessage(..);//method which receive the certificate from the server
InputStream inStream = null;
X509Certificate cert=null;
inStream = new ByteArrayInputStream(value.getBytes());
CertificateFactory cf = CertificateFactory.getInstance("X.509","BC");
cert = (X509Certificate)cf.generateCertificate(inStream);
public static String sendMessage(String url, int port, String tag, byte[] mex1) {
Socket link;
String reply = "";
byte[] replyDec = null;
link = new Socket(InetAddress.getByName(url), port);
InputStream i = null;
try {
i = link.getInputStream();
} catch (IOException ex) {
Logger.getLogger(ClientApp.class.getName()).log(Level.SEVERE, null, ex);
}
Scanner input = new Scanner(i);
while (input.hasNextLine()) {
reply += input.nextLine();
}
replyDec = Base64.decode(reply);
input.close();
link.close();
return new String(replyDec);
}
Almost everything works, in the client side if i print the string i receive i get a text which contain extra character and the certificate data. But it gives me an error when creating the certificate, client side.
This is the error:
java.security.cert.CertificateException: java.io.IOException: DER length more than 4 bytes: 111
at org.bouncycastle.jce.provider.JDKX509CertificateFactory.engineGenerateCertificate(Unknown Source)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:322)
and this is the line from which it comes from
cert = (X509Certificate) cf.generateCertificate(inStream);
Anyone can help me?
Thanks in advance
Throw it all away and use SSL, which already does all that.
You can send the certificate through socket by stream of bytes:
in sender side after configuration of socket:
ObjectOutputStream toServer;
toServer = new ObjectOutputStream(socket.getOutputStream());
byte[] frame = theCertificate.getEncoded();
toServer.writeObject(frame);
in receiver side after configuration of socket:
ObjectInputStream fromClient;
fromClient = new ObjectInputStream(socket.getInputStream());
byte[] cert = fromClient.readObject();
java.security.cert.Certificate jsCert = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(cert));
now you can use this certificate. for example as retrieving the public key:
PublicKey thepublicKey = jsCert.getPublicKey();
It looks possible that your problem might be due to using a PrintWriter to send, and possibly something different to read (scanner). You could try using a StringWriter and StringReader to have a match at either end and then also you can debug if what you send is a perfect match for what you receive.

Reading a remote file using Java

I am looking for an easy way to get files that are situated on a remote server. For this I created a local ftp server on my Windows XP, and now I am trying to give my test applet the following address:
try
{
uri = new URI("ftp://localhost/myTest/test.mid");
File midiFile = new File(uri);
}
catch (Exception ex)
{
}
and of course I receive the following error:
URI scheme is not "file"
I've been trying some other ways to get the file, they don't seem to work. How should I do it? (I am also keen to perform an HTTP request)
You can't do this out of the box with ftp.
If your file is on http, you could do something similar to:
URL url = new URL("http://q.com/test.mid");
InputStream is = url.openStream();
// Read from is
If you want to use a library for doing FTP, you should check out Apache Commons Net
Reading binary file through http and saving it into local file (taken from here):
URL u = new URL("http://www.java2s.com/binary.dat");
URLConnection uc = u.openConnection();
String contentType = uc.getContentType();
int contentLength = uc.getContentLength();
if (contentType.startsWith("text/") || contentLength == -1) {
throw new IOException("This is not a binary file.");
}
InputStream raw = uc.getInputStream();
InputStream in = new BufferedInputStream(raw);
byte[] data = new byte[contentLength];
int bytesRead = 0;
int offset = 0;
while (offset < contentLength) {
bytesRead = in.read(data, offset, data.length - offset);
if (bytesRead == -1)
break;
offset += bytesRead;
}
in.close();
if (offset != contentLength) {
throw new IOException("Only read " + offset + " bytes; Expected " + contentLength + " bytes");
}
String filename = u.getFile().substring(filename.lastIndexOf('/') + 1);
FileOutputStream out = new FileOutputStream(filename);
out.write(data);
out.flush();
out.close();
You are almost there. You need to use URL, instead of URI. Java comes with default URL handler for FTP. For example, you can read the remote file into byte array like this,
try {
URL url = new URL("ftp://localhost/myTest/test.mid");
InputStream is = url.openStream();
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int n;
while ((n = is.read(buf)) >= 0)
os.write(buf, 0, n);
os.close();
is.close();
byte[] data = os.toByteArray();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
However, FTP may not be the best protocol to use in an applet. Besides the security restrictions, you will have to deal with connectivity issues since FTP requires multiple ports. Use HTTP if all possible as suggested by others.
I find this very useful: https://docs.oracle.com/javase/tutorial/networking/urls/readingURL.html
import java.net.*;
import java.io.*;
public class URLReader {
public static void main(String[] args) throws Exception {
URL oracle = new URL("http://www.oracle.com/");
BufferedReader in = new BufferedReader(
new InputStreamReader(oracle.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}
This worked for me, while trying to bring the file from a remote machine onto my machine.
NOTE - These are the parameters passed to the function mentioned in the code below:
String domain = "xyz.company.com";
String userName = "GDD";
String password = "fjsdfks";
(here you have to give your machine ip address of the remote system, then the path of the text file (testFileUpload.txt) on the remote machine, here C$ means C drive of the remote system. Also the ip address starts with \\ , but in order to escape the two backslashes we start it \\\\ )
String remoteFilePathTransfer = "\\\\13.3.2.33\\c$\\FileUploadVerify\\testFileUpload.txt";
(here this is the path on the local machine at which the file has to be transferred, it will create this new text file - testFileUploadTransferred.txt, with the contents on the remote file - testFileUpload.txt which is on the remote system)
String fileTransferDestinationTransfer = "D:/FileUploadVerification/TransferredFromRemote/testFileUploadTransferred.txt";
import java.io.File;
import java.io.IOException;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.Selectors;
import org.apache.commons.vfs.UserAuthenticator;
import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.auth.StaticUserAuthenticator;
import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
public class FileTransferUtility {
public void transferFileFromRemote(String domain, String userName, String password, String remoteFileLocation,
String fileDestinationLocation) {
File f = new File(fileDestinationLocation);
FileObject destn;
try {
FileSystemManager fm = VFS.getManager();
destn = VFS.getManager().resolveFile(f.getAbsolutePath());
if(!f.exists())
{
System.out.println("File : "+fileDestinationLocation +" does not exist. transferring file from : "+ remoteFileLocation+" to: "+fileDestinationLocation);
}
else
System.out.println("File : "+fileDestinationLocation +" exists. Transferring(override) file from : "+ remoteFileLocation+" to: "+fileDestinationLocation);
UserAuthenticator auth = new StaticUserAuthenticator(domain, userName, password);
FileSystemOptions opts = new FileSystemOptions();
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
FileObject fo = VFS.getManager().resolveFile(remoteFileLocation, opts);
System.out.println(fo.exists());
destn.copyFrom(fo, Selectors.SELECT_SELF);
destn.close();
if(f.exists())
{
System.out.println("File transfer from : "+ remoteFileLocation+" to: "+fileDestinationLocation+" is successful");
}
}
catch (FileSystemException e) {
e.printStackTrace();
}
}
}
I have coded a Java Remote File client/server objects to access a remote filesystem as if it was local. It works without any authentication (which was the point at that time) but it could be modified to use SSLSocket instead of standard sockets for authentication.
It is very raw access: no username/password, no "home"/chroot directory.
Everything is kept as simple as possible:
Server setup
JRFServer srv = JRFServer.get(new InetSocketAddress(2205));
srv.start();
Client setup
JRFClient cli = new JRFClient(new InetSocketAddress("jrfserver-hostname", 2205));
You have access to remote File, InputStream and OutputStream through the client. It extends java.io.File for seamless use in API using File to access its metadata (i.e. length(), lastModified(), ...).
It also uses optional compression for file chunk transfer and programmable MTU, with optimized whole-file retrieval. A CLI is built-in with an FTP-like syntax for end-users.
org.apache.commons.io.FileUtils.copyURLToFile(new URL(REMOTE_URL), new File(FILE_NAME), CONNECT_TIMEOUT, READ_TIMEOUT);
Since you are on Windows, you can set up a network share and access it that way.

Categories