My Safe is an Eclipse RCP based software I developed last year. As suggested by its name, it is a secure file manager.
It is easy to use. You must input the correct password in order to enter My Safe. Inside My Safe, you can see all directories and files as they originally are. But these directories and files are encrypted in the file system. And they are decrypted on demand in My Safe's interface. The password you use to enter My Safe is the key for encryption and decryption. AES is used as the cipher.
I want to argue that such software as My Safe is necessary even on our personal desktops or laptops. So that other people may possess our computer but can not possess our data.
My Sony laptop does have a secure drive called My Safe as well, but it is not perfect. It is a proprietary technology. It means the data is tightly bound to the Sony laptop. So if the software is broken, there is no way for me to recover the encrypted data. And I can not decrypted the encrypted data on another computer.
Therefore I developed my very own My Safe. And it turns out to be very useful!
Showing posts with label Security. Show all posts
Showing posts with label Security. Show all posts
Thursday, December 11, 2008
Wednesday, November 19, 2008
Let Java SSL Trust All Certificates without Violating Security Manager
Java SSL by default does not trust self-signed certificate. Wikibooks:Programming reveals a way to allow connection to secure HTTP server using self-signed certificate. The magic looks like:
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
// do nothing
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
// do nothing
}
}
};
// Install the all-trusting trust manager
SSLContext sc = null;
try {
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
} catch(GeneralSecurityException gse) {
throw new IllegalStateException(gse.getMessage());
}
HttpsURLConnection.setDefaultSSLSocketFactory(
sc.getSocketFactory());
However, HttpsURLConnection.setDefaultSSLSocketFactory(...) will throw a SecurityException (a RuntimeException) if a security manager exists and its checkSetFactory method does not allow a socket factory to be specified. The thrown SecurityException looks like
Exception in thread "main" java.security.AccessControlException: access denied (java.lang.RuntimePermission setFactory)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkSetFactory(SecurityManager.java:1612)
at javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(HttpsURLConnection.java:308)
at SecurityManagerTest.main(SecurityManagerTest.java:50)
A workaround to avoid such a SecurityException is as below:
URL url = new URL("https://engage.ac.uk");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.getInputStream();
The trick is to use the instance method setSSLSocketFactory instead of the static method setDefaultSSLSocketFactory. The former does not throw a SecurityException.
Note: need to use conn.getInputStream() instead of url.openStream(), otherwise the customised SocketFactory won't be used.
Of course to allow to connect the secure web site, the following permission should be added in the Java security policy file:
permission java.net.SocketPermission "engage.ac.uk:443", "connect";
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
// do nothing
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
// do nothing
}
}
};
// Install the all-trusting trust manager
SSLContext sc = null;
try {
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
} catch(GeneralSecurityException gse) {
throw new IllegalStateException(gse.getMessage());
}
HttpsURLConnection.setDefaultSSLSocketFactory(
sc.getSocketFactory());
However, HttpsURLConnection.setDefaultSSLSocketFactory(...) will throw a SecurityException (a RuntimeException) if a security manager exists and its checkSetFactory method does not allow a socket factory to be specified. The thrown SecurityException looks like
Exception in thread "main" java.security.AccessControlException: access denied (java.lang.RuntimePermission setFactory)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkSetFactory(SecurityManager.java:1612)
at javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(HttpsURLConnection.java:308)
at SecurityManagerTest.main(SecurityManagerTest.java:50)
A workaround to avoid such a SecurityException is as below:
URL url = new URL("https://engage.ac.uk");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.getInputStream();
The trick is to use the instance method setSSLSocketFactory instead of the static method setDefaultSSLSocketFactory. The former does not throw a SecurityException.
Note: need to use conn.getInputStream() instead of url.openStream(), otherwise the customised SocketFactory won't be used.
Of course to allow to connect the secure web site, the following permission should be added in the Java security policy file:
permission java.net.SocketPermission "engage.ac.uk:443", "connect";
Use Security Manager to Control Java Web Application Behavior
In a Java web application server like Tomcat, we have the Tomcat container and multiple web applications running in the same JVM. It is thus very important to cut the unexpected interactions between applications and between applications and Tomcat. Ideally it is expected the behavior of one web application should not affect the behavior of other applications as well as Tomcat, in a bad way.
One of such unexpected interactions is caused by modifying shared classes and objects, for instance, changing system properties, changing system classes' behavior.
Tomcat 5.5's class loaders are organised as:
In both cases, web applications and Tomcat share the classes managed by class loaders Bootstrap, System and Common.
Let's say one web application use the following code to tell Java runtime to use the XSLT implementation shipped with JDK.
System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
Other web applications may choose to use other XSLT implementations in a similar way. If a certain web application's correct behavior is depending on a particular XLST implementation, then we may get a problem, because System.setProperty("javax.xml.transform.TransformerFactory", ...) will change the JVM-wide XSLT implementation.
Therefore it is advisable to use Java security manager to control the permissions granted to web application code.
Note $CATALINA_HOME/bin/startup.sh does not start up a Tomcat with the security manager. To enable the security manager, use $CATALINA_HOME/bin/startup.sh -security. It will append "-Djava.security.manager -Djava.security.policy=..." to the JVM arguments.
A simple Java program testing security manager and policy file
public class SecurityManagerTest {
public static void main(String[] args) throws Exception {
System.setProperty("greeting", "hello world!");
System.out.println(System.getProperty("greeting"));
}
}
Run this program, you will see "hello world!" printed out.
Prepare a policy file called lab.policy:
grant {
permission java.util.PropertyPermission "*", "read";
};
It says any code can only read system properties, but not write.
By the way, the policy file can be created using policytool.
Then run the program like this:
java -Djava.security.manager -Djava.security.policy=lab.policy SecurityManagerTest
You will see an excpetion pop up:
Exception in thread "main" java.security.AccessControlException: access denied (java.util.PropertyPermission greeting write)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.System.setProperty(System.java:727)
at SecurityManagerTest.main(SecurityManagerTest.java:11)
See the security manager is working. It is important to give the right location for the policy file. Because when the security manager is enabled, by default no permission is granted. So any permission will be denied except those defined in the policy file. In case the policy file cannot be found, then the code is given no permission at all.
One of such unexpected interactions is caused by modifying shared classes and objects, for instance, changing system properties, changing system classes' behavior.
Tomcat 5.5's class loaders are organised as:
BootstrapTomcat 6.0's class loaders are organised as:
|
System
|
Common
/ \
Catalina Shared
/ \
Webapp1 Webapp2 ...
Bootstrap
|
System
|
Common
/ \
Webapp1 Webapp2 ...
In both cases, web applications and Tomcat share the classes managed by class loaders Bootstrap, System and Common.
Let's say one web application use the following code to tell Java runtime to use the XSLT implementation shipped with JDK.
System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
Other web applications may choose to use other XSLT implementations in a similar way. If a certain web application's correct behavior is depending on a particular XLST implementation, then we may get a problem, because System.setProperty("javax.xml.transform.TransformerFactory", ...) will change the JVM-wide XSLT implementation.
Therefore it is advisable to use Java security manager to control the permissions granted to web application code.
Note $CATALINA_HOME/bin/startup.sh does not start up a Tomcat with the security manager. To enable the security manager, use $CATALINA_HOME/bin/startup.sh -security. It will append "-Djava.security.manager -Djava.security.policy=..." to the JVM arguments.
A simple Java program testing security manager and policy file
public class SecurityManagerTest {
public static void main(String[] args) throws Exception {
System.setProperty("greeting", "hello world!");
System.out.println(System.getProperty("greeting"));
}
}
Run this program, you will see "hello world!" printed out.
Prepare a policy file called lab.policy:
grant {
permission java.util.PropertyPermission "*", "read";
};
It says any code can only read system properties, but not write.
By the way, the policy file can be created using policytool.
Then run the program like this:
java -Djava.security.manager -Djava.security.policy=lab.policy SecurityManagerTest
You will see an excpetion pop up:
Exception in thread "main" java.security.AccessControlException: access denied (java.util.PropertyPermission greeting write)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.System.setProperty(System.java:727)
at SecurityManagerTest.main(SecurityManagerTest.java:11)
See the security manager is working. It is important to give the right location for the policy file. Because when the security manager is enabled, by default no permission is granted. So any permission will be denied except those defined in the policy file. In case the policy file cannot be found, then the code is given no permission at all.
Thursday, November 06, 2008
OpenSSL
Recently I used the openssl utility to generate key pairs and certificates. For example,
- To generate a private key: openssl genrsa -out ca.key 2048
- To create a self-signed certificate: openssl req -new -key ca.key -x509 -days 365 -out ca.crt
- To create a certificate signing request: openssl req -new -key temp.key -out temp.csr
- To create a certificate from a certificate signing request: openssl x509 -req -in temp.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out temp.crt
- To display a certificate: openssl x509 -text -in temp.crt
- To display the content of a pkcs12 formatted certificate (the displayed private key and certificate are in PEM format, which can be used in the above commands): openssl pkcs12 -in old_uk_escience.p12 -out old.txt
- To convert from pkcs12 format to PEM format: openssl pkcs12 -in cred.p12 -out cert.pem -nodes -clcerts -nokeys, openssl pkcs12 -in cred.p12 -out key.pem -nodes -nocerts
- To create pkcs12 format certificate using PEM format private key and certificate: openssl pkcs12 -in temp.crt -inkey temp.key -out temp.p12 -export
Subscribe to:
Posts (Atom)