วันพุธที่ 30 พฤศจิกายน พ.ศ. 2554

Java TLS/SSL #2

ตัวอย่าง code JSSE


ตัวอย่างในการ Run
Server:
D:\java\TLS>java ClassFileServer 80 . TLS true

Client:
D:\java\TLS>java SSLSocketClientWithClientAuth 147.127.xxx.90 80 /index.html


Modify to support Client authentication:

ClassFileServer:
ks.load(new FileInputStream("keystore-147.127.xxx.90"), passphrase);
kmf.init(ks, passphrase);
KeyStore ksTrust = KeyStore.getInstance("JKS");
ksTrust.load(new FileInputStream("truststore-147.127.xxx.91"), null);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ksTrust);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
===========================

SSLSocketClientWithClientAuth:
ks.load(new FileInputStream("keystore-147.127.xxx.91"), passphrase);
kmf.init(ks, passphrase);
KeyStore ksTrust = KeyStore.getInstance("JKS");
ksTrust.load(new FileInputStream("truststore-147.127.xxx.90"), null);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ksTrust);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

===========================
Just swap truststore and keystore for each other.



Trust store เหมือน public key แต่ทำไมจึงมี password?
Ans:
NOTE: Trust stores often have passwords but for validation of credentials the password is not needed because public key certificates are publicly accessible in any key or trust store. If you supply a password, the KeyStore.load method will use it when loading the store but only to validate the integrity of non-public information during the load – never during actual use of public key certificates in the store. Thus, you may always pass null in the second argument to KeyStore.load. If you do so, only public information will be loaded from the store.

วันพฤหัสบดีที่ 24 พฤศจิกายน พ.ศ. 2554

P2PNS vs RELOAD

Interested P2PSIP security solutions

- P2PNS: เป็น p2p-sip overlay ที่ใช้ การ hash(public-key) ในการ create ID เพื่อป้องการพวก Sybil attack สามารถ config DHT algorithm ใช้งานผ่าน OpenSER ที่ติดต่อกับ overlay network ที่ได้จาก OverSim (ที่ Run ผ่าน Omnet++ อีกที)

default DHT algorithm คือ Kademlia

P2PNS ออกแบบมาเพื่อให้ peer เก็บค่าของ SIP AoR ที่ Peer เอง และ retrieve ผ่าน DHT algorithm แทนที่จะต้องไป Query ผ่าน Name Server (เลยตั้งชื่อว่า P2PNS) แต่ไม่ได้บอกรายละเอียดชัดเจน ของ security เกี่ยวกับ การรับส่งข้อมูล



- RELOAD: คล้าย ๆ กับ P2PNS แต่ กำหนดเงื่อนไข รายละเอียดการส่งข้อมูลเยอะกว่า มี security layer บังคับใช้ TLS/SSL รวมกับ PKI, มี Certificate server ไว้ตรวจสอบ กำหนดทุกการส่งต้องผ่าน TLS/SSL

default DHT algorithm คือ chord




วันศุกร์ที่ 21 ตุลาคม พ.ศ. 2554

SSLContext

วิธีการกำหนดให้ใช้ Java SSL/TLS ก่อนจะสร้าง SSLSocket ขึ้นมามีหลายวิธี

1. กำหนดผ่าน SystemProperty โดย ทาง commandline

-Djavax.net.ssl.keyStore=keystoreSrv

หรือ set ใน program
System.setProperty("javax.net.ssl.keyStore", "keystoreSrv");


2. กำหนดใน JAVA_HOME/lib/security/jssecacerts หรือ JAVA_HOME/lib/security/cacerts


สร้าง SSLSocket ได้ดังนี้
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();

หากโชคดี connect ได้พอดีกับ ตอนที่ GetDefault ของ SSLContext ที่อ่านข้อมูลจาก SystemProperty ได้ทัน ก็ Run ได้ผ่านไม่มีปัญหา ซึ่งกรณีที่ทำ 1 connection จะไม่เจอปัญหานี้ (เหมือนกับตัวอย่าง code ที่เคยเขียนไว้)

แต่วิธีที่กล่าวมานั้น ไม่สามารถใช้ได้ในกรณีที่ทำ multiple TLS/SSL connections รวมกับ การ create Multi-Thread ไว้รอรับ connections เพราะเวลาสั่ง getDefault() ของ SSLContext เพื่อสร้าง SSLSocket หรือ SSLServerSocket แล้ว มักจะเจอ error เช่น

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

หรืออาจจะเป็น error อื่น ๆ เช่น certificate error, หา certificate ไม่เจอ ฯลฯ

ทั้ง ๆ ที่เราก็ set ค่า keyStore กับ trustStore ผ่าน SystemProperty ไปแล้ว

วิธีแก้ไขคือ
ให้สร้าง SSLContext ขึ้นมาเอง ดังนี้

public SSLContext createSSLContext(int type) {
//------------
char[] password;
SSLContext ctx = null;
InputStream in = null;
KeyStore ks = null;
KeyManagerFactory kmf = null;
TrustManagerFactory tmf = null;

try {

kmf = KeyManagerFactory.getInstance("SunX509", "SunJSSE");
tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");

if (type == KEYSTORE) { // for authen incoming connection
ks = KeyStore.getInstance(KeyStore.getDefaultType());
password = "123456".toCharArray();
in = (new FileInputStream("keystoreSrv"));
ks.load(in, password);
kmf.init(ks, password);
} else { // for connect another to authen
ks = KeyStore.getInstance(KeyStore.getDefaultType());
//password = "123456".toCharArray();
in = (new FileInputStream("truststoreCli"));
ks.load(in, null);
kmf.init(ks, null);
}

in.close();
tmf.init(ks);
ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
} catch (Exception e) {
e.printStackTrace();
}
return ctx;
}

จากนั้นเราก็นำ ctx นี่แหละไปสร้าง SSLSocket หรือ SSLServerSocket ดังนี้

SSLServerSocketFactory sslserversocketfactory = ctx.getServerSocketFactory();

SSLSocketFactory sslsocketfactory = ctx.getSocketFactory();

เท่านี้ก็จะไม่เจอ Error ดังกล่าวแล้วครับ

วันอังคารที่ 18 ตุลาคม พ.ศ. 2554

Digital Home Networking Book

Some parts of my researches here are appeared in the book now. :-)

http://www.iste.co.uk/index.php?f=x&ACTION=View&id=442

วันพุธที่ 28 กันยายน พ.ศ. 2554

HTTPS Java

HTTPS server on Windows
1. download "Win32 Binary including OpenSSL 0.9.8r"
(file.key = private key, file.cert = self signed certificate + public key)
3. re-config https, restart apache and verify


HTTPS client by Java
1. Since java truststore does not use the same format, then we have to convert self-signed certificate from server using this command
c:\> keytool -import -file file.cert -storepass $PASS -keystore server.keystore

2. Error:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present

3. Add anonymous class :

con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});

----- java code for https client -----

import java.net.*;
import java.io.*;
import javax.net.ssl.*;

public class HttpsClient {

public static void main(String[] args) throws Exception {
System.setProperty("javax.net.ssl.trustStore", "server.keystore");
String httpsURL = "https://147.127.xxx.xx/serverCertificate";
URL myurl = new URL(httpsURL);


HttpsURLConnection con = (HttpsURLConnection) myurl.openConnection();
con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
con.connect();
InputStream ins = con.getInputStream();
InputStreamReader isr = new InputStreamReader(ins);
BufferedReader in = new BufferedReader(isr);
String inputLine;

while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}

in.close();
}
}

Note: Just use for testing, it is not suitable for real deployment.

วันอังคารที่ 27 กันยายน พ.ศ. 2554

Event Java


My Simple example with 4 classes for understanding how event and eventListener work together.

------------------------------
package myevents;
import java.util.EventObject;

public class MyEvent extends EventObject {

private static final long serialVersionUID = 5736098458773344230L;
private Object data;

public MyEvent(Object source, Object _data) {
super(source);
data = _data;
}

public Object getData() {
return data;
}
}
-------------------------------
package myevents;
import java.util.EventListener;

public interface MyEventListener extends EventListener {
public void myEventHappend(MyEvent e);
}
------------------------------
package myevents;
public class PracticalInterface implements MyEventListener {

@Override
public void myEventHappend(MyEvent e) {
System.out.println((String) e.getData());
}
}
------------------------------
package myevents;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;

public class AppProgram extends JFrame {

private Vector listeners = new Vector();
private JTextArea _tar = new JTextArea(22,40);
private JButton _bt1 = new JButton("Yeah");
private JButton _bt2 = new JButton("Yoo");

public AppProgram() {
super("Application");
setLayout(new FlowLayout());
_bt1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
shootEvent("Yeah !!");
}
});
_bt2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
shootEvent("Yoo !?");
}
});
this.add(_tar);
this.add(_bt1);
this.add(_bt2);
}

public void addListener(MyEventListener l) {
listeners.add(l);
}

public void removeListener(MyEventListener l) {
listeners.remove(l);
}

public void shootEvent(String text) {
MyEvent me = new MyEvent(this, text);
if (listeners.size() > 0) {
((MyEventListener)listeners.firstElement()).myEventHappend(me);
}
}

public static void main(String[] args) {
AppProgram app = new AppProgram();
PracticalInterface lis = new PracticalInterface();
app.addListener(lis);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(400,600);
app.setVisible(true);
}

}



จาก 
http://windygallery.wordpress.com/2010/02/18/events-and-eventlistener/

วันพุธที่ 14 กันยายน พ.ศ. 2554

Keystore for TLS/SSL

create keystore (public/private key):
keytool -genkeypair -alias certificatekey -keyalg RSA -validity 7 -keystore keystore.jks

verify keystore:
keytool -list -v -keystore keystore.jks

create self signed certificate:
keytool -export -alias certificatekey -keystore keystore.jks -rfc -file selfsignedcert.cer

import certificate to trust store (public key):
keytool -import -alias certificatekey -file selfsignedcert.cer -keystore truststore.jks

verify trust store:
keytool -list -v -keystore truststore.jks


ตัวอย่าง code TLS/SSL Java

java -Djavax.net.ssl.keyStore=mySrvKeystore -Djavax.net.ssl.keyStorePassword=123456 EchoServer

เราสามารถใช้ option -Djavax.net.ssl.keyStore=... ใน netbeans ได้ โดยกำหนดที่ Run parameter และ ป้อนค่า options นี้ ลงไปใน VM options (ไม่ใช่ใน arguments อันนี้ สำหรับ args[] ของฟังก์ชัน main) จากนั้น ให้เก็บ file keyStore ใน project folder (parent ของ src)