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.
Related
I have connection to TCP server (ip,port) to which meter is connected. I'd like to read the specified data from this port because when I'm using standard read method it sends me the whole data stream which takes about 15 minutes to read. So my question: is there any method I can use to get one specified register's value using his OBIS code (1.1.1.8.0.255 - active energy taken) in java via TCP server?
import java.net.*;
import java.io.*;
public class scratch {
public static void main(String[] args) {
String hostname = "ip (hidden)";
int port = port (hidden);
try (Socket socket = new Socket(hostname, port)) {
OutputStream out = socket.getOutputStream();
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
int character;
StringBuilder data = new StringBuilder();
String test = "/?!\r\n";
byte[] req = test.getBytes();
out.write(req);
while ((character = reader.read()) != '\n') {
data.append((char) character);
}
System.out.println(data);
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
}
}
The message "test" send initiation request to meter and his respond is correct but I dont' know how to put flags (ACK STX ETX) in my request, I've tried something like this:
String test2 = (char)0x6 + "051\r\n";
byte[] req2 = test2.getBytes("ASCII");
out.write(req2);
But meter doesn't recognize it.
I have written a simple e-mail client in java without using the JavaMail API, as by what I read from the documentation it seems necessary to split the messages up into head and body and in the single MIME-parts for sending which would make my application a lot more complicated. Everything worked fine for a SSL port (465) but now I'm trying to use the client with a different provider that only supports STARTTLS on port 587. The following code is of a class I wrote to test the access to the server.
private static DataOutputStream dos; //Streams to communicate with the server
private static DataInputStream dis;
public static void main(String[] args) {
try {
Socket socket = new Socket("mail.arcor.de", 587);
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
new Thread(() -> {readInputRun();}).start(); //see below, every input from the server is printed to the standard output.
dos.write(("EHLO " + InetAddress.getLocalHost().getHostAddress() + "\r\n").getBytes());
dos.write("STARTTLS\r\n".getBytes());
SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(socket, "mail.arcor.de", 587, true);
dos = new DataOutputStream(sslSocket.getOutputStream());
dis = new DataInputStream(sslSocket.getInputStream());
sslSocket.startHandshake();
dos.write(("EHLO " + InetAddress.getLocalHost().getHostAddress() + "\r\n").getBytes());
dos.write("QUIT\r\n".getBytes());
Thread.sleep(5000);
dis.close();
dos.close();
socket.close();
} catch(Exception e) {
e.printStackTrace();
}
}
private static void readInputRun() {
try {
int input;
while((input = dis.read()) >= 0) {
System.out.print((char) input);
}
} catch(Exception e) {
e.printStackTrace();
}
}
Every time I execute it, I get the following exception:
javax.net.ssl.SSLException: Unsupported or unrecognized SSL message
at java.base/sun.security.ssl.SSLSocketInputRecord.handleUnknownRecord(SSLSocketInputRecord.java:416)
at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:173)
at java.base/sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1031)
at java.base/sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
at java.base/sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1402)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1429)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at accessTest.AccessTestSTARTTLS.main(AccessTestSTARTTLS.java:31)
It is thrown at line 31, which is 'sslSocket.startHandshake();', so somehow the handshake does not work out. Do I initiate it at the wrong point or in the wrong way?
Thanks in advance for any help.
EDIT: As suggested in the comment, I enabled the logs and found the following:
httpslog. In the fifth but last line there is an unreadable character, obviously as part of the client hello, so my computer sends it. Why is this the case and how can I stop that?
To be clear, the main intention behind this answer is to mark the question as answered, because actually the solution is found in the comments to the question. The problem lies in the readInputRun() that reads part of the ServerHello, so letting the reading thread interrupt itself before the handshake and restarting it after it solves it:
dos.write("STARTTLS\r\n".getBytes());
SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(socket, "mail.arcor.de", 587, true);
dos = new DataOutputStream(sslSocket.getOutputStream());
dis = new DataInputStream(sslSocket.getInputStream());
sslSocket.startHandshake();
new Thread(() -> {readInputRun();}).start();
dos.write(("EHLO " + InetAddress.getLocalHost().getHostAddress() + "\r\n").getBytes());
dos.write("QUIT\r\n".getBytes());
and:
private static void readInputRun() {
try {
int input;
String allInput = "";
while((input = dis.read()) >= 0) {
allInput += (char) input;
System.out.print(allInput.charAt(allInput.length() - 1));
if(allInput.endsWith("Start TLS\r\n")) {
break;
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
I'm using a socket to connect my client with the server, I need a way so that when somebody tries to login on the client with an account, it sends the username and password to the server, and checks if the account exists. I just need to know how to make it send the message to the server when they press login.
i tried this to make it send a message to the server
public static void sendmsg(String a, String b)
{
try
{
String host = "127.0.0.1";
int port = 43655;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String sendMessage = a;
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+sendMessage);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " +message);
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
//Closing the socket
try
{
socket.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
nice you are working with Sockets, well I have an approach you can try, and maybe if it is useful you can consider for your implementation.
First of all I will create an entity to handle those values and fill it with the incoming data.
class UserAuth {
private String username;
private String password;
//Consider here your getters and setters, I am not including them
}
I will use the entity as the parameter for the method while sending and maybe you can fill it as something like:
UserAuth attemptingUser = new UserAuth(...)
ObjectInputStream works fine for these kind of scenarios. If you still want to work with Strings, you can use BufferedReader and try to merge your username and password as one single String and use the .readLine() method to obtain (separated with commas), then use String methods such Split but I find that could take some more time, should be better if you handle it with an object. But it depends on the complexity you want to add to your application :).
class AuthClient {
public void sendMsg(UserAuth attemptingUser) {
String host = "localhost";
int port = 2055;
//1. Create the socket
Socket sender = new Socket(host, port);
//2. Create an object output stream to write the object into the stream
ObjectOutputStream outputWriter = new ObjectOutputStream(sender.getOutputStream());
//3. Write (send the object)
outputWriter.writeObject(attemptingUser);
//4. Close
outputWriter.close();
sender.close();
}
}
class AuthServer {
ServerSocket ss = new ServerSocket(2055);
public void receiveMsg() {
//1. Accept the connection
Socket conn = ss.accept();
//2. Receive the flow
ObjectInputStream readStream = new ObjectInputStream(conn.getInputStream());
//3. Read the object
UserAuth userReceived = readStream.readObject();
//4. Verify against file, db or whatever
if (userReceived.getUsername().equals("admin") && userReceived.getPassword().equals("admin")) {
//Authentication
}
}
}
(This is added as the part I edit for what you asked me in the comments)
public void sendMsg(String username, String password) {
String host = "localhost";
int port = 2055;
//1. Create the socket
Socket sender = new Socket(host, port);
//2. Create the UserAuth object based on the parameters you received
UserAuth myuser = new UserAuth();
myuser.setUsername(username);
myuser.setPassword(password);
//3. Follow same instructions for the creation of ObjectOutputStream...
ObjectOutputStream objectWriter = new ObjectOutputStream(sender.getOutputStream());
objectWriter.writeObject(myuser);
//That is what I would use if I keep your structure
}
If you want to keep your structure using Strings, I would simplify and reduce impact of I/O by using the String methods. Since you know you are always expecting user/password, I would merge your two params in one single String or use special char and on server side handle with StringTokenizer class. Or maybe handle with the "split" method. You have many options here.
So far, this will be my approach for the problem you are facing. Hope it helps somehow. Best regards and happy coding :).
What you have done looks OK to me but it all depends on what the server is expecting to receive. What is the terminating character as you have not sent one unless it's already contained within your String a variable.
If the server is expecting an end of line character (which you don't currently send) you can use a PrintWriter instead of a BufferedWriter like this
pw = new PrintWriter(socket.getOutputStream(), true);
pw.println(a);
Your server would then be doing something like this
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String value = br.readLine();
At the moment I'm trying to develop an Android Application for Instant Messaging. I want to use ejabberd for this on an Ubuntu Server. There is just one problem.
When I try to connect to my ejabberd first with this xml-line:
<stream:stream to='x.x.x.x' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
it takes very long to receive the answer (about 20 seconds, sometimes longer).
I just have this problem, when I send some "good" data to the Server. Sending some "bad" data, i receive the Error message very fast.
It's performed by an Android IntentService
I will Post my Code here too:
the attributes:
private Socket socket;
private String host = "x.x.x.x";
private int port = 5222;
private OutputStream out = null;
private String in = null;
the doInBackground():
this.socket = new Socket(host,port);
if(!this.socket.isConnected()){
Log.e("Socket","Socket nicht geöffnet");
}else{
Log.e("Socket","Socket erfolgreich geöffnet");
//create output stream
try {
this.out = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
//write to output stream
StringBuffer stringbuffer = new StringBuffer();
stringbuffer.append("<stream:stream to='5.175.8.41' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>");
//convert into bits and give it to outputstream
try {
this.out.write(String.valueOf(stringbuffer).getBytes("UTF-8"),0,String.valueOf(stringbuffer).getBytes().length);
out.flush();
Log.e("Connecting-out","Erstes Tupel erfolgreich gesendet.");
} catch (IOException e) {
e.printStackTrace();
}
//receive the answer from server
try {
Log.e("lol","lol");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"),200);
StringBuilder builder = new StringBuilder();
String aux;
aux = in.readLine();
this.in = builder.toString();
Log.e("...",aux);
} catch (IOException e) {
e.printStackTrace();
}
Log.e("Connecting-in",in);
i think especially these lines
StringBuilder builder = new StringBuilder();
String aux;
aux = in.readLine();
this.in = builder.toString();
take very long. But the strange thing is , that the Error message is read very fast. So it has to be the Server?
Can someone please help me?
Thanks in advance :)
You used readLine() and it waits for new line character.
On error, server generally disconnects the connection.
It is why you get error answer immediately.
I suggest you not using readLine().
i have this assignment where i am supposed to write a proxy server that uses java sockets to handle get requests from a client. I am now stuck and have been looking all over google to find the answer but without success.
Christoffers solution helped my with my first problem. Now that i have updated the code this is what i am using.
The problem is that it only downloads parts of most webpages before it gets stuck on sending the packets back to the client loop. At the moment I cant explain why it is behaving the way it is.
public class MyProxyServer {
//Set the portnumber to open socket on
public static final int portNumber = 5555;
public static void main(String[] args){
//create and start the proxy
MyProxyServer myProxyServer = new MyProxyServer();
myProxyServer.start();
}
public void start(){
System.out.println("Starting MyProxyServer ...");
try {
//create the socket
ServerSocket serverSocket = new ServerSocket(MyProxyServer.portNumber);
while(true)
{
//wait for a client to connect
Socket clientSocket = serverSocket.accept();
//create a reader to read the instream
BufferedReader inreader = new BufferedReader( new InputStreamReader(clientSocket.getInputStream(), "ISO-8859-1"));
//string builder for preformance when we loop over the inputstream and read lines
StringBuilder builder = new StringBuilder();
String host = "";
for (String buffer; (buffer = inreader.readLine()) != null;) {
if (buffer.isEmpty()) break;
builder.append(buffer.replaceAll("keep-alive", "close"));
if(buffer.contains("Host"))
{
//parse the host
host = buffer.replaceAll("Host: ", "");
}
System.out.println(buffer);
}
String req = builder.toString();
System.out.println("finshed reading \n" + req);
System.out.println("host: " + host);
//new socket to send the information over
Socket s = new Socket(InetAddress.getByName(host), 80);
//printwriter to send text over the output stream
PrintWriter pw = new PrintWriter(s.getOutputStream());
//send the request from the client
pw.println(req+"\r\n");
pw.flush();
//create inputstream to receive the web page from the host
BufferedInputStream in = new BufferedInputStream(s.getInputStream());
//create outputstream to send the web page to the client
BufferedOutputStream outbuffer = new BufferedOutputStream(clientSocket.getOutputStream());
byte[] bytebuffer = new byte[1024];
int bytesread;
//send the response back to the client
while((bytesread = in.read(bytebuffer)) != -1) {
System.out.println(bytesread);
outbuffer.write(bytebuffer,0, bytesread);
outbuffer.flush();
}
System.out.println("done sending");
//close the streams
inreader.close();
s.close();
pw.close();
outbuffer.close();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch(RuntimeException e){
e.printStackTrace();
}
}
}
If anyone could explain to me why i cant get it working correctly and how to solve it I would be very grateful!
Thanks in advance.