In the first part of the tutorial, SSL is being configured for server authentication. In the second part, the SSL configuration is extended for also providing client authentication.
SSL configuration is a two-step process. First the SSL certificates need to be created, and then the jigsaw server needs to be configured. One item not covered in this document is the importing of already existing certificates.
Make sure that jdk 1.4 is being used.
We are going to be using the SSL implementation from Sun. Mainly the keytool (http://java.sun.com/j2se/1.4/docs/tooldocs/solaris/keytool.html) is used to configure the SSL certificates. If keytool is not in your default PATH, you can find it in the "bin" directory of your JDK installation.
keytool -genkey -alias troi.example.com -keypass example -keystore
/opt/jigsaw/dev/Jigsaw/keystore/troi.keystore -keyalg RSA
keytool -certreq -alias troi.example.com -keypass example -keystore
/opt/jigsaw/dev/Jigsaw/keystore/troi.keystore -file troi.csr
-----BEGIN NEW CERTIFICATE REQUEST----- MIICgTCCAj4CAQAwezELMAkGA1UEBhMCVVMxETAPBgAAAAgTCElsbGlub2lzMRYwFAYDVQQHEw1E b3duZXJzIEdyb3ZlMRAwDgYDVQQKEwdQZXJzZWNvMRkwFwYDVQQLExBCdXNpbmVzcyBTeXN0ZW1z MRQwEgYDVQQDEwtCcmlhbiBMYWlyZDCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLf Spwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQ paSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd 0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6j fwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GFAAKBgQDc5Ki4 7dX93se92yzYjxJIi99R9EZYHu4sNUH9obMQYO7o5u/3AOkxzqHLx60wWbf9JoCAlMe8q2i28NNC hjsN6LN7V0fgA05k/CzM9pMxbgeA0dqwQrtroWkJnFyzzFLrxjv7Rrh5RDGV/+ZeR72ZpHwy1GOj yDB2Dz+NE98sgKAAMAsGByqGSM44BAMFAAMwADAtAhRumfMg6P1KJmstMYga74KxaPLBfgIVAIwB bVanNqQb898bqHBkRybHIFqW -----END NEW CERTIFICATE REQUEST-----
Now we will import the response from the certificate authority.
keytool -import -alias sis.example.com -keystore sis.keystore -file sis.cer
-keyalg RSA -trustcacerts
and skip the next point (related to self-signature)
keytool -selfcert -alias troi.example.com -keystore
/opt/jigsaw/dev/Jigsaw/keystore/troi.keystore -keyalg RSA
# Points to the key store (cf. 4. above, don't forget to put the full path to the keystore) org.w3c.jigsaw.ssl.keystore.path= # Supplies the password for accessing the key store ... org.w3c.jigsaw.ssl.keystore.password= # Finally, the socket client factory has to be set to the SSL factory ... org.w3c.jigsaw.http.ClientFactory=org.w3c.jigsaw.https.socket.SSLSocketClientFactory
Of course you may change the default port to use the default one for SSL: 443 (or any other you like and which is not yet used)
You should also change the propfile value to match the name of your configuration file.
org.w3c.jigsaw.daemon.handlers=https-server|... https-server.org.w3c.jigsaw.daemon.class=org.w3c.jigsaw.https.httpsd
This should cover the setup requirements. You should be able to start jigsaw and see something like the following when the start up occurs:
Jigsaw[2.2.3]: serving at https://troi:8002/
You can also use the secure protocol for webdav, in which case the daemon class must be set to
org.w3c.jigsaw.webdavs.webdavsd
Server authentication enables a client to verify in a secure way, which server she or he is talking to.
Jigsaw also provides for client authentication, which addresses the other way around: It enables a server (and a web application) to verify in a secure way, which client accesses the server. Although, client authentication is rarely used in the web, it is a powerful infrastructure for building up secure web applications with distributed user management.
For verifying clients, they must present a certificate, which can be checked by the server using public key infrastructure. In order to do so, the server needs an additional store for also keeping track of trusted CA certificates used to sign client certificates.
Extending the SSL configuration is a two-step process again. First the trust store has to be populated with CA certificates (at least one), and then the jigsaw server needs to be configured.
You can obtain a client certificate from an authority like verisign and store it in your browser for being presented to the server during the SSL handshake. In this case, you also need to import the authority's certificate used to sign yours into the server's trust store. The latter task can be performed using keytool again.
If you prefer acting as your own CA, keytool and the SUN JCE implementation are not sufficient, because they currently do not provide for signing certificates other than your own. However, you can download a free JCE extension from bouncy castle, which also provides for certificate signing features. You can modify the following sample code for playing CA:
Make sure that the bouncy castle bcprov-jdk14-121.jar file is in your JRE/lib/ext directory.
/** * Copyright (c) 2004 Thomas Kopp * All rights reserved. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ import java.io.*; import java.util.*; import java.security.Security; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.*; import org.bouncycastle.jce.*; import org.bouncycastle.jce.provider.*; import org.bouncycastle.asn1.x509.*; /** * Sample signing utility developped for simplified interoperability with keytool. * * It assumes that the CA has a self-signed certificate with alias "ca" in the "ca.db" JKS type keystore. * In addition, it assumes that a self-signed client certificate with alias "foo" resides in * the "bar.db" JKS type keystore. The CA-signed version gets stored with alias "foo" again in * the "bar.p12" PKCS12 type keystore, so that it can easily be imported by web browsers. * * The ca uses the "manager" password for accessing its own store and the "example" * password for accessing the client stores and certificates. */ public class signtool { static { // add the bouncy castle provider Security.addProvider(new BouncyCastleProvider()); } public static void main(String[] args) { try { // The issuer certificate access KeyStore ksca = KeyStore.getInstance("JKS"); ksca.load(new FileInputStream("ca.db"), "manager".toCharArray()); X509Certificate cacert = (X509Certificate)ksca.getCertificate("ca"); PrivateKey caprivate = (PrivateKey)ksca.getKey("ca", "manager".toCharArray()); // The subject certificate access KeyStore ksbar = KeyStore.getInstance("JKS"); ksbar.load(new FileInputStream("bar.db"), "example".toCharArray()); X509Certificate foocert = (X509Certificate)ksbar.getCertificate("foo"); PrivateKey fooprivate = (PrivateKey)ksbar.getKey("foo", "example".toCharArray()); // The certificate chain building process X509V3CertificateGenerator engine = new X509V3CertificateGenerator(); engine.setSerialNumber(foocert.getSerialNumber()); engine.setSignatureAlgorithm(foocert.getSigAlgName()); engine.setNotBefore(foocert.getNotBefore()); engine.setNotAfter(foocert.getNotAfter()); engine.setPublicKey(foocert.getPublicKey()); engine.setSubjectDN(new X509Name(true, foocert.getSubjectX500Principal().getName())); engine.setIssuerDN(new X509Name(true, cacert.getIssuerX500Principal().getName())); // ... and a little signature ... X509Certificate foosigned = engine.generateX509Certificate(caprivate); X509Certificate[] signedchain = new X509Certificate[] { foosigned, cacert }; // The signed certificate update KeyStore ksbarca = KeyStore.getInstance("PKCS12", "BC"); ksbarca.load(null, null); // for initializing the keystore ksbarca.setKeyEntry("foo", fooprivate, "example".toCharArray(), signedchain); ksbarca.store(new FileOutputStream("bar.p12"), "example".toCharArray()); System.out.println(Arrays.asList(signedchain)); } catch (Exception ex) { ex.printStackTrace(); } } }
Now, being able to set up a server-side trust store keeping a CA certificate and to import a CA-signed certificate into your browser's certificate store, we can complete the client authentication configuration.
# Points to the trust store (cf. 1. above, don't forget to put the full path to the truststore) org.w3c.jigsaw.ssl.truststore.path= # Supplies the password for accessing the trust store ... org.w3c.jigsaw.ssl.truststore.password= # Optionally, you can decide, whether to force clients (right side set to: true) to authenticate or # also admit a client without successful authentication (right side set to: false), which is the default org.w3c.jigsaw.ssl.must.authenticate=
This should cover the setup requirements. When starting and accessing a server url, you should (after
server certificate presentation) be asked to type your browser's certificate store password, because the
server wants to check your client certificate. If this is successful or the
org.w3c.jigsaw.ssl.must.authenticate
option is set to false
you are allowed to continue.
Note, client certificates and other SSL characteristics are also transparent to a servlet via the
getAuthType
, getRemoteUser
, getUserPrincipal
methods and the following
request attributes of the servlet api:
javax.servlet.request.cipher_suite javax.servlet.request.key_size javax.servlet.request.X509Certificate