foaf+ssl: a first implementation
By bblfish on Nov 20, 2008
The first very simple implementations for the foaf+ssl protocol are now out: the first step in adding simple distributed security to the global open distributed decentralized social network that is emerging.
Update Feb 2009: I put up a service to create a foaf+ssl service in a few clicks. Try that out if you are short on time first.
The foaf+ssl protocol has been discussed in detail in a previous blog: "FOAF & SSL: creating a global decentralised authentication protocol", which goes over the theory of what we have implemented here. For those of you who have more time I also recommend my JavaOne 2008 presentation Building Secure, Open and Distributed Social Network Applications, which explains the need for a protocol such as this, gives some background understanding of the semantic web, and covers the working of this protocol in detail, all in a nice to listen to slideshow with audio.
In this article we are going to be rather more practical, and less theoretical, but still too technical for the likes of many. I could spend a lot of time building a nice user interface to help make this blog a point and click experience. But we are not looking for point and click users now, but people who feel at home looking at some code, working with abstract security concepts, who can be critical and find solutions to problems too, and are willing to learn some new things. So I have simplified things as much as needs be for people who fall into that category (and made it easy enough for technical managers to follow too, I hope ).
To try this out yourself you need just download the source code in the So(m)mer repository. This can be done simply with the following command line:
(leave the password blank)
$ svn checkout https://sommer.dev.java.net/svn/sommer/trunk sommer --username guest
This is downloading a lot more code than is needed by the way. But I don't have time to spend on isolating all the dependencies, bandwidth is cheap, and the rest of the code in there is pretty interesting too, I am sure you will agree. Depending on your connection speed, this will take some time to download, so we can do something else in the meantime, such as have a quick look at the uml diagram of the foaf+ssl protocol:
Let us make clear who is playing what role. You are Romeo. You want your client - a simple web browser such as Firefox or Safari will do - to identify yourself to Juliette's Web server. Juliette as it happens is a semantic web expert and she trusts that if you are able to read through this blog, understand it, create your X509 certificate and set up your foaf file so that it publishes your public key information correctly then you are human, intelligent, avant-garde, and you have enough money to own a web server which is all to your advantage. As a result her semantically enabled server will give you the secret information you were looking for.
Juliette knows of course that at a later time things won't be that simple anymore, when distributed social networks will be big enough that the proportion of fools will be large enough for their predators to take an interest in this technology, and the tools for putting up a certificate will come packaged with everyone's operating system, embedded in every tool, etc... At that point things will have moved on and Juliette will have added more criteria to give access to her secret file. Not only will your certificate have to match the information in your foaf file as it does now, but given that she knows your URL and what you have published there of your social graph, she will be able to use that and your position in the social graph of her friends to enabling her server to decide how to treat you.
Creating a certificate and a foaf file
So the first thing to do is for you to create yourself a certificate and a foaf file. This is quite easy. You just need to do the following in a shell.
$ cd sommer/misc/FoafServer/ $ java -version java version "1.5.0_16" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b06-284) Java HotSpot(TM) Client VM (build 1.5.0_16-133, mixed mode, sharing) $ ant jar
Currently one needs at least Java 5 to run this.
Before you create your certificate, you need to know what your foaf URL is going to be. If you allready have a foaf file, then that is easy, and the following will get you going:
$ java -cp dist/FoafServer.jar net.java.dev.sommer.foafserver.utils.GenerateKey -shortfoaf Enter full URL of the person to identify (no relative urls allowed): for example: http://bblfish.net/people/henry/card#me http://bblfish.net/people/henry/card#me Enter password for new keystore :enterAnewPasswordForNewStore publish the triples expressed by this n3 # you can use use cwm to merge it into an rdf file # or a web service such as http://www.rdfabout.com/demo/validator/ to convert it to rdf/xml # Generated by sommer.dev.java.net @prefix cert: <http://www.w3.org/ns/auth/cert#> . @prefix rsa: <http://www.w3.org/ns/auth/rsa#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . <http://bblfish.net/people/henry/card#me> a foaf:Person; is cert:identity of [ a rsa:RSAPublicKey; rsa:public_exponent "65537"\^cert:decimal ; rsa:modulus """b6bd6ce1a5ef51aaa69752c6af2e71948ab6da 9e5a5f086dba7548d8b80150d392117d90138948062eec6ecb5745a45491eea03a46b0a1c2e6324d 54144f42cdaa05ca39939eb973086cfedc8e31641cf7f29abc58310dcb8e56d9e6dae2233a317167 74d1eb32ced152084cfb860fb8cb5298a3c0270145c5d878f07f6417af"""\^cert:hex ; ] . the public and private keys are in the stored in cert.p12 you can list the contents by running the command $ openssl pkcs12 -clcerts -nokeys -in cert.p12 | openssl x509 -noout -text
If you do then run the openssl command you will find that the public key components should match the rdf above.
$ openssl pkcs12 -clcerts -nokeys -in cert.p12 | openssl x509 -noout -text Enter Import Password: MAC verified OK Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha1WithRSAEncryption Issuer: CN=http://bblfish.net/people/henry/card#me Validity Not Before: Nov 19 10:58:50 2008 GMT Not After : Nov 10 10:58:50 2009 GMT Subject: CN=http://bblfish.net/people/henry/card#me Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:b6:bd:6c:e1:a5:ef:51:aa:a6:97:52:c6:af:2e: 71:94:8a:b6:da:9e:5a:5f:08:6d:ba:75:48:d8:b8: 01:50:d3:92:11:7d:90:13:89:48:06:2e:ec:6e:cb: 57:45:a4:54:91:ee:a0:3a:46:b0:a1:c2:e6:32:4d: 54:14:4f:42:cd:aa:05:ca:39:93:9e:b9:73:08:6c: fe:dc:8e:31:64:1c:f7:f2:9a:bc:58:31:0d:cb:8e: 56:d9:e6:da:e2:23:3a:31:71:67:74:d1:eb:32:ce: d1:52:08:4c:fb:86:0f:b8:cb:52:98:a3:c0:27:01: 45:c5:d8:78:f0:7f:64:17:af Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical CA:TRUE X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment, Key Agreement, Certificate Sign Netscape Cert Type: SSL Client, S/MIME X509v3 Subject Key Identifier: 85:CD:66:A3:F7:23:DA:42:4B:F6:44:A1:90:A8:FE:27:9E:55:64:FE X509v3 Authority Key Identifier: keyid:85:CD:66:A3:F7:23:DA:42:4B:F6:44:A1:90:A8:FE:27:9E:55:64:FE X509v3 Subject Alternative Name: URI:http://bblfish.net/people/henry/card#me Signature Algorithm: sha1WithRSAEncryption a6:e0:3f:7c:cb:78:9b:f1:75:7f:62:ca:20:9e:a3:bb:87:61: 29:59:3f:b9:bb:70:c5:06:bd:9a:62:fc:98:32:b7:f4:8b:53: ca:69:fc:5e:01:6a:4c:d8:85:5c:b3:a1:84:ec:1c:d2:6f:a8: 0f:dd:c0:ff:9f:88:d2:84:8f:77:48:2e:f0:91:fb:2c:2a:22: 96:07:be:ce:b2:98:87:ee:40:bd:16:32:fa:11:55:fb:0f:96: fb:c4:f8:be:66:3f:98:fa:62:61:0b:2f:b5:02:98:97:53:35: b5:46:32:c4:38:01:4c:97:66:aa:79:40:1a:67:45:bd:a0:e1: 97:72
Notice also that the X509v3 Subject Alternative Name, is your foaf URL. The Issuer Distinguished name (starting with CN= here) could be anything.
This by the way, is the certificate that you will be adding to your browser in the next section.
If you don't have a foaf file, then the simplest way to do this is to:
- decide where you are going to place the file on your web server
- decide what the name of it is
- Put a fake file there named
- get that file with a browser by typing in the full url there
- your foaf url with then be
Then you can use the following command to create your foaf file:
$ java -cp dist/FoafServer.jar net.java.dev.sommer.foafserver.utils.GenerateKey
That is the same as the first one but without the
-shortfoaf argument. You will be asked for some information to fill up your foaf file, so as to make it a little more realistic -- you might as well get something useful out of this. You can then use either cwm or a web service to convert that N3 into rdf/xml, which you can then publish at the correct location. Now entering your url into a web browser should get your foaf file.
Adding the certificate to the browser
The previous procedure will have created a certificate cert.p12, which you now need to import into your browser. The software that creates the certificate could I guess place it in your browser too, but that would require some of work to make it cross platform. Something to do for sure, but not now. On OSX adding certs programmatically to the Keychain application is quite easy.
So to add the certificate to your browsers store, open up Firefox's preferences and go to the Advanced->Encryption tab as shown here
Click on "View Certificates" button, and you will get the Certificate Manager window pictured here.
Click the import button, and import the certificate we created in the previous section. That's it.
Starting Juliette's server
In a few days time Ian Jacobi will have a python based server working with the new updated certificate ontology. I will point to that as soon as he has it working. In the mean time you can run Juliette's test server locally like this:
$ ant run
This will start her server on your computer on localhost on port 8843 where it will be listening on a secure socket.
Connecting your client to Juliette's server
So now you can just go to https://localhost:8843/servlet/CheckClient in your favorite browser. This is Juliette's protected resource by the way, so we have moved straight to step 2 in the above UML diagram.
Now because this is a server running locally, and it has a secure port open that emits a certificate that is not signed by a well established security authority things get more complicated than they usually need be. So the following steps appea only because of this and so, to make it clear that this is just a result of this experiment, I have placed the following paragraph in a blue background. You will only need to do this the first time you connect in this experminent, so be weary of the blues.
Firefox gave me the following warning the first time I tried it.
This is problematic because it just warns that the server's certificate is not trusted, but does not allow you to specify that you trust it (after all, perhaps you just mailed you the public key in the certificate and you could use that information to decide that you trust the server).
On trying again, shift reloading perhaps, I am not sure, I finally got Firefox to present me with the following secure connection failed page:
Safari had done the right things first off. Since we trust localhost:8843 (having just started it and even inspected some of the code ) we just need to click the "Or you can add an exception ..." link, which brings up the dialog below:
They are trying to frighten users here of course. And so they should. Ahh if only we had a localhost signed certificate by a trusted CA, I would not have to write this whole part of the blog!So of course you go there and click "Add Exception...", and this brings up the following dialog.
So click "Get Certificate" and get the server certificate. When done you can see the certificate
And confirm the security Exception.
Again all of this need not happen. But since it also makes clear what is going on, it can be helpful to show it.
Choose your certificate
Having accepted the server's certificate, it will now ask you for yours. As a result of this Firefox opens up the following dialog.
Since you only have one client certificate this is an easy choice. If you had a number of them, you could choose which persona to present to the site. When you click Ok, the certificate will be sent back to the server. This is the end of stage 2 in the UML diagram above.
At that point Juliette's server ( on localhost ) will go and get your foaf file (step 3), and compare the information about your public key to the one in the certificate you just presented (step 4) by making the following query on your foaf file, as shown in the CheckClient class:
If the information in the certificate and the foaf file correspond, then the server will send you Juliette's secret information. In a Tabulator enabled browser this comes out like this:
TupleQuery query = rep.prepareTupleQuery(QueryLanguage.SPARQL,
The source code for all that is not far, and you will see that the algorithms used are very simple. This proves that the minimal piece, which is equivalent to what OpenID does, works. Next we will need to build up the server so that it can make decisions based on a web of trust. But by then you will have your foaf file, and filled up your social network a little for this to work.
Discussions on this and on a number of other protocols in the same space is currently happening on the foaf protocols mailing list. You are welcome to join the sommer project to work on the code and debug it. As I mentioned Ian Jacobi has a public server running which he should be updating soon with the new certificate ontology that we have been using here.
Clearly it would be really good to have a number of more advanced servers running this in order to experiment with access controls that add social proximity requirements.
Things to look at:
- What other browsers does this work with?
- Can anyone get this to work with Aladdin USB e-Token keys or similar tools?
- Work on access controls that take social proximity into account
- Does this remove the need for cookie identifiers on web sites?
I hope to be able to present this at the W3C Workshop on the Future of Social Networking in January 2009.