cryptographic web of trust
By bblfish on Aug 09, 2007
As our identity moves more and more onto the Web our ability to have people trust that what we write has not been altered is becoming increasingly important. As our home page becomes our OpenId, linking to our CV, blogs and foaf information, it will become more important for services to be able to trust that the information they see really is what I wrote. Otherwise the following scenario can become all to easy to imagine. Someone breaks into my web server and changes the OpenId link on my home page to point to a server they control. They then go and post comments around the web using my openid as identity. Their server of course always authenticates them. People who receive the posts then click on the OpenId URL which happens to be my home page, read information about me, and seeing that information trust that the comment really came from me.
What is needed is some way to increase the methods people can have to trust information I state. Here I describe how one can use cryptography to increase that trust level. Starting from my creation of a PGP key, I show how I can describe my public signature in my foaf file, used PGP to sign that file and then link to the signature so that people can detect a tampered file. From this basis I show how one can build a very solid cryptographically enhanced web of trust.
Creating your PGP public key
After reading the first part of "SafariBooks Online, and feeling comfortable that I understood the basics, I decided it was high time for me to create myself a Public PGP key. Reading the GPG Manual and a few other HOWTOs on the web, using the gnu GPG library, I managed to make myself one quite easily.
Linking to the Public Key from your foaf fileHaving this it was just a matter of placing it on my web site and using the Web Of Trust ontology developed by Dan Brickley to point to it and describe it, with the following triples:
@prefix wot: <http://xmlns.com/wot/0.1/> . @prefix : <http://bblfish.net/people/henry/card#> . :me is wot:identity of [ a wot:PubKey; wot:pubkeyAddress <http://bblfish.net/people/henry/henry.pubkey.asc>; wot:fingerprint "0DF560B5DADF6D348CC99EA0FD76F60D4CAE10D7"; wot:hex_id "4CAE10D7"; wot:length 1024 ] .
is wot:identity of construct is a nice N3 short hand for refering to the inverse relation of wot:identity, without having to name one. This states that my public key can be found at http://bblfish.net/people/henry/henry.pubkey.asc, and describe its fingerprint, key length and its hex id. I am not sure why the wot:PubKey resource has to be a blank node, and can't be the URL of the public key itself, which would make for the following N3:
:me is wot:identity of [ = < http://bblfish.net/people/henry/henry.pubkey.asc> a wot:PubKey; wot:fingerprint "0DF560B5DADF6D348CC99EA0FD76F60D4CAE10D7" ] .
Perhaps simply because it is quite likely that one would want to put copies of one's public key in dfiferent places? owl:sameAs could have done the trick there too though...
Signing your foaf file
Anyway, once that is done, I want to be able to sign my foaf file. Of course it would be pretty tricky to sign the foaf file and put the signature into the foaf file simultaneously, as that would change the content of the foaf file and make the signature invalid. So the easiest solution is to simply have the foaf file point to the signature with something like this 
<> wot:assurance <card.asc>
The problem with this solution is that my foaf file at http://bblfish.net/people/henry/card currently returns two different representations: a rdf/xml one and an N3 one depending one how it is called. (More on this in I have a Web 2.0 name!). Now a signature is valid only for a sequence of bits, and the rdf sequence of bits is different from the N3 sequence, so they can't both have the same sig. There is a complicated solution developed by Jeremy Carroll in his paper Signing RDF Graphs, which proposes to sign a canonicalised RDF graph. The problem is that the algorithm to create such a graph does take some time to compute, only works on a subset of all RDF graphs, but mostly that no software currently implements that algorithm.
Luckily there is a simple solution, which I got by inspiration from my work on creating an ontology for Atom, Atom OWL, and that is to link my card explicity to their alternate representation (the
<link type="alternate" href="...">)  and to sign those alternate representations. This gives me the following triples:
@prefix iana: <http://www.iana.org/assignments/relation/> . @prefix awol: <http://bblfish.net/work/atom-owl/2006-06-06/#> . <http://bblfish.net/people/henry/card> a foaf:PersonalProfileDocument; iana:alternate <http://bblfish.net/people/henry/card.rdf>, <http://bblfish.net/people/henry/card.n3> . <http://bblfish.net/people/henry/card.rdf> wot:assurance <http://bblfish.net/people/henry/asc.card.rdf.asc> ; awol:type "application/rdf+xml" . <http://bblfish.net/people/henry/card.n3> wot:assurance &lhttp://bblfish.net/people/henry/asc.card.n3.asc> ; awol:type "text/rdf+n3" .
Here I am saying that my card has two alternate representations, an rdf and an n3 one, what their mime type is, and where I can find the signature for each. Simple.
So if I put all of the above together I get the following extract from my N3 file:
@prefix foaf: <http://xmlns.com/foaf/0.1/>. @prefix wot: <http://xmlns.com/wot/0.1/> . @prefix awol: <http://bblfish.net/work/atom-owl/2006-06-06/#> . @prefix iana: <http://www.iana.org/assignments/relation/> . @prefix : <http://bblfish.net/people/henry/card#> . <http://bblfish.net/people/henry/card> a foaf:PersonalProfileDocument; foaf:maker :me; foaf:title "Henry Story's FOAF file"; foaf:primaryTopic :me ; iana:alternate <http://bblfish.net/people/henry/card.rdf>, <http://bblfish.net/people/henry/card.n3> . <http://bblfish.net/people/henry/card.rdf> wot:assurance <http://bblfish.net/people/henry/asc.card.rdf.asc> ; awol:type "application/rdf+xml" . <http://bblfish.net/people/henry/card.n3> wot:assurance <http://bblfish.net/people/henry/asc.card.n3.asc> ; awol:type "text/rdf+n3" . :me a foaf:Person; foaf:title "Mr"; foaf:family_name "Story"; foaf:givenname "Henry"; foaf:openid <http://openid.sun.com/bblfish> ; foaf:openid <http://bblfish.videntity.org/> ; is wot:identity of [ a wot:PubKey; wot:pubkeyAddress <ttp://bblfish.net/people/henry/henry.pubkey.asc>; wot:fingerprint "0DF560B5DADF6D348CC99EA0FD76F60D4CAE10D7"; wot:hex_id "4CAE10D7"; wot:length 1024 ];
Which can be graphical represented as follows:
Building a web of TrustFrom here is is easy to see how I can use the wot ontology to sign other files, link to my friends public signatures, sign their public signatures, how they could sign mine, etc, etc. and thereby create a cryptographically enhanced Web of Trust built on decentralised identity. Of course this is still a little complicated to put together by hand, but it should be really easy to automate, by incorporating it into the Beatnik Address Book for example. To illustrate this I will show I linked up to Dan Brickley and Tim Berners Lee's signature.
<http://danbri.org/foaf.rdf> a foaf:PersonalProfileDocument; wot:assurance <http://danbri.org/foaf.rdf/foaf.rdf.asc> . <http://danbri.org/foaf.rdf#danbri> foaf:pubkeyAddress <http://danbri.org/danbri-pubkey.txt>
(foaf:pubkeyAddress is a relation that is not defined in foaf yet. Dan, one of the co-creators of foaf, is clearly experimenting here) Now with this information I can download Danbri's rdf, the public key and the signature and test that the document has not been tampered with. On the command line I do it like this:
bblfish$ gpg --import danbri.pubkey.asc bblfish$ curl http://danbri.org/foaf.rdf > danbri.foaf.rdf bblfish$ curl http://danbri.org/foaf.rdf.asc > danbri.foaf.rdf.asc bblfish$ gpg --verify danbri.foaf.rdf.asc danbri.foaf.rdf
Of course this assumes that someone has not broken onto his server and changed all those files. As it happens I chatted with Dan over Skype (which I got from his foaf file!) and he sent me his public key that way. It certainly felt like I had Dan on the other side of the line, so I trust this public key enough. But why not publish what public key I am relying on? Then Dan and others can know what signature I am using and correct me if I am wrong. So I added the following to my foaf file
:me foaf:knows [ = <http://danbri.org/foaf.rdf#danbri>; a foaf:Person; foaf:name "Dan Brickley"; is wot:identity of [ a wot:PubKey; wot:pubkeyAddress <http://danbri.org/danbri-pubkey.txt>; wot:hex_id "B573B63A" ] ] .
In the above I am linking to Dan's public key on his server, the one that might have been compromised. Note that I specify the wot:hex_id of the public key though. Finding another public key with the same hex would be tremendously difficult I am told. But who knows. I have not done the maths on this. But I can make it even more difficult by signing his public key with my key, and placing that signature on my server.
bblfish$ gpg -a --detach-sign danbri.pubkey.asc
Then I can make that signature public by linking to it from my foaf file
<http://danbri.org/danbri-pubkey.txt> wot:assurance <danbri.pubkey.asc.asc> .
Now people who read my foaf file will know how I verify Dan's information, and detect if something does not fit between what I say and what Dan's says. If they then do the same when linking to my foaf file - that is mention in it where one is to find my public key, it's hash and sign my public key with their signature, placing that on their server - then anyone who would want to compromise any of us consistently to the outside world, would have to compromise all of the information on each of our servers consistently. As more people are added to the network, and link up to each other, the complexity of doing this grows exponentially. As there are more ways to tie information together there are more ways people can find the information, so the information becomes more valuable (as described in RDF and Metcalf's Law), and there are more ways to find inconsistencies, thereby making the information more reliable, thereby making it more valuable, and so on, and so on...
One can even make things more complicated for a wannabe hacker by placing other people's public keys one one's server, thereby duplicating information. Tim Berners Lee does not link to his public key, but I got it over irc, and published it on my web server. Then I can add that information to my foaf file:
:me foaf:knows [ = <http://www.w3.org/People/Berners-Lee/card#i>; a foaf:Person; foaf:name "Tim Berners Lee"; is wot:identity of [ a wot:Pubkey; wot:pubkeyAddress <timbl.pubkey.asc> ; wot:hex_id "9FC3D57E" ]; ] .
By making public what public keys I use, I get the following benefits:
- people can contact me and let me know if I am being taken for a ride,
- it helps them locate public keys
- the metadata associated with a public key grows
- more people link into the cryptography network, making it more likely that more tools will build into this system
Encrypting parts of one's foaf file
Now that you have my public signature you can send me encrypted mail or other files using my public signature, verify signatures I place around the web and read files I encrypt with my private key. Of the files that I can encrypt one interesting one is my own foaf file. Of course encrypting the whole foaf file is not so helpful, as it breaks down the web of trust piece. But there may well be pieces of a foaf file that I would like to encrypt for only some people to see. This can be done quite easily as described in "Encrypting Foaf Files" . Note that the encrypted file can be encrypted for a number of different users simultaneously. This would be simple to do, and would be of great help in making current practice available in an intelligent and coherent way to the semantic web. One thing I could do is encrypt it for all of my friend whose public key I know. I am not sure what kind of information I would want to do this with, but well, it's good to know its possible.
- This is how "PGP Signing FOAF Files" describes the procedure.
- The iana alternate (
http://www.iana.org/assignments/relation/) relation is not dereferenceable. It would be very helpful if iana made ontologies for each of their relations available.
- Thanks to Stephen Livingstone for pointing that way in a reply to this blog post on the openid mailing list.
- A huge numbers of resources on the subject can be found on the Semantic Web Trust and Security Resource Guide, which I found via the Wikipedia Web of Trust page.
- This can be used to build a very simple but powerful web authentication protocol as described in my March 2008 article RDFAuth: sketch of a buzzword compliant authentication protocol