D
despikyxd
Gast
[NET/SICHERHEIT] hybrides Kryptosystem mit RSA und AES
ich denke ich muss den interessierten die funktionsweise von RSA und AES nicht erklären und kann gleich mit dem code durchstarten
nach langem suchen und probieren habe ich nun ein hybrides krypto-system entwickelt um befehle und daten gesichert zu übertragen
die verwendung für RAW daten ist zwar nicht implementiert lässt sich aber einfach mit zwei zusätzlichen methoden realisieren ... zur zeit sind die zusendenen daten dem limit unterlegen das diese durch ein String-Objekt darstellbar sein müssen um zum empfangen die readLine() methode des BufferedReader nutzen zu können
die daten selbst werden als HEX-daten übertragen um eine leichte rückkonvertierung in byte zu ermöglichen
das system stütz sich dabei auf 3 klassen
1. synccrypt.java - stellt die hauptklasse da ... über sie wird der AES-schlüssel erstellt *mit einer static-methode* und die ver- und entschlüsselung bewerkstelligt
2. asynccrypt.java - klasse für das RSA-system mit schlüsselerstellung, -austausch und austausch des AES-schlüssels
3. tools.java - helfer-klasse ... enthält lediglich 2 methoden zur konvertierung zwischen String und byte[] *könnte auch in synccrypt integriert werden*
source
synccrypt.java
asynccrypt.java
helfer-klasse tools.java
wie ihr seht ist das ganze eher simpel gehalten und sieht für viele sicher sehr schrecklich aus
ich habe mir halt diesen programmierstil angewöhnt und werde auch weiter so schreiben da ich bei einigen stilen nicht wirklich den unterschied sehe
beispiel welches für mich eher verwirrend ist als irgendwie logisch
meine schreibweise
ich persönlich finde meine variante deutlich übersichtlicher und leichter zuordbar ... aber naja ...
ich habe zur demonstration auch ein beispiel programmiert
dies beinhaltet einen server , einen clienten und einen sniffer der zwischen beiden die daten als RAW ausgibt
SERVER
sserver.java
sclient.java
CLIENT
client.java
clientreader.java
SNIFFER
sniffer.java
ich werde versuchen für den gesamten code support zu leisten und bei fragen , verbesserungsvorschlägen und vor allem kritiken zu reagieren und zu antworten
alles in allem denke ich doch das ich hier einen sehr interessanten thread gestartet habe und das es einigen bei der netcode-entwicklung helfen wird
greedz ... SPiKEe
ich denke ich muss den interessierten die funktionsweise von RSA und AES nicht erklären und kann gleich mit dem code durchstarten
nach langem suchen und probieren habe ich nun ein hybrides krypto-system entwickelt um befehle und daten gesichert zu übertragen
die verwendung für RAW daten ist zwar nicht implementiert lässt sich aber einfach mit zwei zusätzlichen methoden realisieren ... zur zeit sind die zusendenen daten dem limit unterlegen das diese durch ein String-Objekt darstellbar sein müssen um zum empfangen die readLine() methode des BufferedReader nutzen zu können
die daten selbst werden als HEX-daten übertragen um eine leichte rückkonvertierung in byte zu ermöglichen
das system stütz sich dabei auf 3 klassen
1. synccrypt.java - stellt die hauptklasse da ... über sie wird der AES-schlüssel erstellt *mit einer static-methode* und die ver- und entschlüsselung bewerkstelligt
2. asynccrypt.java - klasse für das RSA-system mit schlüsselerstellung, -austausch und austausch des AES-schlüssels
3. tools.java - helfer-klasse ... enthält lediglich 2 methoden zur konvertierung zwischen String und byte[] *könnte auch in synccrypt integriert werden*
source
synccrypt.java
Java:
import java.io.*;
import java.security.*;
import javax.crypto.*;
class synccrypt
{
private BufferedReader in=null;
private PrintStream out=null;
private Cipher ecip=null;
private Cipher dcip=null;
private SecretKey sk=null;
public synccrypt() { }
//konstruktor mit übergabe der in- und outputstreams und des AES-schlüssels
public synccrypt(BufferedReader in, PrintStream out, SecretKey sk) { this.in=in; this.out=out; this.sk=sk; }
//init-funktion zur initialisierung der cipher
public void init() throws Exception
{
ecip=Cipher.getInstance("AES");
ecip.init(Cipher.ENCRYPT_MODE, sk);
dcip=Cipher.getInstance("AES");
dcip.init(Cipher.DECRYPT_MODE, sk);
}
//static-methode zur erzeugung des AES-schlüssels
public static SecretKey genKey() throws Exception
{
KeyGenerator kg=KeyGenerator.getInstance("AES");
kg.init(new SecureRandom());
return kg.generateKey();
}
//sende- und empfangsmethoden
public void sendMsg(String msg) throws Exception
{
byte[] input=msg.getBytes();
byte[] output=crypt(input, ecip);
String send=tools.hex(output);
out.println(send);
}
public String recieveMsg() throws Exception
{
String line=new String("");
while(true)
{
line=in.readLine();
if(line==null)
return (new String(""));
if(!line.equals(""))
break;
}
byte[] input=tools.dehex(line);
byte[] ret=crypt(input, dcip);
return (new String(ret));
}
//private crypto-methode für ver- und entschlüsselung
private byte[] crypt(byte[] input, Cipher cip) throws Exception
{
ByteArrayInputStream bais=new ByteArrayInputStream(input);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
int bs=cip.getBlockSize();
int os=cip.getOutputSize(bs);
byte[] inb=new byte[bs];
byte[] outb=new byte[os];
int inl=0;
boolean fin=false;
while(!fin)
{
inl=bais.read(inb);
if(inl==bs)
{
int outl=cip.update(inb, 0, bs, outb);
baos.write(outb, 0, outl);
}
else
fin=true;
}
if(inl>0)
outb=cip.doFinal(inb, 0, inl);
else
outb=cip.doFinal();
baos.write(outb);
return (baos.toByteArray());
}
}
asynccrypt.java
Java:
import java.math.*;
import java.io.*;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import javax.crypto.*;
class asynccrypt
{
BufferedReader in=null;
PrintStream out=null;
PublicKey pub=null;
PrivateKey priv=null;
public asynccrypt() { }
//konstruktor mit übergabe der in- und outputstreams
public asynccrypt(BufferedReader in, PrintStream out) { this.in=in; this.out=out; }
//methode zur generierung des schlüsselpaars
public void genKeyPair() throws Exception
{
KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");
SecureRandom sr=new SecureRandom();
kpg.initialize(1024, sr);
KeyPair kp=kpg.generateKeyPair();
pub=kp.getPublic();
priv=kp.getPrivate();
}
//methoden zum senden und empfangen des public-keys
public void sendPublicKey() throws Exception
{
RSAPublicKey pk=(RSAPublicKey)pub;
BigInteger mod=pk.getModulus();
out.println(mod.toString(16));
}
public void recievePublicKey() throws Exception
{
String line=new String("");
while(true)
{
line=in.readLine();
if(!line.equals(""))
break;
}
BigInteger exp=new BigInteger("65537");
BigInteger mod=new BigInteger(line, 16);
RSAPublicKeySpec ks=new RSAPublicKeySpec(mod, exp);
KeyFactory kf=KeyFactory.getInstance("RSA");
pub=kf.generatePublic(ks);
}
//methoden zum senden und empfangen des AES-schlüssels
public void sendSyncKey(SecretKey sk) throws Exception
{
Cipher c=Cipher.getInstance("RSA");
c.init(Cipher.WRAP_MODE, pub);
byte[] wk=c.wrap(sk);
out.println(tools.hex(wk));
}
public SecretKey recieveSyncKey() throws Exception
{
String line=new String("");
while(true)
{
line=in.readLine();
if(!line.equals(""))
break;
}
byte[] wk=tools.dehex(line);
Cipher c=Cipher.getInstance("RSA");
c.init(Cipher.UNWRAP_MODE, priv);
SecretKey sk=(SecretKey)c.unwrap(wk, "AES", Cipher.SECRET_KEY);
return sk;
}
}
helfer-klasse tools.java
Java:
public class tools
{
public static String hex(byte[] input) throws Exception
{
StringBuffer sb=new StringBuffer(input.length*2);
for(int i=0; i<input.length; i++)
{
int v=input[i]&0xFF;
if(v<16)
sb.append("0");
sb.append(Integer.toHexString(v));
}
return sb.toString().toUpperCase();
}
public static byte[] dehex(String input) throws Exception
{
byte[] ret=new byte[input.length()/2];
for(int i=0; i<ret.length; i++)
{
int index=i*2;
int v=Integer.parseInt(input.substring(index, index+2), 16);
ret[i]=(byte)v;
}
return ret;
}
}
wie ihr seht ist das ganze eher simpel gehalten und sieht für viele sicher sehr schrecklich aus
ich habe mir halt diesen programmierstil angewöhnt und werde auch weiter so schreiben da ich bei einigen stilen nicht wirklich den unterschied sehe
beispiel welches für mich eher verwirrend ist als irgendwie logisch
Java:
public void method() {
//code
}
Java:
public void method()
{
//code
}
ich persönlich finde meine variante deutlich übersichtlicher und leichter zuordbar ... aber naja ...
ich habe zur demonstration auch ein beispiel programmiert
dies beinhaltet einen server , einen clienten und einen sniffer der zwischen beiden die daten als RAW ausgibt
SERVER
sserver.java
Java:
import java.io.*;
import java.net.*;
public class sserver
{
public static void main(String[] args) { new sserver(); }
public sserver()
{
ServerSocket ss=null;
try { ss=new ServerSocket(7459); }
catch(Exception e) { e.printStackTrace(); System.exit(1); }
while(true)
{
try
{
Socket cs=ss.accept();
(new sclient(cs)).start();
}
catch(Exception e) { }
}
}
}
sclient.java
Java:
import java.io.*;
import java.net.*;
import java.security.*;
import javax.crypto.*;
class sclient extends Thread
{
Socket cs=null;
public sclient() { }
public sclient(Socket cs) { this.cs=cs; }
public void run()
{
InputStream in=null;
OutputStream out=null;
try { in=cs.getInputStream(); out=cs.getOutputStream(); }
catch(Exception e) { try { cs.close(); } catch(Exception ex) { } }
try
{
BufferedReader bin=new BufferedReader(new InputStreamReader(in));
PrintStream pout=new PrintStream(out, true);
asynccrypt ac=new asynccrypt(bin, pout);
ac.genKeyPair();
ac.sendPublicKey();
SecretKey sk=ac.recieveSyncKey();
synccrypt sc=new synccrypt(bin, pout, sk);
sc.init();
String line=new String("");
while(true)
{
try { line=sc.recieveMsg(); } catch(Exception ex) { break; }
if(!line.equals(""))
{
System.out.println(line);
sc.sendMsg(line);
}
}
in.close();
out.close();
cs.close();
}
catch(Exception e) { }
}
}
CLIENT
client.java
Java:
import java.io.*;
import java.net.*;
import java.security.*;
import javax.crypto.*;
public class client
{
public static void main(String[] args) { new client(); }
public client()
{
Socket cs=null;
InputStream in=null;
OutputStream out=null;
try { cs=new Socket("127.0.0.1", 7460); }
catch(Exception e) { e.printStackTrace(); System.exit(1); }
try { in=cs.getInputStream(); out=cs.getOutputStream(); }
catch(Exception e) { e.printStackTrace(); System.exit(1); }
BufferedReader cin=new BufferedReader(new InputStreamReader(System.in));
BufferedReader bin=new BufferedReader(new InputStreamReader(in));
PrintStream pout=new PrintStream(out);
asynccrypt ac=new asynccrypt(bin, pout);
try { ac.recievePublicKey(); }
catch(Exception e) { e.printStackTrace(); System.exit(1); }
SecretKey sk=null;
try { sk=synccrypt.genKey(); ac.sendSyncKey(sk); }
catch(Exception e) { e.printStackTrace(); System.exit(1); }
synccrypt sc=new synccrypt(bin, pout, sk);
try { sc.init(); } catch(Exception e) { }
(new clientreader(sc)).start();
String line=new String("");
while(true)
{
try
{
line=cin.readLine();
if(line.equals("exit"))
break;
if(!line.equals(""))
sc.sendMsg(line);
}
catch(Exception e) { break; }
}
try
{
in.close();
out.close();
cs.close();
}
catch(Exception e) { }
System.exit(0);
}
}
clientreader.java
Java:
import java.io.*;
class clientreader extends Thread
{
synccrypt sc=null;
public clientreader() { }
public clientreader(synccrypt sc) { this.sc=sc; }
public void run()
{
String line=new String("");
while(true)
{
try
{
line=sc.recieveMsg();
if(line==null)
break;
if(!line.equals(""))
System.out.println(line);
}
catch(Exception e) { break; }
}
}
}
SNIFFER
sniffer.java
Java:
import java.io.*;
import java.net.*;
public class sniffer
{
public static void main(String[] args) throws Exception { new sniffer(); }
public sniffer() throws Exception
{
ServerSocket ss=new ServerSocket(7460);
while(true)
{
Socket cs=ss.accept();
InputStream in=cs.getInputStream();
OutputStream out=cs.getOutputStream();
Socket cc=new Socket("127.0.0.1", 7459);
InputStream cin=cc.getInputStream();
OutputStream cout=cc.getOutputStream();
(new snifflog(in, cout)).start();
(new snifflog(cin, out)).start();
}
}
}
class snifflog extends Thread
{
InputStream in=null;
OutputStream out=null;
public snifflog() { }
public snifflog(InputStream in, OutputStream out) { this.in=in; this.out=out; }
public void run()
{
int read=0;
byte[] buf=new byte[8192];
while(true)
{
try
{
while((read=in.read(buf))!=-1)
{
if(read==0)
continue;
System.out.write(buf, 0, read);
out.write(buf, 0, read);
}
}
catch(Exception e) { }
}
}
}
ich werde versuchen für den gesamten code support zu leisten und bei fragen , verbesserungsvorschlägen und vor allem kritiken zu reagieren und zu antworten
alles in allem denke ich doch das ich hier einen sehr interessanten thread gestartet habe und das es einigen bei der netcode-entwicklung helfen wird
greedz ... SPiKEe