7 import java.security.*;
\r
8 import javax.crypto.*;
\r
9 import javax.crypto.spec.*;
\r
11 import org.bouncycastle.openssl.*;
\r
12 import org.bouncycastle.util.encoders.*;
\r
20 * 4 byte: msg length
\r
23 public class TCPW implements Runnable{
\r
24 private TCP $parent = null;
\r
26 private Socket $sock = null;
\r
27 private InputStream $in = null;
\r
28 private OutputStream $out = null;
\r
29 private String[] $usrInfo = null;
\r
30 private Cipher $s2c = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding");
\r
31 private Cipher $c2s = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding");
\r
32 private PublicKey $puk = null;
\r
33 private SecretKey $skey = null;
\r
34 private String $challenge = null;
\r
35 private byte[] $iv = null;
\r
36 private boolean $nextIsC = false;
\r
38 public TCPW(Socket $s, TCP $t)throws Exception{
\r
42 $c2s.init(Cipher.DECRYPT_MODE, Main.$tcp.$prk);
\r
43 $in = $sock.getInputStream();
\r
44 $out = $sock.getOutputStream();
\r
45 new Thread(this).start();
\r
50 while($sock != null){
\r
53 }catch(Exception $e){$e.printStackTrace();}
\r
54 $parent.delConn(this);
\r
57 public void send(String $msg){
\r
59 byte[] $encrypted = $s2c.doFinal($msg.getBytes());
\r
60 byte[] $len = Helper.int2ba($encrypted.length);
\r
62 $out.write($encrypted);
\r
64 }catch(Exception $e){$e.printStackTrace();}
\r
67 public void receive()throws Exception{
\r
68 int $len = Helper.ba2int(Helper.readBA($in, 4));
\r
69 byte[]$raw = Helper.readBA($in, $len);
\r
72 $msg = new String($raw);
\r
74 $msg = new String($c2s.doFinal($raw));
\r
76 if($nextIsC){ //check challenge or kill
\r
77 if($msg.equals($challenge)){
\r
78 $c2s = Cipher.getInstance("AES/CTR/NoPadding");
\r
79 $s2c = Cipher.getInstance("AES/CTR/NoPadding");
\r
80 $c2s.init(Cipher.ENCRYPT_MODE, $skey, new IvParameterSpec($iv));
\r
81 $s2c.init(Cipher.DECRYPT_MODE, $skey, new IvParameterSpec($iv));
\r
87 String $data[] = $msg.trim().split("\\s+"); //regex: whitespace character once and more
\r
89 if($data[0].equalsIgnoreCase("!login")){
\r
90 if($data[1] != null){
\r
91 PEMReader in = new PEMReader(new FileReader(Main.$cfg.getString("keys.public.dir")+File.separator+$data[1]));
\r
92 $puk = (PublicKey) in.readObject();
\r
93 $c2s.init(Cipher.DECRYPT_MODE, $puk);
\r
95 byte[] $rand = new byte[32];
\r
96 new SecureRandom().nextBytes($rand);
\r
97 $challenge = new String(Base64.encode($rand));
\r
99 KeyGenerator $gen = KeyGenerator.getInstance("AES");
\r
101 $skey = $gen.generateKey();
\r
103 byte[] $iv = new byte[16];
\r
104 new SecureRandom().nextBytes($iv);
\r
105 send("!ok "+$data[2]+" "+$challenge+" "+new String(Base64.encode($skey.getEncoded()))+" "+new String(Base64.encode($rand)));
\r
112 send("Not logged in! Log in now! (!login user pass)");
\r
115 if($data[0].equalsIgnoreCase("!logout")){
\r
116 java.util.Date now = new Date(System.currentTimeMillis());
\r
117 java.text.DateFormat formatter = new java.text.SimpleDateFormat("dd.MM.yyyy HH:mm");
\r
118 String $date = formatter.format(now);
\r
119 $usrInfo[2] = "Offline since:"+$date;
\r
121 send("logged out!");
\r
123 if($data[0].equalsIgnoreCase("!send")){
\r
124 $parent.sendAll($usrInfo[0]+" said: "+$msg.substring(5).trim());
\r
126 if($data[0].equalsIgnoreCase("!msg")){
\r
127 String[] $udata = Main.$usr.get($data[1]);
\r
128 if($udata == null || $data.length <2){
\r
129 send("Supplied user is invalid!");
\r
132 TCPW $tmp = $parent.getConnByName($data[1]);
\r
134 send("User offline");
\r
137 if($tmp != null && $tmp.isLoggedIn())$tmp.send($usrInfo[0]+" whispers: "+$msg.substring(5+$data[1].length()).trim());
\r
138 send("privmsg sent!");
\r
142 public boolean isLoggedIn(){
\r
143 if($usrInfo != null) return true;
\r
146 public String getName(){
\r
147 if($usrInfo != null)return $usrInfo[0];
\r
151 public void shutdown(){
\r
157 }catch(Exception $e){$e.printStackTrace();}
\r