วันศุกร์ที่ 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