Szyfrowane strumienie danych

0

Witam mam problem z tworzeniem szyfrowanych strumieni danych. Oto kod mojego serwera:

import java.io.*;
import java.net.*;
import java.security.*;
import java.sql.Time;
import java.util.concurrent.TimeUnit;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.NoSuchPaddingException;

public class Server 
{
	public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InterruptedException, ClassNotFoundException
	{
		new Server();
		System.out.println("stworzony obiekt");
	}
	public Server() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InterruptedException, ClassNotFoundException
	{
		ServerSocket ss = new ServerSocket(7500);
		ServerSocket ss2 = new ServerSocket(7600);
		Socket socket = ss.accept();
		ObjectInputStream ois = null;//new ObjectInputStream(socket.getInputStream());
		ObjectOutputStream ous = new ObjectOutputStream(socket.getOutputStream());
		System.out.println("Server - udalo sie");
		KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
		KeyPair pair = kpg.generateKeyPair();
		Key publiczny = pair.getPublic();
		Key prywatny = pair.getPrivate();
		ous.writeObject(publiczny);
		System.out.println("server - wyslalem klucz");
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, prywatny);
		try
		{
		ois = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipher));
		}catch(Exception e)
		{
			e.printStackTrace();
		}finally
		{
			System.out.println("server - wywalilo");
		}
		System.out.println("server - zrobilem strumien");
		while(true)
			ois.readObject();
	}
}

Program zatrzymuje mi się na instrukcji ois = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipher));.Output:

Server - udalo sie
server - wyslalem klucz

Co to moze byc? Jak rozlacze klienta pokazuje sie wyjatek i wyswietla kolejne dwa komunikaty

server - wywalilo
server - zrobilem strumien

Wiec nie jest to kwestia nieprzechwyconego wyjatku.Program po prostu zawiesza sie na konstruktorze strumienia wejsciowego. Z gory dzieki za pomoc. Pozdrawiam

0

Nie zaglebialem sie poki co ale na moje to Ty masz nieskonczona petle w konstruktorze Servera - jestes pewien ze tego chcesz?

0

Tak. To tylko taki maly programik ktory napisalem bo nie dzialalo mi to w duzo wiekszym projekcie, dlatego napisalem ten serwer zeby sprobowac w prostszym programie. Wykonanie programu nie dochodzi niestety do tej petli. Wszystko zatrzymuje sie na konstruktorze strumienia wejsciowego. Pozdrawiam

0

ObjectInputStream w konstruktorze czyta header (metoda readStreamHeader()), ObjectOutputStream ma metode writeStreamHeader - musisz po stronie klienta utworzyc new ObjectOutputStream(socket.getOutputStream()) - to zapisze 2 wartosci short do servera, i wtedy sie odblokuje. Mozesz tez zapisac jakiekolwiek inne wartoswci tam, wtedy server odczyta je i dostaniesz blad ze to nie jest poprawny format strumienia. Zasada jest taka - gdy wczytujesz ObjectInputStream, po drugiej stronie musi byc ObjectOutputStream.
Co do Twojego kodu i petli - zauwaz ze to nie zezwoli na wyjscie z konstruktora, czyli reszta metody main sie nie wykona. Jest to calkowicie zle.

0

Kodu klienta nie wklejalem bo problem mam z serwerem. Ale w kliencie tworze object output stream i o dziwo tam NIE MA problemu. A ta petla jest dlatego ze w kliencie zrobilem taka sama zapisujaca do strumienia poniewaz w przeciwnym wypadku w serwerze pojawial sie wyjatek EOFEception poniewaz byl on zawieszony na konstruktorze strumienia wejsciowego a klient po stworzeniu strumieni konczyl swoje dzialanie i dochodzilo do rozlaczenia. Zrobilem to w konstruktorze bo nie chciało mi się pisac nowej metody, poniewaz tak jak mowilem nie działa mi to w duzym programie i chciałem tutaj tylko sprawdzic czy sie uda. We właściwym programie odbieranie obiektow ma miejsce w osobnym watku. Pozdrawiam

0

Klient dziala bo nie czeka na nic, tylko zapisuje. Wklej kod klienta, ten ktory jest odpowiedzialny za polaczenie z serwerem to bedzie mozna cos wiecej powiedziec.

0

Oto kod klienta:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.*;
import java.security.*;
import java.util.concurrent.TimeUnit;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;


public class Klient 
{
	public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException
	{
		try {
			new Klient();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public Klient() throws UnknownHostException, IOException, ClassNotFoundException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InterruptedException
	{
		Socket socket = new Socket("localhost", 7500);
		ObjectOutputStream ous = new ObjectOutputStream(socket.getOutputStream());
		ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
		System.out.println("klient - udalo sie");
		Key pub = (Key)ois.readObject();
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, pub);

		try
		{
		ous = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipher));
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		System.out.println("klient - zrobilem strumien");
		while(true)
		{
			ous.writeObject(pub);
			TimeUnit.SECONDS.sleep(3);
		}
	}
}

Pozdrawiam

0

Zauwazylem ze jak usune new CipherInputStream to się łączy. Więc coś z tworzeniem tego szyfrowanego strumienia jest nietak.
Pozdrawiam

0

CipherOutputStream moze byc buforowany:

public void flush()
throws IOException

Flushes this output stream by forcing any buffered output bytes that have already been processed by the encapsulated cipher object to be written out.

Any bytes buffered by the encapsulated cipher and waiting to be processed by it will not be written out. For example, if the encapsulated cipher is a block cipher, and the total number of bytes written using one of the write methods is less than the cipher's block size, no bytes will be written out.

Moze to jest Twoj problem. Sprobuj dac flush(), ale to i tak moze nie pomoc.

0

Dalem flush w kliencie ale nie pomaga. W zasadzie zawiesza się na tworzeniu strumienia wejsciowego w serwerze wiec tak myslalem ze nie pomoze w tej chwili :/. Udalo mi się zrobic to z kluczem symetrycznym AES wiec cos z tym szyfrowaniem RSA jest nietak. Wolal bym jednak jakies szyfrowanie z kluczem publicznym.
Pozdrawiam

0

Witam. Postanowiłem w takim wypadku zastąpić klasę CipherOutputStream oraz CipherInputStream włąsnymi klasami. na razie zrobiłem klasę zapisującą:

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.ShortBufferException;

public class MyCoderOutputStream extends FilterOutputStream 
{
	public MyCoderOutputStream(OutputStream os, Cipher cipher)
	{
		super(os);
		this.os = os;
		this.cipher = cipher;
	}
	@Override
	public void write(int b) throws IOException {
		try {
			super.write(cipher.doFinal(cipher.update(new byte[]{(byte)b}))[0]);
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//@Override
	public void write(byte[] b) throws IOException {
		try {
			super.write(cipher.doFinal(cipher.update(b)));
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Override
	public void write(byte[] b, int off, int len) throws IOException {
		try {
			//System.out.println("Rozmiar b: " + b.length);
			byte[] nowe = new byte[b.length];
			int i = 0;
			for(; (nowe.length - i*117) >= 117 ; i++)
			{
				cipher.update(b, i*117, 117, nowe, i*117);
				cipher.doFinal(nowe, i*117, 117, nowe, i*117);
			}
			cipher.update(b, i*117, b.length%117, nowe, i*117);
			cipher.doFinal(nowe, i*117, b.length%117, nowe, i*117);
			os.write(nowe);
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ShortBufferException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	private OutputStream os;
	private Cipher cipher;
}

Niestety w linii:
cipher.doFinal(nowe, i*117, 117, nowe, i*117); występuje błąd
javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
Przeciez dziele te dane na bloki po 117 bajtów :/. Macie jakies pomysły? Pozdrawiam

0

Ok zrobiłęm to tak:

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.ShortBufferException;

public class MyCoderOutputStream extends FilterOutputStream 
{
	public MyCoderOutputStream(OutputStream os, Cipher cipher)
	{
		super(os);
		this.os = os;
		this.cipher = cipher;
	}
	@Override
	public void write(int b) throws IOException {
		try {
			super.write(cipher.doFinal(cipher.update(new byte[]{(byte)b}))[0]);
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
	}
	@Override
	public void write(byte[] b) throws IOException {
		try {
			super.write(cipher.doFinal(cipher.update(b)));
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
	}
	@Override
	public void write(byte[] b, int off, int len) throws IOException {
		try {
			byte[] nowe = new byte[b.length];
			int i = 0;
			ArrayList<byte[]> tab = new ArrayList<byte[]>();
			int s = 0;
			for(; (nowe.length - i*117) >= 117 ; i++)
			{
				cipher.update(b, i*117, 117, nowe, i*117);
				tab.add(cipher.doFinal());
				System.out.println("rozmiar: " + (s+=tab.get(tab.size() - 1).length));
			}
			cipher.update(b, i*117, b.length%117, nowe, i*117);
			tab.add(cipher.doFinal());
			System.out.println("rozmiar: " + (s+=tab.get(tab.size() - 1).length));
			nowe = new byte[s];
			for(int c = 0, x = 0; c < tab.size() ; c++)
			{
				for(int d = 0 ; d < tab.get(c).length ; d++, x++)
				{
					byte[] t = tab.get(c);
					nowe[x] = t[d];
				}
			}
			os.write(nowe);
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (ShortBufferException e) {
			e.printStackTrace();
		}
	}
	private OutputStream os;
	private Cipher cipher;
}

I teraz NIE MA zadnych wyjatkow ale zato w klasie czytajacej:

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;


public class MyCoderInputStream extends FilterInputStream 
{
	public MyCoderInputStream(InputStream is, Cipher cipher)
	{
		super(is);
		this.is = is;
		this.cipher = cipher;
		System.out.println("MyCoder konstruktor.");
	}
	@Override
	public int read() throws IOException 
	{
		System.out.println("MyCoder read()");
		byte bajt = Byte.parseByte(""+super.read());
		try {
			bajt = (cipher.doFinal(cipher.update(new byte[]{bajt})))[0];
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return Integer.parseInt("" + bajt);
		//return super.read();
	}
	@Override
	public int read(byte[] b) throws IOException {
		System.out.println("MyCoder read(byte[] b)");
		int effect  = super.read(b);
		try {
			b = cipher.doFinal(cipher.update(b));
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return effect;
	}
	@Override
	public int read(byte[] b, int off, int len) throws IOException {
		System.out.println("MyCoder read(byte[] b, int off, int len)");
		int effect = super.read(b, off, len);
		try {
			b = cipher.doFinal(cipher.update(b, off, len));
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return effect;
	}
	private InputStream is;
	private Cipher cipher;

}

wyrzuca:

javax.crypto.BadPaddingException: Data must start with zero

w linii

b = cipher.doFinal(cipher.update(b, off, len));

Pomozcie bo juz niemam sily do tego. Pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1