Hi Jens, Agreed - however our use case wouldn't work well with solution you propose. Our documents are signed before they are inserted into CouchDB http://goo.gl/vlJwO (and actually before certain metadata fields are attached to the object). That's one area where I think your proposal is lacking is that there's not really a method to exclude fields from the signature except via underscore fields. The key thing to note is we had a document model before object signing requirement; so we had to design a signature solution that was additive in order to not change object model field names for risk of blowing backwards compatibility. If there was way with your solution, similar to the security object, store an model to XOR against to compute/validate the signature that might be fine.
On Jul 3, 2012, at 6:07 PM, Jens Alfke wrote: On Jul 3, 2012, at 10:01 AM, Jim Klo wrote: Yes, and as a matter of fact, i just got digital signature validation using OpenPGP within a map function working a few minutes ago! Here's a link to the relevant code: https://github.com/jimklo/TheCollector/blob/master/dataservices/thecollector-resources/views/lib/sig_utils.js As far as I can tell, this code uses a data schema where the signed contents are wrapped in some kind of OpenPGP encoding: var msg_list = openpgp.read_message(doc.digital_signature.signature); for (var i=0; i<msg_list.length; i++) { isValid |= msg_list[i].verifySignature(); } It looks like msg_list is the actual document payload, which has to be decoded using openpgp.read_message. Correct - and yes agreed not exactly the most efficient. Possibly using a detached signature would be better, however because we also identified that a canonical JSON serialization has not been widely defined or accepted we went for a translation of selected signed fields to bencoding then using OpenPGP, clearsign a SHA256 hash of the bencoded JSON. This is IMHO not a very good solution because it hides the document contents away — for example, all the map functions and any app logic that uses documents will have to know to call read_message, which will also make them slower. Presumably the performance hit is only a once per view hit, which I can live with in our UC. I'm not sure I'm following though - we don't hide the document contents at all, as we use clearsign, unless you were assuming we were encrypting too. I'd agree that I don't necessarily like that each map must apply the check; however for our UC, that's acceptable, since not all documents are signed. Additionally, moving this code from a map function into a validate document update function would solve the need of having to validate within each map function; potentially marking each document with a _isvalidsignature field upon insert/update. The schema I implemented (see my previous message) doesn't alter the basic document format. The signature is in a nested object but applies to the entire document contents (minus the signature itself of course). There's no need to change any code that reads documents; the only time you have to know about the signature scheme is while verifying the signature. It's even possible to have multiple signatures on a document. Essentially we've both aligned to more or less the same solution, and identified similar challenges. The one issue both of us face is the encoding of floating point values. Our rule is to convert FPV to a base 10 string representation, before bencoding. Otherwise things like ratings or other numerically scaled values get lost in the serialization process and non-unique hashes become pointless to sign. If you haven't been following IETF's JOSE, you should take a look at it http://datatracker.ietf.org/doc/draft-ietf-jose-json-web-signature/?include_text=1 It's not very CouchDB friendly, however I wonder if there would be a way to make couch use it; Say you can insert and update docs using a JOSE payload instead of a JSON payload, CouchDB could deserialize the b64 encoding back into JSON for users who don't care to validate signatures, but then optionally could GET the documents back as a list of JOSE payloads.. The nice thing about their solution is there's no need for a canonical representation, the bad thing is there's no way to deal with 'unsigned fields'. I'm certainly open to some collaboration here, as I'm not too happy with bencoding and FWIW canonical JSON is very difficult to make portable (ordered maps aren't supported across many languages) I've been considering replacing bencoding with Tagged Netstrings http://tnetstrings.org/ which provides a good translation that is more portable and include floating point, and boolean values. —Jens Jim Klo Senior Software Engineer Center for Software Engineering SRI International
