Distributed Matter - Blog

To content | To menu | To search

Tuesday, October 14 2008

Comparing Web of Trust and Hierarchical PKI for FOAF+SSL

I've been talking with Henry Story about SSL and security-related issues, following the publication of his blog entries: "RDFAuth: sketch of a buzzword compliant authentication protocol" and "FOAF & SSL: creating a global decentralised authentication protocol". Our discussion more or less started when I was making the first release of jSSLutils, and I'm also interested in authentication mechanisms in general. Henry got a few of us together to talk about this.

The idea behind Henry's proposal is to provide a secure authentication mechanism based on FOAF (Friend-of-a-friend) files and public key cryptography. It follows some of Dan Brickley's work; there's also a prototype server implementation by Pipian. One of the aim is to replace hierarchical Public Key Infrastructures (PKI), which are centralised, with something more flexible. Indeed, hierarchical PKIs rely on a Certificate Authority (CA) to assert the identity of a user or a server. This is typically how most people use HTTPS web-servers: you trust your bank's website because its certificate can be verified against a CA certificate which is trusted by your browser. What is perhaps less-widely known is the use of client-side certificate authentication. In this case, not only the server presents a certificate to the user, but the user also presents a certificate (for which he/she has a private key) to the server. If the server trusts the CA certificate that issued the certificate of the user, then it's a valid form of authentication. Again, this requires the user to have been delivered a certificate signed by a CA that the server trusts.

The most difficult aspect of establishing a Certificate Authority isn't the technical one: the main difficulty is in the legal and administrative process whereby the authority operates and delivers certificates. There are a number of commercial CAs (Verisign, Thawte, ...) which most browsers trust by default: there certificates are already in the browser (or underlying software) when you obtain it. The price required to be delivered a certificate vary depending on various attributes that can be in the certificate (for example code-signing), on the CA, and on how far they've actually been to check that the users are who they say they are. Some institutions also provide this service for free. For example, the UK e-Science CA can provide certificates to more or less all UK academics; despite being free for the user, the procedures are relatively thorough, since you have to turn up in person to a local approved CA representative, who will check your passport or similar proof of ID. This is not something that all commercial CAs do. It would be tempting to assume that the more someone has paid a CA for a certificate, the more certain you can be of their identity; this is not necessarily the case (although some people have a vested interest in making you think so).

A FOAF+SSL authentication mechanism would make it possible to avoid depending on a small number of CAs, and instead relies on a FOAF network to assert identity. This works along the lines of a Web-of-Trust (WoT) model, like OpenPGP, which can provide certain advantages (and possibly its share of problems).

Making this work in practice

You can find more details on Henry's blog. We want to use this to provide access control on the (semantic) web, using SSL as an underlying authentication mechanism. (As a first step, it's easier to focus on client-authentication using this method; we'll still use hierarchical CAs to assert the identity of a server.)

The way SSL client-side authentication works in most servers is by configuring a set of trusted CA certificates (the trust store in Java); this follows the X.509 PKI model of trust. If the client presents a certificate issued by a CA the server trusts, then the server authenticates the client. In most systems, the validation of the client certificate is done by the SSL library, which will reject it and most likely close the connection if cannot find a chain to a trusted CA certificate, before any application data is exchanged. Luckily, the way these underlying SSL libraries perform this verification can be customised.

What we've done (and there's some sample code in the Sommer project code repository) is "converting" an OpenPGP key-pair (which is in fact a form of certificate) into an X.509 certificate that can be used directly. It's just a self-signed certificate based on the OpenPGP key material: it contains the OpenPGP public key and is signed by the corresponding private key. If the client presents this certificate to a server during the SSL-handshake, this proves to the server that the client has the corresponding private key. Trusting what that certificates represent may then be handled differently, by customising the way trust is managed within the server. Of course, the X.509 certificate generated this way can also contain other pieces of information, including Subject Distinguished Name (Subject DN) and time-validity. We're still experimenting with this, and none of this is standardised, but the main extension we've been using is the "subject alternative name", which we've set to be the URI identifying the user; this fits the FOAF model quite well. We then tell the underlying SSL library to trust any client certificate, letting the layer above perform the trust verification (this can for example be done in Java using the TrustAllClientsWrappingTrustManager of jSSLutils).

Another approach, which has recently been published as an experimental RFC 5081 consists of extending TLS to support not only X.509 certificates but also PGP certificates. I think our approach is easier at the moment, since the approach in RFC 5081 would require changes in the existing SSL/TLS libraries (changes which I haven't seen, and which I doubt will happen in the short term for rather well-established projects such as OpenSSL or the JDK). The problem with our approach is that we move the evaluation of trust up to the layer that uses SSL, which means it has to be handled explicitly at the moment (of course, there's nothing preventing us from providing a library or similar module for this). I also reckon that the web-of-trust model can be a bit harder to evaluate in some cases, and this might require more interaction and configuration than the X.509 model had (just providing CA certificates and perhaps CRLs). It's anyway a more convenient way to experiment with this, rather than having to wait for RFC 5081-compliant implementations.

How to model trust

The hierarchical PKI model (X.509) is fairly simple to evaluate. The network of trust can be modelled as a tree, the root of which is the CA certificate; the chain is built between the leaf (the user certificate) to the root of the tree. This is also because CAs come with policies that specify which certificates intermediate CAs are allowed to sign so that the chain is valid. Although it has the inconvenience of being central (and thus concentrates power in the CA), it is relatively straightforward to understand, implement and evaluate.

If we want to use a Web-of-Trust model, we need to provide a new way to evaluate trust, and to model this in the FOAF extensions. (At this stage, I should point out that I know very little about FOAF/RDF/ontologies, but I'm planning to learn about all that very soon.)

There's a good description of how this can be done in Walking the Web of Trust, by Germano Caronni.

Another problem is that, in the CA model, a root CA or any intermediate in the chain is something for which:

  • you trust its identity, and
  • you trust its ability to perform the necessary steps to check and assert someone else's identity.

There are usually legal documents and policies in certificate authorities that define these agreements.

One must be quite careful in a Web-of-Trust model to make sure that this distinction is integrated in the function that evaluates trust. Trusting someone's identity and trusting someone's actions are rather distinct things. On the one hand, this can bring more complexity; on the other hand, this can bring more power to the model. For example, we could integrate more information than just asserting someone's friendship in a FOAF file, but add domains of expertise for which a server could choose to trust a user only if the model trusts them enough to be qualified to perform the task.

How to revoke trust

Problems with keys happen; we need to anticipate them. I think there are two main reasons for using Certificate Revocation Lists (CRLs) in the PKI world:

  1. the private key of a user has been lost or compromised,
  2. the user has done something bad and is no longer to be trusted.

The first problem is a matter of propagating the revocation to whoever has the user in their FOAF file. It's likely that he/she had them in his/her FOAF file, so it seems feasible. Similar things could happen if the keys of a CA were compromised or otherwise lost. Such a scenario would cause disruption, but it could be contained.

The second problem is really an authorisation issue, in fact, in a hierarchical PKI. The identity of the user could still be valid, thus authentication would work well, you would just want to deny authorisation. In the case of Web-of-Trust, this can be a bit more tricky, since you may have to re-evaluate the assertions you've made about his friends. Put it this way: is the friend of your former friend who betrayed you still your friend after that? I'm not sure there's a right answer to this, but I doubt this type of case can be handled automatically.

It's probably not a bad thing to re-assess the content of the FOAF file regularly, as Henry suggested, but this will demand actions from the user, and thus appropriate user education. In my experience, the problems with security are not as much technical as they're a matter of educating users and providing them with something easy enough to use. Otherwise, they might just not use your system securely or won't use it at all.

I'm not sure there is a right answer between Web-of-Trust or hierarchical PKI. It really depends on your working environment and on how easy it is to set up a PKI there. The advantages of the Web-of-Trust combined with FOAF are appealing: more flexibility, less dependence on a central system. Perhaps the two can be used together for two different usages: after all, you don't necessarily introduce your friends by showing their passport. This is only the beginning. I think the challenge is now to provide a suitable formula to evaluate trust, and to explain it to the users accordingly.

Thursday, May 22 2008

jSSLutils: Customisable configuration of SSL in Java

I recently released jSSLutils: a library to help configure SSL in Java.


In my current project, I have been designing and implementing a system for managing data and allow these data to be shared between the relevant people. Securing access to this data is a strong requirement of this project. This system is implemented using Restlet (only the server-side at the moment), in Java.

In our domain, we tend to use SSL client-side authentication, whereby not only the server presents a certificate to the client (like most secure consumer-oriented websites do) but the client also sends its certificate to the server for being authenticated. Some of these certificates may also be proxy-certificates, often used as a single sign-on (SSO) mechanism in grids based on GSI. We also have a public-key infrastructure (PKI) set up with a certificate authority (CA) for our community.

I've experimented with more advanced configurations of SSL, mainly dealing with proxy-certificates and Certificate Revocation Lists (CRLs), which are not always supported by Java applications out of the box. I had managed to get Jetty to accept proxy-certificates; this is possible by modifying the SSL connectors. Later on, I tried to do the same thing with Restlet. Restlet can use several SSL connectors (based on Jetty, Grizzly, or others). What is common to all these SSL configurations is that they require the TrustManagers to be adapted when building the SSLContext used to create the SSLSockets. This was a good opportunity to package my code and make it usable from several projects.


I have thus created this relatively small library: jSSLutils. The initial aims were:

  • to provide a consistent way to configure SSL-related parameters in Java applications,
  • to be able to customise the way keys and trust were managed (in particular grid proxy-certificates),
  • to be able to configure CRLs.

There is some initial documentation on the jSSLutils website. There are also examples in the form of jUnit tests in the source code. They even come with test keys, certificates and CRL so that you can try them out.

As of this week, version 0.3 is in the central Maven repository, which should make it easier to use.


Coincidentally, Henry Story was also looking for customisation features in SSL at the same time on the Restlet mailing-list. I was able to help him a bit for his work on FOAF & SSL: a global decentralised authentication protocol. You can find his work in the Som(m)er Address Book project. This looks like a very interesting approach for authentication, but I haven't found the time to get more involved in this project.


I've also looked at using PKCS#11 tokens and the Apple Keychain (on Mac OS X) from Java, to store and to use the keys and certificates. While investigating this, I found out that some applications (most of those I've looked into) were unable to support these features, at least not easily. Fortunately, the projects I've looked into are open source: I was therefore able to add the features I wanted and contribute them back to their communities. For example, I submitted a patch for Tomcat and a patch for Jetty, to make it possible to use the Apple Keychain or a different Java security provider (useful for static configuration of PKCS#11).

The code for loading a KeyStore in many Java applications seems to assume that it's going to be loaded from a file, which isn't the case for PKCS#11 tokens or the KeychainStore. jSSLutils also provides a jsslutils.keystores.KeyStoreLoader, which should help handling these cases as normal cases.


Comments and suggestions are welcome, please get in touch!