Ben Laurie - Up-Goer 5 Capabilities
Just for fun, I tried to explain capabilities using only the ten hundred most used words. Here’s what I came up with.
They are a way to allow people to use the things they are allowed to use and not the things they are not allowed to use by giving them a key for each thing they are allowed to use. Every thing has its own key. If you are shown a key you can make another key for the same thing. Keys should be very, very, very hard to guess.
For capability purists: yes, I am describing network capabilities.
Ben Laurie - Sea Bass and Dal
The sea bass part of this is really easy: fry sea bass fillets in extra virgin olive oil and some sea salt for about 5 minutes skin side down, which makes it lovely and crispy, then turn over for about 30 seconds to cook it through. Obviously you do this at the end.
Dal is a more moveable feast – I used a mix of toor dal (oily, as it happens, but plain would be fine), white urad dal and red lentils – these all cook relatively quickly and end up quite soft. Fry onions in ghee, add ground cumin, coriander, fennel, fenugreek, dried red chili, star anise (I know this is non standard, but it is great in dal) and whole mustard seeds. You can play with this mix infinitely, but that’s what I used tonight. Fry the washed dal briefly in the onion/spice mix and then add water. Boil hard for about 30 mins, stirring occasionally, adding water as needed (a quite wet outcome is perfectly ok) until the dal is soft but still retains a little identity. Towards the end add chicken stock and salt.
I also did cardamom rice (take whole cardamom, beat up somewhat in a pestle and mortar and chuck into the rice/water mix at the beginning – cook the rice however you cook rice). The whole combo was lovely – crispy sea bass contrasted nicely with the soft, spicy dal, and the rice gave that slight citric edge.
Ben Laurie - Clocks and Security
I keep running into this.
People want to design protocols where replay attacks are prevented. To prevent replay attacks, you have to keep track of what’s already been said. But you don’t want to do this forever, so the smart thing to do is include time in the protocol. That is, the message is accepted if both the timestamp is recent and the nonce (or whatever) has not previously been used. This means that the server can discard nonces after a while and not worry about allowing replays of very old packets.
But then the problem is that clients don’t have the right time.
And so people jump through hoops to take account of this fact – extra round trips, time offsets, all sorts of nonsense.
Can we stop dancing around the problem and just fix the damn client’s clock? If the user wants the clock set wrong, fine – all we need is a correct clock for protocols. The machine can continue to show the user whatever wrong time he wants to see.
So how do we get this correct clock? Well, that doesn’t seem hard – we have NTP already, and it works pretty well. If we have mutually distrusting parties that don’t want to rely on each other’s clocks, then it doesn’t seem hard to have clocks with signatures (NTP already supports this) so each distrusting group can nominate its trusted time servers and multiple clocks can be maintained for them.
This seems like an entirely soluble problem, yet every time I review a protocol that needs it, it is thrown up as completely insoluble. It really seems like it’s time to bite that bullet – it’s not even hard (a rubber bullet?)!
Note: this does not solve any problems to do with untrusted clients. You still need to design your protocols to resist clients that want to mess with you. But at least you could stop worrying about time skew.
Ben Laurie - I Hate Java, or How To Make Ant Run Javascript
I am writing this up because it took me all day to figure out, and the Interwebz was surprisingly unhelpful!
So, if you’re trying to configure EJBCA, or maybe something else whose author thought that including Javascript in a makefile was a really great idea, you may run into this error, when you run ant:
/disk1.1/usr/home/ben/software/unpacked/ejbca_4_0_12/propertyDefaults.xml:11: Unable to create javax script engine for javascript
If you Google for that, maybe you’ll now find this article, but as I write, you get a lot of hits on people with this problem, and a paucity of useful advice. So, here’s how I fixed it…
First off, the core problem is ant needs BSF (the Bean Scripting Framework) in order to run scripts at all, and also Rhino, in order to run Javascript. And to complicate matters further, BSF needs Jakarta Commons Logging. It turns out you can get these in various ways, some of which I’ve tested. In particular, you can generally download zips of jars (and other junk) from the projects’ sites (generally described as binaries, for some reason), or you might be able to install packages or ports. In practice I got BSF from its own site, logging by installing a port, and I tried Rhino both ways. So, once you’ve got the relevant jars, the next bit of magic is to let Ant know about them.
You can either install them in Ant’s library directory, wherever that is, or name them in a -lib argument on the command line. Like this:
ant -lib '../bsf-2.4.0/lib/bsf.jar:/usr/local/share/java/classes/commons-logging.jar:/usr/local/share/java/rhino/rhino.jar' <target>
And Robert, as they say, is a close relative. Update: putting them on the classpath does work, so long as you remember the classpath is separated by colons and not semicolons. On some platforms. However, this does not make jrunscript work.
So, this solved my immediate problem, but I’m now really curious to know how jrunscript can be made to understand JS. Coz right now, despite having all the stuff I need to make Ant do it, I get
script engine for language js can not be found
How about it, lazyweb?
BTW, I hate Java.
Ben Laurie - What Is SHA-3 Good For?
Cryptographers are excited because NIST have announced the selection of SHA-3. There are various reasons to like SHA-3, perhaps most importantly because it uses a different design from its predecessors, so attacks that work against them are unlikely to work against it.
But if I were paranoid, there’d be something else I’d be thinking about: SHA-3 is particularly fast in hardware. So what’s bad about that? Well, in practice, on most platforms, this is not actually particularly useful: it is quite expensive to get data out of your CPU and into special-purpose hardware – so expensive that hardware offload of hashing is completely unheard of. In fact, even more expensive crypto is hardly worth offloading, which is why specialist crypto hardware manufacturers tend to concentrate on the lucrative HSM market, rather than on accelerators, these days.
So, who benefits from high speed hardware? In practice, it mostly seems to be attackers – for example, if I want to crack a large number of hashed passwords, then it is useful to build special hardware to do so.
It is notable, at least to the paranoid, that the other recent crypto competition by NIST, AES, was also hardware friendly – but again, in a way useful mostly to attackers. In particular, AES is very fast to key – this is a property that is almost completely useless for defence, but, once more, great if you have some encrypted stuff that you are hoping to crack.
The question is, who stands to benefit from this? Well, there is a certain agency who are building a giant data centre who might just like us all to be using crypto that’s easy to attack if you have sufficient resource, and who have a history of working with NIST.
Just sayin’.
Ben Laurie - Compression Violates Semantic Security
There’s been quite a lot of noise about the still not-fully-disclosed CRIME attack on TLS recently. But, fully disclosed or not, I think we can say with certainty that it turns out that compression is a problem.
The interesting thing, to me at least, is that, in retrospect, this is completely obvious. In cryptography, we have standards that we hold encryption algorithms to, and one of these is semantic security. In short, this means that an attacker should learn nothing (other than length[1]) about a plaintext, given its ciphertext. One way this is often phrased is as a game: given two plaintexts of equal lengths, and one ciphertext made from one of the two plaintexts, then an attacker, who knows everything about the algorithm other than the key, should not be able to guess better than chance which of the two plaintexts was used.
It is obvious that, in general, if compression is used, this game can only go the attacker’s way: the length of the ciphertext must reveal something about the content of the plaintext. This is because, in general, not all texts can compress – indeed, if some plaintexts come out shorter, there must also be some that come out longer. So, since the attacker knows what compression algorithm is in use, he can tell which of the two plaintexts was used by the length of the ciphertext, in general (note that there may be pairs of plaintexts for which this is not true, but in general, there are pairs where the lengths are different). And thus he wins the game, which shows that compression simply cannot be used in a system giving semantic security[2].
And we expect TLS to give semantic security, just like all modern crypto. So, it should’ve been obvious from the start that compression was a non-runner. Why did we not realise? I think the answer to that question would be very interesting indeed. Also, what else do we do now that obviously violates semantic security?
[1] Sometimes even academics admit to real world constraints!
[2] Pedants might argue that actually, yes, you can use compression: just pad everything to the longest a plaintext could compress to. As I’ve noted above, if the compression works at all (that is, some texts are reduced in length), then some texts must actually expand. Which means that you must pad to longer than the original length. So, yeah, pedant, you can use compression, but only if it actually expands!
Ben Laurie - Revocation Transparency and Sovereign Keys
In line with Certificate Transparency (note, updated version, 2.1a), we’ve been thinking about how to do something similar for revocation. Not because we have any particular plan but because as soon as we mention CT, people always say “what about revocation?”. Which is, admittedly, in a bit of a pickle, and it isn’t at all obvious how to fix it. But however its fixed, we think its a good idea to have transparency – for everyone to be assured that they are seeing revocation state that is the same as everyone else is seeing, and for revocations to be auditable – just as we think certificate issuance should be.
So, we’re quite excited that recently we came up with not one, but two, mechanisms. One of them (Sparse Merkle Trees) even appears to be novel. There’s a brief write-up here.
Also, it turns out, Sparse Merkle Trees can be used to solve a problem that has been bugging me with Sovereign Keys since day one. The issue is that in SK the relying party needs to trust mirrors to tell it what the current status of any particular domain is (i.e. what the current key is), because the only other way to be sure is to download the entire database, which will be many gigabytes long. Using Sparse Merkle Trees plus a CT-like append-only log (as described in the RT document), this is no longer the case. Instead, we can generate a sparse tree containing leaves corresponding to the hashes of domain names. The value stored at the leaf is the domain’s current key (or whatever we want to store there). The sparse tree allows us to verify efficiently that we are, indeed, seeing the latest version, and the append-only log prevents abuse of the change mechanism to make temporary changes shown only to a subset of relying parties.
Ben Laurie - Who Remembers VASCO?
When I talk to people about what I’m doing, I usually mention the DigiNotar fiasco. I’m often surprised by how many people remember it, especially those not involved in security – and often not particularly technical.
DigiNotar, of course, no longer exists as a result of this incident. But who remembers VASCO, the company that owned DigiNotar? No-one, as far as I can tell. Apparently they suffer not at all from their incompetence.
I particularly love their press release
VASCO expects the impact of the breach of DigiNotar’s SSL and EVSSL business to be minimal. Through the first six months of 2011, revenue from the SSL and EVSSL business was less than Euro 100,000. VASCO does not expect that the DigiNotar security incident will have a significant impact on the company’s future revenue or business plans.
Well, they were not wrong there!
Ben Laurie - Verifiable Logs: Solving The “Cryptocat Problem”
There’s been a lot of heat about Cryptocat lately. But not much light. In summary, one side says you can’t trust software you download from the ‘net to not reveal all your secrets, and the other side says that’s all we got, so suck it up. So, how do we fix this problem?
First off, lets take a look at the core of the problem: if you download something from the ‘net, how can you be sure what you got is what was advertised? One of the much-lauded benefits of open source is that it can be reviewed – experts can take a look and see whether it really does what it says. So, that deals with half the problem. But how do we know we got what the experts reviewed?
I propose that the answer is publicly verifiable logs. The idea is that anyone can operate a log of “stuff” that can be verified by anyone else. What do I mean by “verified”? I mean that if two people see the log, they can mutually check that they saw the same thing. Of course, this is trivial if you are prepared to send the whole log to each other – just check they’re identical. The trick is to do this verification efficiently.
Luckily we have a way to do that: Merkle Trees. These allow us to summarise the log with a short chunk of binary (the “root”). If we both get the same root, then we both have the same log. What’s more, they also allow an efficient proof that any particular item is in the log – given the item, the log can show a chain of hashes leading to the root. This chain proves that the item actually is in the log summarised by the root.
What’s more, with only a bit more cunningness, we can also efficiently show that any version of the log (with more data appended) contains any prior version. In other words, we can show that the log never deletes anything, but only grows by adding new things at the end.
Got it? To reiterate: it is possible to create a log that can demonstrate that everyone sees the same version, and that as it grows, everyone continues to see the same data added to it. What’s more, these things can be done efficiently[1].
Now we have that piece of machinery, how do we use it to solve the “Cryptocat problem”? Simple: every time Cryptocat does a new release, it pushes a copy of the source into the verifiable log. Every time you download Cryptocat, you verify that the version you are given is in the public log, and refuse to run it if not. And we’re done.
If Cryptocat ever decides to release a version that, say, reveals your keys, or decrypts your chats for a third party, then that version is on display for all to see. Cryptocat will get caught – and likely caught quite quickly. If Cryptocat tries to avoid this publication, then you won’t run it, so you’ll be safe.
Admittedly this does not actually _prevent_ Cryptocat from shafting you, but it does mean it is very unlikely to get away with it, and having done it once, it will probably not get the chance to do it to anyone again…
Note that it doesn’t matter if the author of Cryptocat is the one who made the change, or someone who hacked his site, or a man-in-the-middle. If they do not publish source, then you won’t run it. And if they do publish source, they get caught.
Incidentally, I originally proposed publicly verifiable logs for fixing PKI but they have many uses. Also, for Certificate Transparency, we are implementing a publicly verifiable log. I would be very happy to help with a version for logging software instead of certificates.
[1] To get an idea of what I mean by “efficiently” a proof that two log versions are consistent or that a particular item is in a particular log version consists of log_2(n) hashes, where n is the number of items in the log. So, for a log with a billion items, this proof would have around 30 entries, each, say, 32 bytes long. So, it takes me less than 1 kB for a proof about a log with a billion entries. How about a trillion? Just ten more entries, i.e. under 1,300 bytes.
Ben Laurie - Certificate Transparency Version 2
A lot of people didn’t like that the original version had a delay before you could issue a new certificate. So, we redesigned the protocol to avoid that problem.
In a nutshell, a new certificate is sent to the log, which immediately returns a signed hash of the certificate, indicating that the cert will be included in the log. It is required to actually appear in the log before a certain amount of time has passed. Other than that, everything proceeds along the same lines as before, though there are many detailed changes.
As always, comments welcome.
Ben Laurie - Venison and Chestnut Stew
Cooked this last night, it was pretty yummy.
onion
bacon
venison (not sure what cut, we used a casserole mix from here)
flour
carrot
celery
red wine
chicken stock
bouquet garni
garlic
chestnuts
jelly (e.g. redcurrant, medlar)
Fry the chopped onion and bacon for a while. Add the venison chunks and fry until browned (note that proper recipes give you a lot of hooey about coating in flour and frying in batches – whilst I am as much a fan of the Maillard reaction as the next guy, I don’t think it is necessary to do it to every bit of meat in the whole stew, and nor can I discern an advantage in burning the flour). Unless your hob is a lot hotter than mine, what will almost certainly happen is it’ll brown a bit and then release a bunch of juices which it’ll boil in. If you want more browning, then give in to convention and fry in small batches. Anyway, once its boiled a bit, throw in some flour, stir until mixed then add wine and stock, about half and half, to cover the meat. Add thinly sliced carrot, celery and the bouquet garni at this point.
Leave to boil gently for 1 hour, then add the chestnuts (I used vacuum-packed ones). I added some crushed garlic, too, because I forgot it earlier. Add the medlar/redcurrant/whatever jelly, too (I used both of those). Boil for another hour. Eat.
I served it with herby mashed potato and leek and peas in saffron cream. Pretty damn good.
Ben Laurie - Factoring RSA
Apparently I have not blogged about factoring weak RSA keys before. Well, I guess I have now
One thing I’ve been wondering ever since that research was done is: is there anything OpenSSL could do about this? I’ve been assuming OpenSSL was used to generate at least some of those keys.
So, I was interested to read this analysis. First off, it shows that it is highly likely that the bad keys were generated by OpenSSL and one other (proprietary) implementation. However, I have to argue with some details in an otherwise excellent writeup.
Firstly, this canard irritates me:
Until version 0.9.7 (released on Dec 31, 2002) OpenSSL relied exclusively on the /dev/urandom source, which by its very definition is non-blocking. If it does not have enough entropy, it will keep churning out pseudo-random numbers possibly of very poor quality in terms of their unpredictability or uniqueness.
By definition? Whose definition? When did Linux man pages become “by definition”? In FreeBSD, which, IMO, has a much sounder approach to randomness, urandom does block until it has sufficient entropy. Is poor design of the OS OpenSSL’s fault?
Which brings me to
FreeBSD prior to version 5 posed its own problem, since its /dev/random source silently redirected to /dev/urandom.
Well. Modern FreeBSD versions link /dev/urandom to /dev/random. That doesn’t seem like a material change to me. I’m pretty sure that the implementation changed, too – perhaps that’s more important than filenames?
Finally, in the summary:
Some unfortunate choices by the OpenSSL library didn’t help either.
Oh really? So the fact that a 10-year-old version of OpenSSL used a device that in some OSes is not very well designed is contributing to this problem? I’m finding this a little hard to swallow. Also, “choices”? What choices? Only one choice is mentioned.
The real problem is, IMNSHO: if you provide a weak random number source, then people will use it when they shouldn’t. The problem here is with the OS that is providing the randomness, not the OpenSSL library. So, why is the OS (which I am prepared to bet is Linux) not even mentioned?
Ben Laurie - Using Capsicum For Sandboxing
FreeBSD 9.0, released in January 2012, has experimental Capsicum support in the kernel, disabled by default. In FreeBSD 10, Capsicum will be enabled by default.
But unless code uses it, we get no benefit. So far, very little code uses Capsicum, mostly just experiments we did for our paper. I figured it was time to start changing that. Today, I’ll describe my first venture – sandboxing bzip2. I chose bzip2 partly because Ilya Bakulin had already done some of the work for me, but mostly because a common failure mode in modern software is mistakes made in complicated bit twiddling code, such as decompressors and ASN.1 decoders.
These can often lead to buffer overflows or integer over/underflows – and these often lead to remote code execution. Which is bad. bzip2 is no stranger to this problem: CVE-2010-0405 describes an integer overflow that could lead to remote code execution. The question is: would Capsicum have helped – and if it would, how practical is it to convert bzip2 to use Capsicum?
The answers are, respectively, “yes” and “fairly practical”.
First of all, how does Capsicum mitigate this problem? The obvious way to defend a decompressor is to run the decompression engine in a separate process with no privilege beyond that needed to get its job done – which is the ability to read the input and write the output. In Capsicum, this is easy to achieve: once the appropriate files are open, fork the process and enter capability mode in the child. Discard all permissions except the ability to read the input and write the output (in Capsicum, this means close all other file descriptors and limit those two to read and write), and then go ahead and decompress. Should there be a bug in the decompressor, what does the attacker get? Well, pretty much what he had already: the ability to read the input file (he supplied it, so no news there!) and the ability to write arbitrary content to the output file (he already had that, since he could have chosen arbitrary input and compressed it). He also gets to burn CPU and consume memory. But that’s it – no access to your files, the network, any other running process, or anything else interesting.
I think that’s pretty neat.
But how hard is it to do? I answer that question in a series of diffs on GitHub, showing a step-by-step transformation of bzip2 into the desired form. I used a technique I like to call error-driven development; the idea is you attempt to make changes that will cause compilation to fail until you have completely accomplished your goal. This is a useful way to reassure yourself that you have made all necessary updates and there’s nothing hiding away you didn’t take care of. If you follow along by building the various stages, you’ll see how it works.
It turns out that in bzip2 this matters – it isn’t very beautifully written, and the code that looks like it might cleanly just take an input file and an output file and do the work in isolation, actually interacts with the rest of the code through various function calls and globals. This causes a problem: once you’ve forked, those globals and functions are now in the wrong process (i.e. the child) and so it is necessary to use RPC to bridge any such things back to the parent process. Error-driven development assures us that we have caught and dealt with all such cases.
So how did this work out in practice? Firstly, it turns out we have to give the compressor a little more privilege: it writes to stderr if there are problems, so we need to also grant write on stderr (note that we could constrain what it writes with a bit more effort). The callbacks we have to provide do not, I think, let it do anything interesting: cause the program to exit, make the output file’s permissions match the input file’s, and remove the input or output files (ok, removing the input file is slightly interesting – but note that bzip2 does this anyway).
Secondly, because we have not yet decided on an RPC mechanism, this particular conversion involves quite a bit of boilerplate: wrapping and unwrapping arguments for RPCs, wiring them up and all that, all of which would be vastly reduced by a proper RPC generator. Try not to let it put you off
Finally, the system has (at least) one global, errno. I did not deal with that so far, which means some errors will report the wrong error – but it is not particularly hard to do so.
So, on to the diffs. This is something of an experimental way to present a piece of development, so I’d be interested in feedback. Here they are, in order:
- Step 1: move functions to be wrapped.
- Step 2: add header for wrapped functions.
- Step 3: wrap a function requiring authority.
- Step 4: move functions that do not require authority.
- Step 5: rename and invoke wrapped functions.
- Step 6: build other files.
- Step 7: wrap a global.
- Step 8: fix similar problems.
- Step 9: wrap a function in the parent.
- Step 10: wrap a 2-way global.
- Step 11: continue to apply the methodology.
- Step 12: get back on track with error-driven development.
- Step 13: define unwrappers.
And there you are: bzip2 is now rendered safe from decompressor exploits, and it was only a few hours work. As we refine the support infrastructure, it will be even less work.
Ben Laurie - Persian Pulled Lamb
I don’t usually link to existing recipes, but this was so good, I had to: http://uktv.co.uk/food/recipe/aid/647703. We only let it marinade for one day, which seemed to work fine.
Ben Laurie - Salmon and Peas in a Saffron Cream Sauce
An impromptu and fast recipe that worked really well.
saffron
butter
olive oil
salt
pepper
mixed herbs
salmon steak fillets
frozen peas
cream
Put the saffron in a small amount of hot water. Get the butter and oil hot enough to bubble, add salt, pepper, mixed herbs. Shortly after, add the salmon, skin side down. Fry until the skin is crispy, then turn onto a side. Fry for a couple of minutes, turn again until all four sides are done. Throw in the frozen peas and mix with the fat. Add the saffron (and water, of course). Bring to the boil, then add cream. Bring to the boil again, season and serve. Try to keep one side of the salmon above the waterline throughout.
We had it with pasta. Start the pasta before the salmon, it really is that quick!
Ben Laurie - EFF Finally Notice 0day Market
Six years after I first blogged about it, the EFF have decided that selling 0days may not be so great.
Maybe they should be reading my blog?
Ben Laurie - Certificate Transparency: Spec and Working Code
Quite a few people have said to me that Certificate Transparency (CT) sounds like a good idea, but they’d like to see a proper spec.
Well, there’s been one of those for quite a while, you can find the latest version in the code repository, or for your viewing convenience, I just made an HTML version.
Today, though, to go with that spec, I’m happy to announce working code for a subset of the protocol. This covers the trickiest part – a fully backwards compatible SSL handshake between servers and clients. The rest of the protocol will necessarily all be new code for interacting with the log server and other new components, and so should not have these issues.
If you build the code according to the README, then you will find instructions in test/README for the demo.
What this does, in short, is the following:
- Run a CT log server. Currently this has no persistence across runs, but does keep a full log in memory.
- Issue a self-signed server certificate. A CA issued certificate would also be fine, but not so easy to automate for a demo.
- Use the CT client to register that certificate with the log server and to obtain a log proof for it.
- Use the CT client to convert that proof into a fake “certificate” which can be included in the certificate chain in the TLS handshake.
- Run an Apache 2.2 instance to serve the self-signed certificate and the log proof certificate. Note that Apache is unmodified, all that is needed is appropriate configuration.
- Use the CT client to connect to the Apache instance and verify the presented log proof.
- You can also connect to Apache with an existing browser to check that you can still access the site despite the presence of the log proof.
There’s plenty more to be done, but this is the part that needs the earliest scrutiny, since we are bending the rules to get back compatibility and avoid the need to change server software. Client software has to change anyway to provide any benefit to users, so that’s less of a worry.
We welcome discussion, suggestions and questions on the mailing list.
Ben Laurie - How “Free” Leads to Closed
The FSF is fond of banging on about how the GPL is more “free” than other open source licences, even though it is actually a more restrictive licence than many others (for example, the Apache Licence).
So I find it ironic that the much anticipated Raspberry Pi is about as un-free as it is possible to be. Yes, it runs Linux. Can you run anything else? No, because the chipset is not documented, it is impossible to write drivers for any other OS. Its hard to imagine what would have happened if the dominant open OS was BSD or Apache licensed, but it is interesting to speculate: would this have happened in that world? Possibly not – one of the reasons the ASF adopted a more free licence was precisely because it is business-friendly. Would chipmakers obsessively protect their chip specs in that world? Who knows, but I like to think not.
In any case, if I were building a device like the Pi, I would not be using undocumented chips.
Ben Laurie - Certificate Transparency Sites
I may not have said much more about Certificate Transparency, but we’ve been working on it. So, those interested in following along (or joining in) are welcome to look at…
The code repository also includes the spec, in xml2rfc format.
Ben Laurie - Fixing CAs
Adam Langley and I have a proposal to bolster up the rather fragile Certificate Authority infrastructure.
TL;DNR: certificates are registered in a public audit log. Servers present proofs that their certificate is registered, along with the certificate itself. Clients check these proofs and domain owners monitor the logs. If a CA mis-issues a certificate then either
- There is no proof of registration, so the browser rejects the certificate, or
- There is a proof of registration and the certificate is published in the log, in which case the domain owner notices and complains, or
- There is a proof of registration but the certificate does not appear in the log, in which case the proof is now proof that the log misbehaved and should be struck off.
And that, as they say, is that.
Update: Adam has blogged, exploring the design space.
Ben Laurie - Open Source Transcription Software Developer
Since we set up FreeBMD, FreeREG and FreeCEN things have come a long way, and so we’re revisiting how we do transcription. Those great guys at Zooniverse have released their Scribe transcription software, which they developed to use with Old Weather and Ancient Lives (and more to come), as open source.
We are working with them to develop a new transcription platform for genealogical records, based on Scribe, and we want to hire a developer to help us with it. Scribe itself is written in Ruby, so some familiarity with that would help. We also use Python and EC2, so knowing about those would be good, too. And the front-end is sure to be using Javascript, so there’s another tickbox to tick.
Finally, we intend to open source everything, and so a developer used to working in an open source community would be helpful.
Everything is negotiable. FreeBMD does not have offices, so this would be “work from home” (or the beach, or whatever suits you).
If you’re interested, send email to freebmd-sd@links.org. Feel free to forward this post, of course.
Ben Laurie - Lessons Not Learned
Anyone who has not had their head under a rock knows about the DigiNotar fiasco.
And those who’ve been paying attention will also know that DigiNotar’s failure is only the most recent in a long series of proofs of what we’ve known for a long time: Certificate Authorities are nothing but a money-making scam. They provide us with no protection whatsoever.
So imagine how delighted I am that we’ve learnt the lessons here (not!) and are now proceeding with an even less-likely-to-succeed plan using OpenID. Well, the US is.
If the plan works, consumers who opt in might soon be able to choose among trusted third parties — such as banks, technology companies or cellphone service providers — that could verify certain personal information about them and issue them secure credentials to use in online transactions.
Does this sound familiar? Rather like “websites that opt in can choose among trusted third parties – Certificate Authorities – that can verify certain information about them and issue them secure credentials to use in online transactions”, perhaps? We’ve seen how well that works. And this time there’s not even a small number of vendors (i.e. the browser vendors) who can remove a “trusted third party” who turns out not to be trustworthy. This time you have to persuade everyone in the world who might rely on the untrusted third party to remove them from their list. Good luck with that (good luck with even finding out who they are).
What is particularly poignant about this article is that even though it’s title is “Online ID Verification Plan Carries Risks” the risks we are supposed to be concerned about are mostly privacy risks, for example
people may not want the banks they might use as their authenticators to know which government sites they visit
and
the government would need new privacy laws or regulations to prohibit identity verifiers from selling user data or sharing it with law enforcement officials without a warrant.
Towards the end, if anyone gets there, is a small mention of some security risk
Carrying around cyber IDs seems even riskier than Social Security cards, Mr. Titus says, because they could let people complete even bigger transactions, like buying a house online. “What happens when you leave your phone at a bar?” he asks. “Could someone take it and use it to commit a form of hyper identity theft?”
Dude! If only the risk were that easy to manage! The real problem comes when someone sets up an account as you with one of these “banks, technology companies or cellphone service providers” (note that CAs are technology companies). Then you are going to get your ass kicked, and you won’t even know who issued the faulty credential or how to stop it.
And, by the way, don’t be fooled by the favourite get-out-of-jail-free clause beloved by policymakers and spammers alike, “opt in”. It won’t matter whether you opt in or not, because the proof you’ve opted in will be down to these “trusted” third parties. And the guy stealing your identity will have no compunction about that particular claim.
Ben Laurie - DNSSEC on the Google Certificate Catalog
I mentioned my work on the Google Certificate Catalog a while back. Now I’ve updated it to sign responses with DNSSEC.
I also updated the command-line utility to verify DNSSEC responses – and added a little utility to fetch the root DNSSEC keys and verify a PGP signature on them.
As always, feedback is welcome.
Ben Laurie - An Efficient and Practical Distributed Currency
Now that I’ve said what I don’t like about Bitcoin, it’s time to talk about efficient alternatives.
In my previous paper on the subject I amused myself by hypothesizing an efficient alternative to Bitcoin based on whatever mechanism it uses to achieve consensus on checkpoints. Whilst this is fun, it is pretty clear that no such decentralised mechanism exists. Bitcoin enthusiasts believe that I have made an error by discounting proof-of-work as the mechanism, for example
I believe Laurie’s paper is missing a key element in bitcoin’s reliance on hashing power as the primary means of achieving consensus: it can survive attacks by governments.
If bitcoin relied solely on a core development team to establish the authoritative block chain, then the currency would have a Single Point of Failure, that governments could easily target if they wanted to take bitcoin down. As it is, every one in the bitcoin community knows that if governments started coming after bitcoin’s development team, the insertion of checkpoints might be disrupted, but the block chain could go on.
Checkpoints are just an added security measure, that are not essential to bitcoin’s operation and that are used as long as the option exists. It is important for the credibility of a decentralized currency that it be possible for it to function without such a relatively easy to disrupt method of establishing consensus, and bitcoin, by relying on hashing power, can.
Ben, your analysis reads as though you took your well-known and long-standing bias against proof-of-work and reverse engineered that ideology to fit into an ad hoc criticism of bitcoin cryptography. You must know that bitcoin represents an example of Byzantine fault tolerance in use and that the bitcoin proof-of-work chain is the key to solving the Byzantine Generals’ Problem of synchronising the global view.
My response is simple: yes, I know that proof-of-work, as used in Bitcoin, is intended to give Byzantine fault tolerance, but my contention is that it doesn’t. And, furthermore, that it fails in a spectacularly inefficient way. I can’t believe I have to keep reiterating the core point, but here we go again: the flaw in proof-of-work as used in Bitcoin is that you have to expend 50% of all the computing power in the universe, for the rest of time in order to keep the currency stable (67% if you want to go for the full Byzantine model). There are two problems with this plan. Firstly, there’s no way you can actually expend 50% (67%), in practice. Secondly, even if you could, it’s far, far too high a price to pay.
In any case, in the end, control of computing power is roughly equivalent to control of money – so why not cut out the middleman and simply buy Bitcoins? It would be just as cheap and it would not burn fossil fuels in the process.
Finally, if the hash chain really works so well, why do the Bitcoin developers include checkpoints? The currency isn’t even under attack and yet they have deemed them necessary. Imagine how much more needed they would be if there were deliberate disruption of Bitcoin (which seems quite easy to do to me).
But then the question would arise: how do we efficiently manage a distributed currency? I present an answer in my next preprint: “An Efficient Distributed Currency”.
Ben Laurie - Decentralised Currencies Are Probably Impossible (But Let’s At Least Make Them Efficient)
How time flies. Following my admittedly somewhat rambling posts on Bitcoin, I decided to write a proper paper about the problem. So, here’s a preprint of “Decentralised Currencies Are Probably Impossible (But Let’s At Least Make Them Efficient)”. It’s short! Enjoy.
I may submit this to a conference, I haven’t decided yet. Suggestions of where are welcome.
By the way, Bitcoin fanboys: I see I have been taken to task for my heretic views on the Bitcoin forums. Since those have cunningly been closed to anyone who does not already have some kind of track record of conforming to the standards of the forums (presumably meaning “don’t diss Bitcoin”) I am unable to respond to comments there, but I would like to note, for the record, that I have not deleted a single non-spam comment on my Bitcoin posts, contrary to claims I see there.
Ben Laurie - Bitcoin is Slow Motion
OK, let’s approach this from another angle.
The core problem Bitcoin tries to solve is how to get consensus in a continuously changing, free-for-all group. It “solves” this essentially insoluble problem by making everyone walk through treacle, so it’s always evident who is in front.
But the problem is, it isn’t really evident. Slowing everyone down doesn’t take away the core problem: that someone with more resources than you can eat your lunch. Right now, with only modest resources, I could rewrite all of Bitcoin history. By the rules of the game, you’d have to accept my longer chain and just swallow the fact you thought you’d minted money.
If you want to avoid that, then you have to have some other route to achieve a consensus view of history. Once you have a way to achieve such a consensus, then you could mint coins by just sequentially numbering them instead of burning CPU on slowing yourself down, using the same consensus mechanism.
Now, I don’t claim to have a robust way to achieve consensus; any route seems to open to attacks by people with more resources. But I make this observation: as several people have noted, currencies are founded on trust: trust that others will honour the currency. It seems to me that there must be some way to leverage this trust into a mechanism for consensus.
Right now, for example, in the UK, I can only spend GBP. At any one time, in a privacy preserving way, it would in theory be possible to know who was in the UK and therefore formed part of the consensus group for the GBP. We could then base consensus on current wielders of private keys known to be in the UK, the vast majority of whom would be honest. Or their devices would be honest on their behalf, to be precise. Once we have such a consensus group, we can issue coins simply by agreeing that they are issued. No CPU burning required.
Ben Laurie - Bitcoin 2
Well, that got a flood of comments.
Suppose I take 20 £5 notes, burn them and offer you a certificate for the smoke for £101. Would you buy the certificate?
This is the value proposition of Bitcoin. I don’t get it. How does that make sense? Why would you burn £100 worth of non-renewable resources and then use it to represent £100 of buying power. Really? That’s just nuts, isn’t it?
I mean, it’s nice for the early adopters, so long as new suckers keep coming along. But in the long run it’s just a pointless waste of stuff we can never get back.
Secondly, the point of referencing “Proof-of-work Proves Not to Work” was just to highlight that cycles are much cheaper for some people than others (particularly botnet operators), which makes them a poor fit for defence.
Finally, consensus is easy if the majority are honest. And then coins become cheap to make. Just saying.
Ben Laurie - Bitcoin
A friend alerted to me to a sudden wave of excitement about Bitcoin.
I have to ask: why? What has changed in the last 10 years to make this work when it didn’t in, say, 1999, when many other related systems (including one of my own) were causing similar excitement? Or in the 20 years since the wave before that, in 1990?
As far as I can see, nothing.
Also, for what its worth, if you are going to deploy electronic coins, why on earth make them expensive to create? That’s just burning money – the idea is to make something unforgeable as cheaply as possible. This is why all modern currencies are fiat currencies instead of being made out of gold.
Bitcoins are designed to be expensive to make: they rely on proof-of-work. It is far more sensible to use signatures over random numbers as a basis, as asymmetric encryption gives us the required unforgeability without any need to involve work. This is how Chaum’s original system worked. And the only real improvement since then has been Brands‘ selective disclosure work.
If you want to limit supply, there are cheaper ways to do that, too. And proof-of-work doesn’t, anyway (it just gives the lion’s share to the guy with the cheapest/biggest hardware).
Incidentally, Lucre has recently been used as the basis for a fully-fledged transaction system, Open Transactions. Note: I have not used this system, so make no claims about how well it works.
(Edit: background reading – “Proof-of-Work” Proves Not to Work)
Ben Laurie - Checking SSL Certificates
I mentioned my work on the Google Certificate Catalog recently. One thing I forgot is a command-line utility I wrote to perform the check for you automatically.
Ben Laurie - Pepper-crusted Tuna
I came across this on my frequent travels to the US (where they tend to call it pepper-crusted ahi, or even, rather redundantly, pepper-crusted ahi tuna). I don’t think I’ve ever seen it in the UK, but it is fantastically easy to cook. And delicious.
Tuna steaks (nice and fresh, so you can leave them rare)
Black peppercorns
Szechuan pepper (optional)
Crush the peppercorns in a pestle and mortar (or mortar and pestle if you’re American). They don’t need to be particularly finally divided, but try to at least split each one in half. Spread half the mix over one side of your tuna steaks and press it in – it sticks surprisingly well. Turn over and repeat. Then fry in hot olive oil for about 4 minutes a side (up to 8 if you’re too chicken for rare tuna, but I promise it tastes/feels much better rare). Do not keep turning them over, turn them just once. Sprinkle on some sea salt when done.
That’s it.
I often serve with plain boiled rice and pak choi.
Ben Laurie - Improving SSL Certificate Security
Given how often I say on this blog that I am not speaking for my employer, I am amused to be able to say for once that I am. Over here.
Ben Laurie - Census FAIL
Once every ten years, every household in the UK gets to fill in a census form. This year, for the first time ever, I think, you can do it online. So, imagine how delighted we are that I am the only person in my household whose name actually fits in the box. Yes, really, there’s a 50 character limit.
Why? Suppose they’d splashed out and allowed 500 characters instead. What would that cost? Well, let’s assume 100M names. That’s an extra 450 x 100 = 45,000 MB of data, assuming they’re still using databases with fixed width fields. 45 GB. That would’ve cost them nearly an extra £5 at today’s prices. Not £5 per person, or £5 per household. £5 total.
Thank god for government savings, eh?
BTW, my wife rang and asked what to do. Amazingly, they opt for the least useful possible answer: start at the beginning of your name and keep going ’til you run out of space. I’m sure future generations will be very happy to have complete middle names and no surname. Not.
Ben Laurie - ZFS Part 3: Replacing Dead Disks
As discussed in my previous article, if a disk fails then a ZFS system will just carry on as if nothing has happened. Of course, we’d like to restore the system to its former redundant glory, so here’s how…
Once more, we simulate a failure by removing the primary disk, but this time replace it with a new unformatted disk (I guess if the new disk was already bootable you’d need to fix that first).
Let’s assume we’re several years down the line and no longer have any documentation at all. First off, find your disks by inspecting dmesg. As before we have ad4 and ad8. ad4 is the new disk.
# diskinfo -v ad4 ad8
ad4
512 # sectorsize
500107862016 # mediasize in bytes (466G)
976773168 # mediasize in sectors
0 # stripesize
0 # stripeoffset
969021 # Cylinders according to firmware.
16 # Heads according to firmware.
63 # Sectors according to firmware.
S20BJ9AB212006 # Disk ident.
ad8
512 # sectorsize
500107862016 # mediasize in bytes (466G)
976773168 # mediasize in sectors
0 # stripesize
0 # stripeoffset
969021 # Cylinders according to firmware.
16 # Heads according to firmware.
63 # Sectors according to firmware.
9VMYLC5V # Disk ident.
This time they are conveniently exactly the same size, despite having diffferent manufacturers (Samsung and Seagate respectively). We already know from the first article in this series that we can deal with disks that don’t look the same, and in any case only 250GB is currently replicated. So, let’s partition the new disk as the old one…
# gpart show ad8
=> 34 976773101 ad8 GPT (466G)
34 128 1 freebsd-boot (64K)
162 4194304 2 freebsd-swap (2.0G)
4194466 484202669 3 freebsd-zfs (231G)
488397135 488376000 4 freebsd-zfs (233G)
# gpart show -l ad8
=> 34 976773101 ad8 GPT (466G)
34 128 1 (null) (64K)
162 4194304 2 swap8 (2.0G)
4194466 484202669 3 system8 (231G)
488397135 488376000 4 scratch8 (233G)
# gpart create -s gpt ad4
ad4 created
# gpart add -b 34 -s 128 -t freebsd-boot ad4
ad4p1 added
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ad4
bootcode written to ad4
# gpart add -s 4194304 -t freebsd-swap -l swap4 ad4
ad4p2 added
# gpart add -s 484202669 -t freebsd-zfs -l system4 ad4
ad4p3 added
# gpart add -t freebsd-zfs -l scratch4 ad4
ad4p4 added
# gpart show ad4
=> 34 976773101 ad4 GPT (466G)
34 128 1 freebsd-boot (64K)
162 4194304 2 freebsd-swap (2.0G)
4194466 484202669 3 freebsd-zfs (231G)
488397135 488376000 4 freebsd-zfs (233G)
Now we’re ready to reattach the disk to the various filesystems.
First the swap. Since we can’t remove the dead disk from the gmirror setup, first we forget then add the new swap partition back in.
# gmirror forget swap
# gmirror insert -h -p 1 swap /dev/gpt/swap4
# gmirror status
Name Status Components
mirror/swap DEGRADED gpt/swap8
gpt/swap4 (29%)
and after a while
# gmirror status
Name Status Components
mirror/swap COMPLETE gpt/swap8
gpt/swap4
Next the main filesystem. In this case, since the new device has the same name as the old one, we can just write
# zpool replace system /dev/gpt/system4
If you boot from pool 'system', you may need to update
boot code on newly attached disk '/dev/gpt/system4'.
Assuming you use GPT partitioning and 'da0' is your new boot disk
you may use the following command:
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
Once more we’ve already done this step, so no need to do it again. Note, this command took a little while, don’t be alarmed!
# zpool status
pool: scratch
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
scratch ONLINE 0 0 0
gpt/scratch8 ONLINE 0 0 0
errors: No known data errors
pool: system
state: DEGRADED
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
scrub: resilver in progress for 0h0m, 9.77% done, 0h2m to go
config:
NAME STATE READ WRITE CKSUM
system DEGRADED 0 0 0
mirror DEGRADED 0 0 0
gpt/system8 ONLINE 0 0 0
replacing DEGRADED 0 0 0
gpt/system4/old UNAVAIL 0 0 0 cannot open
gpt/system4 ONLINE 0 0 0 221M resilvered
errors: No known data errors
and after not very long
# zpool status
pool: scratch
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
scratch ONLINE 0 0 0
gpt/scratch8 ONLINE 0 0 0
errors: No known data errors
pool: system
state: ONLINE
scrub: resilver completed after 0h1m with 0 errors on Sun Mar 27 13:04:02 2011
config:
NAME STATE READ WRITE CKSUM
system ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/system8 ONLINE 0 0 0
gpt/system4 ONLINE 0 0 0 2.21G resilvered
errors: No known data errors
And we’re all good, back to where we were before. Reboot to check everything is fine.
Note, by the way, that all of this was done on a live system in multi-user mode. Apart from the occasional reboot there was no loss of service whatsoever.
Also, because the primary disk didn’t really fail, if I wanted I could put it in my other machine and end up with a working replicated system there without any need for setup.
There is one niggling question remaining: I started off with one 250 GB and one 500 GB disk. I now have two 500 GBs, which means the non-redundant scratch file system I had before could now become redundant. Or they could become part of the system pool. Or they could become a bigger non-redundant scratch filesystem.
In the end I decided to do the simplest thing, which is to make the scratch partitions part of the larger system partition. If I ever need to rearrange that is always possible either with the help of an additional disk or, even, with less safety, by taking one of the disks out of the pools and rearranging onto that (see a description of doing this kind of thing on freenas).
So, to make them part of the existing pool, first destroy the scratch filesystem (if I’d already used it I’d have to copy it before I started, but since I haven’t I can just blow it away). Since we mounted the pool direct, we destroy it with zpool:
# zpool destroy scratch
(and we can confirm it has gone with zpool list and zfs list). Just
for naming sanity, I rename the two scratch partitions:
# gpart modify -i 4 -l system8.p2 ad8
ad8p2 modified
# gpart modify -i 4 -l system4.p2 ad4
ad4p2 modified
and since those aren’t reflected in /dev/gpt, reboot. Then finally
# zpool add system mirror /dev/gpt/system4.p2 /dev/gpt/system8.p2
and presto
# zpool list
NAME SIZE USED AVAIL CAP HEALTH ALTROOT
system 463G 2.21G 461G 0% ONLINE -
Ben Laurie - ZFS Part 2: Disk Failure
Before I’m ready to trust ZFS I need to make sure I can replace a disk when it dies. With the setup described here, as a first experiment I removed the primary disk.
So, power down and remove the primary disk (ad4). Note that if you’re doing this on the Proliant system I mentioned, then you really should replace the drive mount (it is needed for cooling). Luckily I have a spare system so I just borrowed one.
Reboot. Comes up fine on the secondary disk without further intervention.
$ zpool status
pool: scratch
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
scratch ONLINE 0 0 0
gpt/scratch8 ONLINE 0 0 0
errors: No known data errors
pool: system
state: DEGRADED
status: One or more devices could not be opened. Sufficient replicas exist for
the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
see: http://www.sun.com/msg/ZFS-8000-2Q
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
system DEGRADED 0 0 0
mirror DEGRADED 0 0 0
gpt/system8 ONLINE 0 0 0
gpt/system4 UNAVAIL 0 0 0 cannot open
errors: No known data errors
Note that the system pool is now degraded. How would we have known if we hadn’t checked? Well, turns out we missed something from the previous setup.
We should have put
daily_status_zfs_enable="YES"
daily_status_gmirror_enable="YES"
in /etc/periodic.conf. Then in the daily mail we’d see:
Checking status of zfs pools:
pool: system
state: DEGRADED
status: One or more devices could not be opened. Sufficient replicas exist for
the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
see: http://www.sun.com/msg/ZFS-8000-2Q
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
system DEGRADED 0 0 0
mirror DEGRADED 0 0 0
gpt/system8 ONLINE 0 0 0
gpt/system4 UNAVAIL 0 0 0 cannot open
errors: No known data errors
Checking status of gmirror(8) devices:
Name Status Components
mirror/swap DEGRADED gpt/swap8
So remember, boys and girls, read your daily mails!
So far, so good. One disk failed, the system came back up without intervention, and would have alerted us in daily mails had we configured it correctly (of course it now is). So what happens if we put the disk back in? Since we’ve modified the other disk in the meantime, we’d hope that would get reconciled. Let’s see…
Power down and replace the missing disk, reboot.
Now we see
$ zpool status
pool: scratch
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
scratch ONLINE 0 0 0
gpt/scratch8 ONLINE 0 0 0
errors: No known data errors
pool: system
state: ONLINE
scrub: resilver completed after 0h0m with 0 errors on Sat Mar 26 10:48:56 2011
config:
NAME STATE READ WRITE CKSUM
system ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/system8 ONLINE 0 0 0
gpt/system4 ONLINE 0 0 0 345K resilvered
errors: No known data errors
$ gmirror status
Name Status Components
mirror/swap COMPLETE gpt/swap4
gpt/swap8
and there we are, back to where we started. But suppose the disk had really failed, then what? See the next exciting installment!
Ben Laurie - Completely Redundant Disks with ZFS and FreeBSD
A while back, I bought a ReadyNAS device for my network, attracted by the idea of RAID I can grow over time and mirrored disks.
Today I just finished building the same thing “by hand”, using FreeBSD and ZFS. At a fraction of the cost. Here’s how.
First off, I bought this amazing bargain: an HP ProLiant MicroServer. These would be cheap even at list price, but with the current £100 cashback offer, they’re just stupidly cheap. And rather nice.
Since I want to cater for a realistic future, I am assuming by the time I need to replace a drive I will no longer be able to buy a matching device, so I started from day one with a different second drive (the primary is 250 GB, secondary is 500 GB – both Seagate, which was not the plan, but I’ll remedy that in the next episode). I also added an extra 1GB of RAM to the machine (this is important for ZFS which is apparently not happy with less than 2GB of system RAM).
I then followed, more or less, Pawel’s excellent instructions for creating a fully mirrored setup. However, I had to deviate from them somewhat, so here’s my version.
The broad overview of the process is as follows
- Install FreeBSD on the primary disk, using a standard sysinstall.
- Create and populate gmirror and ZFS partitions on the secondary disk.
- Boot from the primary disk, but mount the secondary.
- Create and populate gmirror and ZFS partitions on the primary disk.
- Use excess secondary disk as scratch.
In my case the two disks are ad4 (primary, 250 GB) and ad8 (secondary, 500 GB). Stuff I typed is in italic.
Since we need identical size partitions for the mirror, we need to simulate the first disk (since it happens to be smaller). Get the disk’s size
# diskinfo -v /dev/ad4
/dev/ad4
512 # sectorsize
250059350016 # mediasize in bytes (233G)
488397168 # mediasize in sectors
0 # stripesize
0 # stripeoffset
484521 # Cylinders according to firmware.
16 # Heads according to firmware.
63 # Sectors according to firmware.
9VMQN8T5 # Disk ident.
Create a memory disk the same size. Note that the sector sizes must match!
# mdconfig -a -t swap -s 488397168
md0
Verify they are the same.
# diskinfo -v /dev/ad4 /dev/md0
/dev/ad4
512 # sectorsize
250059350016 # mediasize in bytes (233G)
488397168 # mediasize in sectors
0 # stripesize
0 # stripeoffset
484521 # Cylinders according to firmware.
16 # Heads according to firmware.
63 # Sectors according to firmware.
9VMQN8T5 # Disk ident.
/dev/md0
512 # sectorsize
250059350016 # mediasize in bytes (233G)
488397168 # mediasize in sectors
0 # stripesize
0 # stripeoffset
Now partition the memory disk as we will the first disk later on.
# gpart create -s gpt md0
md0 created
# gpart add -b 34 -s 128 -t freebsd-boot md0
md0p1 added
# gpart add -s 2g -t freebsd-swap -l swap1 md0
md0p2 added
# gpart add -t freebsd-zfs -l systemx md0
md0p3 added
and show the resulting sizes
# gpart show md0
=> 34 488397101 md0 GPT (233G)
34 128 1 freebsd-boot (64K)
162 4194304 2 freebsd-swap (2.0G)
4194466 484202669 3 freebsd-zfs (231G)
Now blow away the memory disk, we don’t need it any more.
# mdconfig -d -u 0
Create the partitions on the second disk.
# gpart create -s gpt ad8
ad8 created
# gpart add -b 34 -s 128 -t freebsd-boot ad8
ad8p1 added
# gpart add -s 2g -t freebsd-swap -l swap1 ad8
ad8p2 added
# gpart add -s 484202669 -t freebsd-zfs -l system8 ad8
ad8p3 added
And eat the rest of the disk as a scratch area (this area will not be mirrored, and so should only be used for disposable stuff).
# gpart add -t freebsd-zfs -l scratch8 ad8
ad8p4 added
Check it matches the md0 simulation
# gpart show ad8
=> 34 976773101 ad8 GPT (466G)
34 128 1 freebsd-boot (64K)
162 4194304 2 freebsd-swap (2.0G)
4194466 484202669 3 freebsd-zfs (231G)
488397135 488376000 4 freebsd-zfs (233G)
And don’t forget to set up the bootloader
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ad8
bootcode written to ad8
I realised as this point I had intended to label everything with an 8, to match the unit number, and had not done so for swap, so for completeness, here’s how you fix it
# gpart modify -i 2 -l swap8 ad8
ad8p2 modified
# gpart show -l ad8
=> 34 976773101 ad8 GPT (466G)
34 128 1 (null) (64K)
162 4194304 2 swap8 (2.0G)
4194466 484202669 3 system8 (231G)
488397135 488376000 4 scratch8 (233G)
Note that the label change is not reflected by the device names in /dev/gpt, which is needed for the next step, so at this point I rebooted.
Now set up the swap mirror.
# gmirror label -F -h -b round-robin swap /dev/gpt/swap8
Create the ZFS storage pool called system, consisting only of our system8 partition.
# zpool create -O mountpoint=/mnt -O atime=off -O setuid=off -O canmount=off system /dev/gpt/system8
And create a dataset – “mountpoint=legacy” stops ZFS from managing it.
# zfs create -o mountpoint=legacy -o setuid=on system/root
Mark it as the default bootable dataset.
# zpool set bootfs=system/root system
Mount it
# mount -t zfs system/root /mnt
# mount
/dev/ad4s1a on / (ufs, local)
devfs on /dev (devfs, local, multilabel)
system/root on /mnt (zfs, local, noatime)
And create the remaining mountpoints according to Pawel’s suggested layout…
# zfs create -o compress=lzjb system/tmp
# chmod 1777 /mnt/tmp
# zfs create -o canmount=off system/usr
# zfs create -o setuid=on system/usr/local
# zfs create -o compress=gzip system/usr/src
# zfs create -o compress=lzjb system/usr/obj
# zfs create -o compress=gzip system/usr/ports
# zfs create -o compress=off system/usr/ports/distfiles
# zfs create -o canmount=off system/var
# zfs create -o compress=gzip system/var/log
# zfs create -o compress=lzjb system/var/audit
# zfs create -o compress=lzjb system/var/tmp
# chmod 1777 /mnt/var/tmp
# zfs create -o canmount=off system/usr/home
And create one for each user:
# zfs create system/usr/home/ben
Now, at a slightly different point from Pawel, I edit the various config files. First /boot/loader.conf. Note that some of these are commented out: this is because, although they appear in Pawel’s version, they are already built into the kernel (this is because I use a GENERIC kernel and he uses a stripped-down one). Including them seems to cause problems (particularly geom_part_gpt, which causes a hang during boot if present).
geom_eli_load=YES
#geom_label_load=YES
geom_mirror_load=YES
#geom_part_gpt_load=YES
zfs_load=YES
vm.kmem_size=3G # This should be 150% of your RAM.
Enable ZFS
# echo zfs_enable=YES >> /etc/rc.conf
Change fstab for the new layout (note, you might want to edit these in – for example, my system had an entry for cd drives).
# cat > /etc/fstab
system/root / zfs rw,noatime 0 0
/dev/mirror/swap.eli none swap sw 0 0
^D
The .eli extension here is magic: geom_eli finds it at startup and automatically encrypts it.
Set the work directory for ports (so that it uses the faster compression scheme during builds).
# echo WRKDIRPREFIX=/usr/obj >> /etc/make.conf
These need to be done now because the next step is to copy the entire install to the new ZFS filesystem. Note that this particular command pastes completely incorrectly from Pawel’s blog post so be careful!
# tar -c --one-file-system -f - . | tar xpf - -C /mnt/
Tar can’t copy some types of file, so expect an error or two at this point:
tar: ./var/run/devd.pipe: tar format cannot archive socket
tar: ./var/run/log: tar format cannot archive socket
tar: ./var/run/logpriv: tar format cannot archive socket
Just for fun, take a look at the ZFS we’ve created so far…
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
system 1.12G 225G 21K /mnt
system/root 495M 225G 495M legacy
system/tmp 30K 225G 30K /mnt/tmp
system/usr 652M 225G 21K /mnt/usr
system/usr/home 50K 225G 21K /mnt/usr/home
system/usr/home/ben 29K 225G 29K /mnt/usr/home/ben
system/usr/local 297M 225G 297M /mnt/usr/local
system/usr/obj 21K 225G 21K /mnt/usr/obj
system/usr/ports 190M 225G 159M /mnt/usr/ports
system/usr/ports/distfiles 30.8M 225G 30.8M /mnt/usr/ports/distfiles
system/usr/src 165M 225G 165M /mnt/usr/src
system/var 100K 225G 21K /mnt/var
system/var/audit 21K 225G 21K /mnt/var/audit
system/var/log 35K 225G 35K /mnt/var/log
system/var/tmp 23K 225G 23K /mnt/var/tmp
Unmount ZFS
# zfs umount -a
And the one we mounted by hand
# umount /mnt
And set the new ZFS-based system to be mounted on /
# zfs set mountpoint=/ system
And … reboot! (this is the moment of truth)
After the reboot, you should see
$ mount
system/root on / (zfs, local, noatime)
devfs on /dev (devfs, local, multilabel)
system/tmp on /tmp (zfs, local, noatime, nosuid)
system/usr/home/ben on /usr/home/ben (zfs, local, noatime, nosuid)
system/usr/local on /usr/local (zfs, local, noatime)
system/usr/obj on /usr/obj (zfs, local, noatime, nosuid)
system/usr/ports on /usr/ports (zfs, local, noatime, nosuid)
system/usr/ports/distfiles on /usr/ports/distfiles (zfs, local, noatime, nosuid)
system/usr/src on /usr/src (zfs, local, noatime, nosuid)
system/var/audit on /var/audit (zfs, local, noatime, nosuid)
system/var/log on /var/log (zfs, local, noatime, nosuid)
system/var/tmp on /var/tmp (zfs, local, noatime, nosuid)
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
system 1.79G 225G 21K /
system/root 763M 225G 763M legacy
system/tmp 43K 225G 43K /tmp
system/usr 1.04G 225G 21K /usr
system/usr/home 50.5K 225G 21K /usr/home
system/usr/home/ben 29.5K 225G 29.5K /usr/home/ben
system/usr/local 297M 225G 297M /usr/local
system/usr/obj 416M 225G 416M /usr/obj
system/usr/ports 190M 225G 159M /usr/ports
system/usr/ports/distfiles 30.8M 225G 30.8M /usr/ports/distfiles
system/usr/src 165M 225G 165M /usr/src
system/var 106K 225G 21K /var
system/var/audit 21K 225G 21K /var/audit
system/var/log 41.5K 225G 41.5K /var/log
system/var/tmp 23K 225G 23K /var/tmp
$ swapinfo
Device 1K-blocks Used Avail Capacity
/dev/mirror/swap.eli 2097148 0 2097148 0%
Note that system is not actually mounted (it has canmount=off) – it is used to allow all the other filesystems to inherit the / mountpoint. The one that is actually mounted on / is system/root, which is marked as legacy because it is mounted before zfs is up.
Now we’re up on the second disk, time to get the first disk back in the picture (we’re using it for boot but nothing else right now).
First blow away the MBR
# dd if=/dev/zero of=/dev/ad4 count=79
79+0 records in
79+0 records out
40448 bytes transferred in 0.008059 secs (5018970 bytes/sec)
and create the GPT partitions:
# gpart create -s GPT ad4
ad4 created
# gpart add -b 34 -s 128 -t freebsd-boot ad4
ad4p1 added
# gpart add -s 2g -t freebsd-swap -l swap4 ad4
ad4p2 added
# gpart add -t freebsd-zfs -l system4 ad4
ad4p3 added
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ad4
bootcode written to ad4
No scratch partition on this one, there’s no room. Now the two disks should match
# gpart show
=> 34 976773101 ad8 GPT (466G)
34 128 1 freebsd-boot (64K)
162 4194304 2 freebsd-swap (2.0G)
4194466 484202669 3 freebsd-zfs (231G)
488397135 488376000 4 freebsd-zfs (233G)
=> 34 488397101 ad4 GPT (233G)
34 128 1 freebsd-boot (64K)
162 4194304 2 freebsd-swap (2.0G)
4194466 484202669 3 freebsd-zfs (231G)
apart from the scratch partition, of course.
Add the mirrored swap
# gmirror insert -h -p 1 swap /dev/gpt/swap4
And when rebuilding is finished, you should see
# gmirror status
Name Status Components
mirror/swap COMPLETE gpt/swap8
gpt/swap4
Now add the second disk’s zfs partition
# zpool attach system /dev/gpt/system8 /dev/gpt/system4
If you boot from pool 'system', you may need to update
boot code on newly attached disk '/dev/gpt/system4'.
Assuming you use GPT partitioning and 'da0' is your new boot disk
you may use the following command:
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
We already did this part, so no need to do anything. Wait for it to finish. Here it is partway through
# zpool status
pool: system
state: ONLINE
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
scrub: resilver in progress for 0h0m, 39.20% done, 0h0m to go
config:
NAME STATE READ WRITE CKSUM
system ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/system8 ONLINE 0 0 0
gpt/system4 ONLINE 0 0 0 718M resilvered
errors: No known data errors
and now done
# zpool status
pool: system
state: ONLINE
scrub: resilver completed after 0h2m with 0 errors on Fri Mar 18 12:13:19 2011
config:
NAME STATE READ WRITE CKSUM
system ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/system8 ONLINE 0 0 0
gpt/system4 ONLINE 0 0 0 1.79G resilvered
errors: No known data errors
And we’re done. Reboot one last time to check everything worked.
One final task not relevant to the mirroring is to mount the scratch disk area.
Create a mountpoint
# mkdir /scratch
And a pool
# zpool create -O mountpoint=/scratch -O atime=off -O setuid=off scratch /dev/gpt/scratch8
This filesystem has no redundancy, as previously mentioned. (edit: I am told that the mkdir and mountpoint are both redundant – zfs will create the directory as needed, and uses the pool name as the mount point by default)
In the next installment I will fail and replace one of the disks.
Edit:
daily_status_zfs_enable="YES"
daily_status_gmirror_enable="YES"
should be added to /etc/periodic.conf so checks are added to the daily mails.
Ben Laurie - Capsicum Wins Cambridge Ring Award
Of course, I know that capabilities are really important, and that the work we (I say we as if I did much – the hard graft is down to Robert Watson and Jon Anderson) have done on adding capabilities to FreeBSD is particularly awesome. But I continue to be amazed at the community reaction to it.
The latest accolade is the rather unwieldy Cambridge Ring Hall of Fame Award for Best Publication of the Year.
You know, I’m beginning to think we might actually make some serious progress with capabilities in the next year or two. Watch this space, there’s a lot going on in this field!
Ben Laurie - Chicken and Lentils
chicken thighs/drumsticks/whatever – skin on
green lentils (I doubt it matters much, but this is what I used)
cardamom pods
cloves
coriander
cumin
dried red chillies
diced ginger
sliced onion
chicken stock
tinned tomatoes
Grind the spices (I use a coffee grinder, but pestle and mortar is fine). Fry with the ginger in whatever oil takes your fancy (or even ghee) for a minute or so, then add the chicken pieces. Fry pretty vigorously until nicely browned, but try not to burn the spices. I try to have enough spice so the chicken all gets nicely coated and there’s some left over for the next stage…
Once the chicken is browned (but not cooked through), set aside, leaving whatever oil and spices aren’t sticking to them in the pan. Add the onions and fry until clear, then add the lentils and some water.
Some, but not all, lentils need to be cooked carefully (they contain an enzyme that ain’t so good for you) so make sure you incorporate the cooking instructions into this recipe. The green lentils I used don’t need soaking (in fact, in my experience you can generally substitute more boiling for soaking anyway), but they do need boiling hard for ten minutes, so … do that now.
Once any hard cooking needed by the lentils is over, return the chicken to the pan, add the tinned tomatoes and chicken stock – smash the tomatoes up, bring to the boil, then simmer until the lentils are done (varies according to type). Note that lentils can soak up a lot of water, so stir occasionally and add more if needed. Season to taste and serve with rice and whatever.
I expect a raita would be nice with this.
I don’t usually do quantities, but since I was asked nicely, here’s some guidance: for eight chicken thighs (enough for four people, if they’re not too greedy) I used around 200g of lentils, one tin of tomatoes and probably around a third of a cup (or more) of spices, after they’d been ground. Mostly cumin and coriander. I know it sounds like a lot, but you need a lot – and its hard to overdo them. Stock should be enough to cook the lentils, bearing in mind the liquid from the tomatoes – the aim is for a thick lentil sauce, not a soup.
Ben Laurie - Who the Hell are 2o7?
My friend Adriana pointed me to this cool track-blocking extension for Chrome.
Back in the day, I used to do this kind of blocking “by hand” – i.e. by manually deciding which cookies to block and which to allow. This is far from an exact science – it’s fairly easy to block some sites into uselessness – so I’m pleased to see an automated alternative.
In any case, it all came to an end when Chrome decided (without any explanation I ever saw) to drop the ability to control cookies, so extensions are probably the only way now.
Anyway, it reminded me of something I kept meaning to look into but never really got very far, which is 2o7.net. This domain crops up all the time if you start monitoring cookies, and clearly is some massive tracking operation. But I’ve never heard of it, and nor has anyone else I know.
So … who the hell are 2o7? (And yes, I can do whois, which leads me to Omniture. Not much the wiser. Except they now seem to be owned by Adobe – mmm – looking forward to mixing all that tracking data with Adobe’s careful attention to security).
Note, btw, the cool track-blocking extension doesn’t appear to have heard of 2o7 either. From my experience you can just block all their cookies without harm.
Ben Laurie - Two Cool Caja Things
Firstly, Paypal are using Caja to protect their customers from errors or evilness in gadgets. There are also some performance hints here.
Secondly, my esteemed colleague, Jasvir Nagra, has put together a really nice playground for Caja. Have a go, it’s pretty.
That is all.
Ben Laurie - Salmon with Sticky Ginger Sauce
Salmon fillets (with skin)
Sugar
Vinegar
Ginger
Spring onions
Finely chop ginger and spring onions. Mix a lot of sugar with a roughly equal quantity of vinegar. Add the ginger and reduce (I always overdo this which means the sauce solidifies when it cools – try not to copy me, it’s a pain to have to keep warming it). Add the chopped spring onions at the end. You could also add chilli, but I didn’t. I expect cubed cucumber might be nice, too.
While it is reducing, fry the salmon in olive oil, quite hot so the skin browns (do the skin side first). Serve with sauce generously drizzled on it.
We had it with rice and leeks with cream (roll-cut leeks, fry gently in butter/salt/pepper, add double cream at the end).
Ben Laurie - Is Openleaks The Next Haystack?
As everyone who’s even half-awake knows by now, a bunch of people who used to work on Wikileaks have got together to work on Openleaks. From what I hear, Openleaks is going to be so much better than Wikileaks – it will have no editorial role, it will strongly protect people who submit leaks, it’s not about the people who run it, it’ll be distributed and encrypted.
But where’s the design to back up this rhetoric? Where are the security reviews from well-known authorities? They seem to be missing. Instead we have excited articles in mainstream media about how wonderful it is going to be, and how many hours the main man has spent on it.
This sounds very familiar indeed. And we all know what happened last time round.
Of course, Openleaks may be fine, but I strongly suggest that those who are working on it publish their plan and subject it to scrutiny before they put contributors at risk.
As always, I offer my services in this regard. I am sure I am not alone.
Ben Laurie - ƃuıʇsılʞɔɐlq uʍop-ǝpısd∩
A well-known problem with anonymity is that it allows trolls to ply their unwelcome trade. So, pretty much every decent cryptographic anonymity scheme proposed has some mechanism for blacklisting. Basically these work by some kind of zero-knowledge proof that you aren’t on the blacklist – and once you’ve done that you can proceed.
However, this scheme suffers from the usual problem with trolls: as soon as they’re blacklisted, they create a new account and carry on. Solving this problem ultimately leads to a need for strong identification for everyone so you can block the underlying identity. Obviously this isn’t going to happen any time soon, and ideally never, so blacklists appear to be fundamentally and fatally flawed, except perhaps in closed user groups (where you can, presumably, find a way to do strong-enough identification, at least sometimes) – for example, members of a club, or employees of a company.
So lately I’ve been thinking about using “blacklists” for reputation. That is, rather than complain about someone’s behaviour and get them blacklisted, instead when you see someone do something you like, add them to a “good behaviour blacklist”. Membership of the “blacklist” then proves the (anonymous) user has a good reputation, which could then be used, for example, to allow them to moderate posts, or could be shown to other users of the system (e.g. “the poster has a +1 reputation”), or all sorts of other things, depending on what the system in question does.
The advantage of doing it this way is that misbehaviour can then be used to remove reputation, and the traditional fallback of trolls no longer works: a new account is just as useless as the one they already have.
There is one snag that I can see, though, which is at least some anonymity systems with blacklisting (e.g. Nymble, which I’ve somehow only recently become aware of) have the side-effect of making every login by a blacklisted person linkable. This is not good, of course. I wonder if there are systems immune to this problem?
Given that Jan Camenisch et al have a presentation on upside-down blacklisting (predating my thinking by quite a long way – one day I’ll get there first!), I assume there are – however, according to Henry, Henry and Goldberg, Camenisch’s scheme is not very efficient compared to Nymble or Nymbler.
Ben Laurie - Grown-up Arduino Programming
As I mentioned in a previous post, I am not a big a fan of the Arduino IDE. Since writing that, I’ve discovered I like it even less, because it does some ad-hoc mangling of what you write to turn it from a nearly-C language into genuine C. As a result, it is possible to write some C++ and get away with it, but whether C++ stuff works or not seems entirely random.
It may sound nuts to want to write C++ for a processor so small. But read on – it turns out you can do some nice things at essentially zero cost. But first you need a proper C++ toolchain. One way to get hold of it would be to install the Arduino IDE, in fact, since it uses it under the hood. But I did it from scratch on my FreeBSD system. This turns out to be mostly easy, but there were a couple of wrinkles worth writing down for the greater good.
Firstly, on FreeBSD the compiler is available as a port, so I just installed it with my favourite ports tool
portmaster devel/avr-gcc
(note that there are several variants based on different versions of the compiler available – this is the default variant which, at the time of writing, is based on gcc 4.2.4).
Sadly, although the libc part of the toolchain is available as a port, too, at the time of writing both versions (devel/avr-libc and devel/avr-libc-devel) are broken because they depend on defunct source code. So, I had to build this one by hand, starting with avr-libc-1.6.8.tar.bz2 from http://download.savannah.gnu.org/releases/avr-libc/. This is not too hard, just a slightly customised configuration followed by the usual make commands:
./configure --prefix=/usr/local/avr --host=avr
make
make install
Setting the prefix to /usr/local/avr is advisable as some things get installed immediately below the prefix and so could conflict with native compilers and libraries. However, it does cause some things to end up in /usr/local/avr/avr. Oh, well.
Next up, a test program is a good idea. avr-glibc comes with demo code, which can be found in /usr/local/avr/share/doc/avr-libc-1.6.8/examples/, but none of it is particularly well suited to an Arduino. So, I stole the Makefile from the demo sample and used this code instead of demo.c
#include <avr/interrupt.h> #include <avr/io.h> #define FLASH PB5 // "Pin 13" (Arduino pin) - ATmega168 pin 19 #define CONTROL_PORT PORTB #define CONTROL_DDR DDRB static void ioinit(void) { CONTROL_DDR = _BV(FLASH); } int main(void) { long n; ioinit(); for( ; ; ) { CONTROL_PORT &= ~_BV(FLASH); for(n=0; n < 300000; ++n) ; CONTROL_PORT |= _BV(FLASH); for(n=0; n < 300000; ++n) ; } }
and modified the Makefile to remove optimisation (essential, otherwise the delay loops get optimised away), select the right CPU (atmega168) and to modify these two lines
DEFS = -I /usr/local/avr/avr/include
LIBS = -B /usr/local/avr/avr/lib
-B is a new flag to me: it specifies where binaries and the crt0 files are found. The last ingredient is a way to upload to the Arduino. The utility avrdude can do this for you
avrdude -p m168 -P /dev/cuaU0 -c arduino -b 19200 -U flash:w:yourstuff.hex
Of course, delay loops are horrible, so my second attempt does this properly, using a timer interrupt. And this is where the C++ comes in: the “standard” way to set up the CPU is to write code like
#define FLASH PB5 // "Pin 13" (Arduino pin) - ATmega168 pin 19 #define CONTROL_PORT PORTB #define CONTROL_DDR DDRB static void ioinit(void) { // PWM, 10-bit, phase-correct TCCR1A = _BV(WGM10) | _BV(WGM11); // Pre-scaler set to 1024 TCCR1B = _BV(CS12) | _BV(CS10); // Set flash pin to output CONTROL_DDR = _BV(FLASH); // Enable timer 1 overflow interrupt TIMSK1 = _BV(TOIE1); sei(); }
which is pretty revolting and involves a lot of manual-reading to understand. So, as is my habit when dealing with hardware, I tried wrapping it up in nice C++ classes to see what the run-time cost is. I won’t show the C++ classes here as they’re quite verbose and are a work in progress, but the net effect on the setup code is that it now looks like this
#define FLASH PortB5 // "Pin 13" (Arduino pin) - ATmega168 pin 19 static void ioinit(void) { Control c; c.tc1.OC1ADisconnected(); c.tc1.OC1BDisconnected(); c.tc1.PWMPhaseCorrect10Bit(); c.tc1.Prescaler1024(); c.tc1.OverflowInterruptEnable(); FLASH::Out(&c); c.Set(); sei(); }
which I hope you’ll agree is much more readable. The amazing thing is that, despite the increased verbosity, there’s no cost at all: this produces almost exactly the same assembler as the original code (it is in a slightly different order, though even that could be fixed if needed). The wonders of optimisation.
Note, by the way, the use of a PWM mode is simply because the demo code I borrowed from actually did use PWM – but pin 19 (where the LED is on a standard Ardunio/Freeduino) isn’t a PWM pin, so my code just uses the timer interrupt to time when to turn the LED on or off. The PWM is not really needed but the timer has to be in some mode, so I haven’t yet bothered to figure out a more appropriate one.
When I’ve got more stuff encapsulated in C++ I’ll start sharing the code.
Ben Laurie - P2P DNS
Apparently the Pirate Bay are tired of ICANN and want to start their own peer-to-peer DNS. I think their chances of wide adoption are pretty near zero, but it’s an interesting area that’s needed serious exploration for quite some time. Obviously if you’re doing P2P DNS you need to use DNSSEC or attacks become trivial. Since they also want to have multiple registrars who can nominate themselves, it seems a proposal I made to the DNS working group many years ago could be handy. Basically, the idea is to distribute keys for “islands of security” by having bilateral agreements between them, so each island signs some set of other island’s keys, if they want to. The user then bootstraps their set of keys by starting from an island or islands they trust.
When ferreting this out I found that the -01 version is already on my server, and I just uploaded -02 – not sure what the differences are, when I have some time I’ll make a diff. Probably.
Ben Laurie - Fun With Freeduino
As I may have mentioned before, I have a place in Wales. That place is pretty primitive, we have a solid fuel heating system, otherwise known as a Rayburn, and until recently the extent of the control systems in the whole house was a thermostat strapped to the hot water tank. When the temperature hits the set point, a pump switches on, which pumps the hot water round the radiators instead.
I did consider adding a second thermostat for a while: if you let the Rayburn get overexcited it can boil the water in the convection system before the hot water tank is up to temperature. This is pretty exciting to be in amongst, the whole place vibrates and clanks. So, I mused about putting in a second thermostat that monitored the temperature of the pipes and switched on the pump if they got too hot. But then I learnt to control the Rayburn better and it has become a non-issue.
But anyway, the prospect of a house with basically no control systems in it has me thinking about building my own: something I’ve long wanted to play with. So, I started looking at the Arduino. I have read that Arduinos are not actually completely open (I believe their PCB design is not, even though everything else is), but in any case, Freeduinos seem to be cheaper, and completely compatible, so I got one from an outfit called nueletronics.
It turns out that there’s a package based on Processing which lets you very easily write and upload C/C++ code for the board, available from the Arduino site, so step one is obviously to write some code to do stuff with the LEDs on the Arduino board. I won’t bore you with that, since the source comes with the Arduino software.
Of course, that’s only fun for a short while, so I had to move on to something relevant to Wales. My first thought was to measure temperature, and perhaps do something about avoiding freezing when we’re not there. In a past life I played with 1-wire devices from Dallas[1] so the natural choice for the thermometer was a Dallas 18B20, also available from nueletronics, as it happens. It turns out that you need a 4.7 kOhm pull-up resistor for the parasitic power, so I bought some of those from eBay (amusingly buying 100 costs the same as buying 10, it seems, so of course I bought 100 – the cost was something like 1p each). Then I needed something to connect it to the Arduino, so I also bought a prototyping shield (shields are what they call daughter boards for the Arduino) and a breadboard, also from eBay.
Then I realised I’d need to communicate the temperature to some more serious machine, for recording/monitoring purposes. So I also bought an Ethernet shield, again from nuelectronics (note that this is not a “standard” Arduino ethernet shield). While I was browsing I realised I could be both lazy and a little tidier by buying yet more stuff from nuelectronics, namely a real-time datalog and I/O shield and a DS18B20 module. Ultimately I’ll probably connect the thermometer directly, but for now the I/O shield provides wiring (the rest of the board is unused in this little project) and the DS18B20 module saves me having a breadboard floating around – the software is exactly the same as it would be if I’d wired it direct.
So, now I’ve got all the hardware, my plan was to read the 1-wire temperature over Ethernet. Simples. Turns out that this was pretty easy once you have all the info (which is not so easy to find!) and cobble together the various bits of software. But since it was actually pretty painful to figure out all the bits, let me explain a step at a time.
- Connect the Freeduino to your PC/Mac/whatever with a USB cable.
- Fire up the Arduino software and configure it for the right USB port (sorry, no great advice on how to do this in general – in my case I had to install drivers on XP to do it).
- Convince yourself that you’ve got this working by running a sketch (this is what the Arduino software calls a program) that blinks the LED.
- Once you’ve done that, then disconnect the USB (which disconnects the power) and stack the I/O board and the Ethernet board on top of the Freeduino, in that order (the Ethernet has to go on top because the connector is too tall to fit between two boards).
- Connect the DS18B20 module to P7 on the I/O board (the centre connector).
- Plug the USB back in.
- Unzip the Ethernet shield drivers into the
librariesdirectory of the Arduino software. They should end up in a directory calledetherShield. - Load up this sketch[2].
- Set an appropriate IP address[3] in the
myiparray at the top of the code. Also set the same address inbaseurl. - Build and install the sketch.
- Point your web browser at the IP address you configured. You should see the current temperature and a button to refresh.
- If you want to monitor temperature over time (and you are on Unix), run a script like this:
while true do wget -q -O - 'http://193.133.15.111/?cmd=2' echo -n ' ' date +%s sleep 60 done
And that’s all folks. My first Arduino thermometer
What next? Well, firstly, the Arduino software environment is actually pretty annoying if you’re a professional coder like me, so I plan to figure out how to do this “properly” with the avr-gcc compiler suite (the Arduino software uses this under the hood, so it can’t be that hard). Secondly it seems to be quite hard to find out what pins are actually used by shields and what they connect to, so I’m probably going to start trying to gather that info in a useful format (does it already exist somewhere?), at least for components I have. I’m also planning to actually control some heating using the Arduino – for that purpose I’ll almost certainly use this relay module with the I/O board, at least for the prototype.
I’ll blog about these when I get round to them.
[1] 1-Wire is a really cute technology that allows you to control and power multiple devices over a single wire (+ ground).
[2] This is the demo code from nuelectronics, tidied up a bit and with some extra functionality added.
[3] If you don’t know what “appropriate” means, you should probably ask someone. It’s hard to give general advice.
Ben Laurie - Why Identity Is Still Just Login
It seems everyone now agrees that Internet identity is about a collection of assertions relating to a person (or thing, if you want to go there). Some of these assertions are assertions one makes about oneself, for example “I like brussels sprouts”, and assertions others make about you, for instance “Ben is a UK citizen, signed the UK Government”. These assertions are essentially invariant, or slowly varying, for the most part. So what makes an identity, we agree, is some collection of these assertions.
But we also agree that people need to assert different identities: there’s Ben at work, Ben as a member of the OpenSSL team, Ben at home and so on. Each of these identities, we like to think, corresponds to a different collection of assertions.
All we need to do, we think, to map these identities onto collections of electronic assertions and we’ll have solved The Internet Identity Problem. People will no longer be required to type in their credit card number five times a day, endlessly write down their address (and correct it when it changes) and so on. The ‘net will become one lovely, seamless experience of auto-communicated factoids about me that are just right for every circumstance and I’ll never fill in a form again.
You can probably see where I’m going. The more I think about it, the more I realise that every situation is different. My “identity” is contextual, and different for each context. We know this from endless studies of human behaviour.
So, what was the point of doing what every electronic identity system wants me to do, namely aggregating various assertions about me into various identities, and then choosing the right identity to reveal? To match this to what I do in the real world, I will need a different identity for each context.
So, what was the point of even talking about identities? Why not simply talk about assertions, and find better ways for me to quickly make the assertions I want to make. Cut out the middleman and do away with the notion of identity.
In practice, of course, this is exactly what has happened. The only vestige of this electronic identity that makes any sense is the ability to log in as some particular “person”. After that all my decisions are entirely contextual, and “identity” doesn’t help me at all. And so what we see is that “identity” has simply become “login”. And will always be so.
In a sense this is exactly what my Belay research project is all about – allowing me to decide exactly what I reveal in each individual context. In Belay, the ability to log in to a particular site will become the same kind of thing as any other assertion – a fine-grained permission I can grant or not grant.
Note: I am not against bundles of assertions – for example, I think lines one and two of my address clearly belong together (though for some purposes the first half of my postcode, or just my country, should suffice) or, less facetiously, when I use my credit card I almost always need to send a bunch of other stuff along with the credit card number. What I doubt is that the notion of a bundle that corresponds to an “identity” is a useful one. This implies that UIs where you pick “an identity” are doomed to failure – some other approach is needed.
Ben Laurie - Apache vs. Oracle
As a founder of the Apache Software Foundation I have long been frustrated by the ASF’s reluctance to confront Sun and now Oracle head-on over their continued refusal to allow Apache Harmony to proceed as an open source Java implementation.
So I am very pleased to see the board finally draw a line in the sand, basically saying “honour the agreements or we block the next version of Java”. Oracle’s response is just ridiculous, including the blatant
Oracle provides TCK licenses under fair, reasonable, and non-discriminatory terms consistent with its obligations under the JSPA.
why even bother to say that in response to ASF’s charges? Do they think the ASF are suddenly going to say “oops, we see the light now, how wrong we were to expect a TCK licence under fair, reasonable and non-discriminatory terms consistent with your obligations under the JSPA, we see it all clearly now and humbly withdraw our unwarranted request”?
Well, whatever Oracle expected, the ASF’s response was short and sweet
Oracle statement regarding Java: “Now is the time for positive action (and) to move Java forward.”
The ball is in your court. Honor the agreement.
How this will play out is very uncertain, at least to me, but one thing is sure: delay and vacillation are over, at least from the ASF. Expect plenty of delay from Oracle, though.
Ben Laurie - Chicken and Cashew
When I fancy a stirfry my thoughts often turn to this dish. I first learnt to cook this from Ken Hom’s excellent book, but it doesn’t bear much resemblance to his version any more. Quick and easy and delicious cold.
Chicken breast
Cashews
Ginger
Dark soy
Spring onions
Sesame oil
Chop the chicken. I believe the Chinese like things to all be roughly the same size, so in theory you should try and chop into cashew-nut-sized pieces. However, I typically do thin slices across the breast (by the way, if you want really thin slices then leaving frozen meat not quite defrosted is a great way to achieve it – no need to complete the defrosting after, it’ll happen in the wok). Marinade the chicken slices for 30 mins at least in diced ginger, dark soy and spring onion, finely chopped. Around here we like to use a lot of ginger but it is up to you.
While its marinading, stirfry the cashews in a little oil over a very gentle heat – burnt nut is very bitter, so keep the heat low and stir continuously – until lightly browned. Sometimes I use roasted and salted cashews, in which case there is no need to fry them, but you do need to rinse the salt off.
Then a little more oil (I use groundnut, by the way) on a high heat. Once it is smoking, throw in the chicken, which should’ve absorbed most of the marinade by now. Stirfry quickly and not for too long; the secret to really tender chicken is to stop as soon as all the meat is coloured – the pieces should be small enough that they’ll be cooked through by the time you’re done. Add the cashews and a little more dark soy and bring up to heat. Then take it off the heat, add yet more finely chopped spring onion and a generous dash of sesame oil give a final stir, and serve with plain boiled rice and a vegetable of your choice. Or a salad, even.
Nom nom. I think there might be some of this calling me from the fridge right now.
Ben Laurie - Radical Copyright Thinking … at the European Commission!
I criticise policy makers a lot. So it’s really nice when they say something sensible – or even inspirational. The summary does not do this speech justice. It’s quite short, I suggest you read it.
“We must ensure that copyright serves as a building block, not a stumbling block – we need action to promote a legal digital Single Market in Europe” European Commission Vice President for the Digital Agenda Neelie Kroes said today at the prestigious Forum D’Avignon, on the subject of how digital technology represents an opportunity rather than a threat to culture. Kroes underlined the need to modernise the copyright system so that it helps rather than hinders artists within the EU’s Single Market. “My goal, in promoting cultural diversity and content adapted to the digital age, is for European creativity to be even stronger”, Kroes said. “Today our fragmented copyright system is ill-adapted to the real essence of art, which has no frontiers. Instead that system has ended up giving a more prominent role to intermediaries than to artists. It irritates the public, who often cannot access what artists want to offer and leaves a vacuum which is served by illegal content, depriving artists of their well-deserved remuneration. It may suit some vested interests to avoid a debate, or to frame the debate in moralistic terms that merely demonise millions of citizens. But that is not a sustainable approach. Time alone will not solve the problems that have emerged.
Ben Laurie - Firesheep: Session Hijacking for Morons
OK, we’ve all known forever that using any kind of credential over an unencrypted connection is a Bad Idea(tm). However, we also know that pretty much every website does an Obi-wan over session cookies, which typically travel over HTTP. “These are not the credentials you are looking for” they tell us.
Firesheep proves that comprehensively wrong. Surf your favourite login-requiring site on an open network, and *BANG*, you’re pwned. Awesome piece of work. Eric Butler, the author, says
Websites have a responsibility to protect the people who depend on their services. They’ve been ignoring this responsibility for too long, and it’s time for everyone to demand a more secure web. My hope is that Firesheep will help the users win.
Ben Laurie - Phished by Visa: The Aftermath
Well over a year ago I wrote about how stupid the Verified by Visa program is. Apparently the mainstream press have now caught up as fraudsters gear up to exploit this fantastic piece of security design. I particularly like the claim from a UK Cards Association representative that VbV reduces fraud (at around 2:30) – immediately after a victim explains that her bank refused to even investigate the possibility of fraud.
This is, of course, in line with the modern banking strategy for fraud: shift all blame to the customer.
Ben Laurie - Aims not Mechanisms
I’m a big fan of the EFF, so it comes as a bit of a surprise when I see them say things that don’t make any sense.
A while back the EFF posted a bill of privacy rights for social network users. Whilst I totally sympathise with what the EFF is trying to say here, I’m disappointed that they head the way of policymakers by ignoring inconvenient technical reality and proposing absurd policies.
In particular, I refer you to this sentence:
The right to control includes users’ right to decide whether their friends may authorize the service to disclose their personal information to third-party websites and applications.
In other words, if I post something to a “social network” (whatever that is: yes, I have an informal notion of what it means, and I’m sure you do, too, but is, say, my blog part of a “social network”? Email?) then I should be able to control whether you, a reader of the stuff I post, can do so via a “third-party application”. For starters, as stated, this is equivalent to determining whether you can read my post at all in most cases, since you do so via a browser, which is a “third-party application”. If I say “no” to my friends using “third-party applications” then I am saying “no” to my friends reading my posts at all.
Perhaps, then, they mean specific third-party applications? So I should be able to say, for example, “my friends can read this with a browser, but not with evil-rebroadcaster-app, which not only reads the posts but sends them to their completely public blog”? Well, perhaps, but how is the social network supposed to control that? This is only possible in the fantasy world of DRM and remote attestation.
Do the EFF really want DRM? Really? I assume not. So they need to find a better way to say what they want. In particular, they should talk about the outcome and not the mechanism. Talking about mechanisms is exactly why most technology policy turns out to be nonsense: mechanisms change and there are far more mechanisms available than any one of us knows about, even those of us whose job it is to know about them. Policy should not talk about the means employed to achieve an aim, it should talk about the aim.
The aim is that users should have control over where their data goes, it seems. Phrased like that, this is clearly not possible, nor even desirable. Substitute “Disney” for the “the users” and you can immediately see why. If you solve this problem, then you solve the DRM “problem”. No right thinking person wants that.
So, it seems like EFF should rethink their aims, as well as how they express them.
Ben Laurie - The Tragedy of the Uncommons
An interesting phenomenon seems to be emerging: ultra-hyped projects are turning out to be crap. I am, of course, speaking of Haystack and Diaspora (you should follow these links, I am not going to go over the ground they cover, much).
The pattern here is that some good self-promoters come up with a cool idea, hype it up to journalists, who cannot distinguish it from the other incomprehensible cool stuff we throw at them daily, who duly write about how it’ll save the world. The interesting thing is what happens next. The self-promoters now have to deliver the goods. But, for some reason, rather than enlisting the help of experts to assist them, they seem to be convinced that because they can persuade the non-experts with their hype they can therefore build this system they have been hyping. My instatheory[1] is that it’d dilute their fame if they shared the actual design and implementation. They’ve got to save the world, after all. Or we could be more charitable and follow Cialdini: it seems humans have a strong drive to be consistent with their past actions. Our heroes have said, very publicly, that they’re going to build this thing, so now they have a natural tendency to do exactly what they said[2].
But the end result, in my sample of two, is disastrous. Haystack has completely unravelled as fundamentally flawed. Diaspora seems to be deeply rooted in totally insecure design. I hope I am preaching to the choir when I say that security is not something that should be bolted on later, and that the best way to do security design is to have the design reviewed as widely as possible. In both Haystack and DIaspora’s cases that could, and should, have been a full public review. There is no excuse for this, it wastes a vast amount of enthusiasm and energy (and money) on ultimately destructive goals.
I don’t have any great ideas on how to fix this, though. Yes, reporters getting expert assistance will help. Many of the experts in the security field are quite outspoken, it isn’t hard to track them down. In Diaspora’s case, perhaps one could have expected that Kickstarter would take a more active role in guidance and mentoring. Or if they already do, get it right.
Natural selection gets you every time.
BTW, if any journalists are reading this, I am absolutely happy to take a call to explain, in English, technological issues.
[1] I love this word. Ben Hyde introduced me to it.
[2] This is known as “consistency” in the compliance trade.
Ben Laurie - Experimenting With Client Certificates
I was recently contacted about yet another attempt to use client certificates for authentication. As anyone paying attention knows, this has some attractions but is pretty much unusable in browsers because of their diabolical UIs. So, I was fascinated to learn that this particular demo completely avoids that issue by implementing TLS entirely in Javascript! This strikes me as a hugely promising approach: now we have complete freedom to experiment with UI, whilst the server side can continue to use off-the-shelf software and standard configurations.
Once UI has been found that works well, I would hope that it would migrate to be part of the browser, it seems pretty clear that doing this on the webpage is not likely to lead to a secure solution in the long run. But in the meantime, anyone can have a crack at their own UI, and all they need is Javascript (OK, for non-coders that might sound like a problem, but believe me, the learning curve is way shallower than any browser I’ve played with).
Anway, pretty much end-of-message, except for some pointers.
- Here’s a demo (confusingly called WebID, since that’s what FOAF+SSL also calls itself). Yes, certificate warnings are expected.
- A blog post about WebID.
- A slide deck.
- A blog post about the JS implementation of TLS.
- The TLS code on GitHub (I’m beginning to like GitHub, even if git still seems incomprehensible to me).
I am very interested in finding competent JS/UI people who would be interested in banging harder on this problem – I can do all the crypto stuff, but I confess UI is not my forte! Anyone out there?
Note, by the way, that the focus on browsers as the “home of authentication” is also a barrier to change – applications also need to authenticate. This is why “zero install” solutions that rely on browsers (e.g. OpenID) are likely doomed to ultimate failure – by the time you’ve built all that into an application (which is obviously not “zero install”), you might as well have just switched it to using TLS and a client certificate…
Ben Laurie - Wasting Public Money: Birth, Marriage and Death Digitisation
In 1998 a group of us started FreeBMD, a project to transcribe and make freely available the Birth, Marriage and Death records for England and Wales. The project has been wildly successful and 12 years on we have 250 million records in our database.
In the meantime the government has twice decided to spend a vast amount of taxpayers’ money duplicating our work. The first project, DoVE, was started in 2005. Three years and £8.5 million later, the project had transcribed 130 million records and was closed down. At no point in the process was FreeBMD contacted – not even to inform us that there was a tender open to do what we clearly were highly qualified to do. Nor were the transcribed records made freely available to those who had paid for them. Oh no, that wouldn’t be the thing to do at all – they were instead given to the GRO to sell.
Fast forward a few years, Big Brother is upon us. And I don’t mean the TV program. In 2009 the Identity and Passport Service decide to try again. I’ll quote it here,
The D&I project is currently in a pause status as IPS awaits the outcome of the government’s Comprehensive Spending Review (CSR). It is possible that the outcome of the CSR will impact the overall scope of the project, as well as timescales and procurement activity.
since history shows that the government are not very good at preserving records[1]. Anyway, you’ll notice that it’s been suspended again, at what cost to the taxpayer I don’t know, perhaps someone out there does. Since the new government has decided to scrap identity cards, which were the driving force for this project (note: no public access to the transcription was planned) I am quietly confident that the outcome of the CSR will be to scrap the project. Again. Of course, they will call it “stalled” or “delayed” so when they next decide to waste our money on it they can revive it.
Anyway, let me go on record now and say this: FreeBMD will complete this transcription, without cost to the taxpayer, given access to the source records. There’s just one condition: we have to be able to publish the complete transcription, free of charge, on the Internet. Of course, it’ll go a bit faster if we do get some money, so I won’t say we wouldn’t accept if it were offered!
Of course, we’ve always been prepared to do this, but why would civil servants shaft their cronies by saving money in that way?
[1] All references to DoVE[2] seem to have been conveniently obliterated by a “move” of the GRO’s website, even though some of it is still hosted on the same website!
[2] Well, at least all references on this rather nice timeline I discovered while researching this post.
Ben Laurie - Cod Chowder
Chowder isn’t exactly rocket science, but this went pretty well, so documenting it here…
I actually made this almost entirely from frozen ingredients and it was just fine. Fresh might be better.
Finely chopped leek
Smoked bacon, sliced (I used some lardons I had in the freezer)
Cubed potatoes
Chicken stock (maybe fish stock would be better, I didn’t have any) or water
Milk (about half as much as stock)
Pepper
Mace
Cod
King prawns
Sweetcorn
Cream
Fry the leeks and bacon in a little butter/olive oil (I used both) until pretty soft – I didn’t crisp the bacon for a change. I think it is better for chowder not to. Add cubed potatoes and fry for a bit longer, then add chicken stock (or water or fish stock) and bring to the boil. Simmer until the potatoes have softened, then zap half the mixture with a blender (I just did this in situ). Season (I didn’t need salt, there was enough in the bacon). Add milk, fish, prawns and bring back up to a simmer, cook for a few minutes, making sure the fish falls apart. Add cooked sweetcorn and bring back up to temperature. Finally, add some cream.
Quantities should be chosen so that the final result is good and thick.
Serve with warm, crusty bread and butter. Works as a whole meal.
Ben Laurie - It’s All About Blame
I do not represent my employer in this post.
“The only way to manage this is true transparency and no anonymity. In a world of asynchronous threats, it is too dangerous for there not to be some way to identify you. We need a [verified] name service for people. Governments will demand it.”
I don’t care whether he actually said it, but it neatly illustrates my point. The trouble with allowing policy makers, CEOs and journalists define technical solutions is that their ability to do so is constrained by their limited understanding of the available technologies. At Google (who I emphatically do not represent in this post), we have this idea that engineers should design the systems they work on. I approve of this idea, so, speaking as a practising engineer in the field of blame (also known as security), I contend that what Eric really should have allegedly said was that the only way to manage this is true ability to blame. When something goes wrong, we should be able to track down the culprit. Governments will demand it.
Imagine if, the next time you got on a plane, instead of showing your passport, you instead handed over an envelope with a fancy seal on it, containing your ID, with windows showing just enough to get you on the plane (e.g. your ticket number and photo). The envelope could be opened on the order of a competent court, should it turn out you did something naughty whilst travelling, but otherwise you would remain unidentified. Would this not achieve the true aim that Eric allegedly thinks should be solved by universal identification? And is it not, when spread to everything, a better answer?
Of course, in the physical world this is actually quite hard to pull off, tamper-proof and -evident seals being what they are (i.e. crap), but in the electronic world we can actually do it. We have the crypto.
Just sayin’.
Ben Laurie - FreeBSD Capsicum
I mentioned FreeBSD Capsicum in my roundup of capability OSes earlier this year without mentioning that I am involved in the project. Since then we’ve managed to port and sandbox Chromium, using less code than any other Chromium sandbox (100 lines), as well as a number of other applications. Also impressive, I think, is the fact that Robert Watson managed to write this sandbox in just two days, having never seen the Chromium codebase before – this is as much a testament to Robert’s coding skills and the clean Chromium codebase as it is to Capsicum, but nevertheless worth a mention.
Anyway, at USENIX Security this week, we won Best Student Paper. A PC member described the paper to me as “excellent” and “very important”. Robert has also blogged about it rather more eloquently than I can manage at this time in the morning.
You can read the paper, too, if you want.
Even more exciting, FreeBSD 9 will include the Capsicum capability framework, allowing the peaceful coexistence of capability and POSIX programs. Although this has been attempted before, as far as I am aware all previous versions have put a POSIX emulation layer on top of a capability system, rather than grafting capabilities onto POSIX. Since Capsicum is highly efficient and FreeBSD is a perfectly sound and portable system (and my server OS of choice), this opens up the possibility of a gradual migration to capabilities, something that has been problem up to now.
Robert and I (and a host of others) are continuing our research into practical capability systems, Robert at Cambridge and me at Google. Work is also in progress to port Capsicum to Linux.
Ben Laurie - Alternatives to Adium?
When I’m at home, I tend to use Pidgin for IM. When travelling, I generally use Adium. But Adium is driving me nuts: basically it is fantastically unstable. Empirically this appears to be related to the number of contacts, of which I have many (i.e. reducing the number makes it less crashy).
So … what can I use on MacOS that’s less crap than Adium but still supports OTR?
Ben Laurie - Cabbage and Peas
I have a vague recollection of being served this somewhere, but I can’t remember where.
Smoked bacon
Cabbage (we used sweetheart, but I don’t think it is critical, savoy would probably be even nicer)
Frozen peas
Double cream
Slice the bacon thinly, fry in a little oil until crispy (at least, that’s what I’d do, my sous-chef decided to stop sooner than that and it was fine), chop cabbage into strips, add to the bacon+fat and braise (I found I didn’t need a lid at all, but you may – and even may need to add a little water, depending on the cabbage). When the cabbage is nearly done, add the frozen peas. As soon as they defrost, a generous gloop of double cream. Add salt at some point if the bacon isn’t too salty and pepper in any case.
We ate this with roast pork belly and roast potatoes. Yummy.