diff --git a/OBJSIG.md b/OBJSIG.md new file mode 100644 index 0000000..9d7f234 --- /dev/null +++ b/OBJSIG.md @@ -0,0 +1,107 @@ +Object Signing +============== + +Signing objects is very important. But the other issue is authenticating +that the signed object is valid. One issue that is if a key is +compromised, it can be used to sign statements that objects in the past +are valid. One way to address this situation is to sign the current +Merkle DAG that contains all the "produced" objects by that author. The +tree structure of a Merkle DAG with selective split locations allow the +tree to add additional objects w/o recalculating the entire tree. + +This also allows rolling keys more simply, as the new key starts signing +the new root, and once verification of the new key has been done, the +objects are now authenticated again. When this happens, no old keys +need be kept, and it's encouraged to remove the old keys and only keep +one, the current key, for each identity. + +As this spec is geared toward JSON encoding, but + +Objects: +Identity +- uuid: UUIDv4 +- updated: Date that this object was last updated +- name: Common name of this identity. +- email (optional) +- info +- tree_hash: Hash of the root of the object tree +- public_key: A publicKey object as specified in [JSF] +- sig: The signature of the object, a signaturecore as defined by [JSF]. + +name: Note that it is recommended to ensure that this is unique among + all the identities imported/trusted, and that work is done to present + look alike names. Giving an option to rename an Identity locally is + highly recommended to make it easier for the user. +info: General information text about this identity. +tree_hash: The multihash of the root of the object tree. +sig: Note that keyId and publicKey should not be included, as the public + key used to verify the signature MUST be the publick_key as specified + by the public_key property of the Identity object. + +ValidIdentity +- identity: UUIDv4 of the identity. +- identity_pubkey: The publicKey object, per [JSF], of the Identity object + being asserted. +- assertee: UUIDv4 of the identity asserting the validity. +- assertee_pubkey: The publicKey object, per [JSF], of the Identity object + being asserted. +- sig: Signature of the assertion, a signateurecore by [JSF]. + +It is yet to be decided if the ValidIdentity object will be used. + +The tree_hash is a [multihash]. The data refered will be a JSON [JCS] +encoded object or array. If it is an array, then each element of the +array will be a multihash refering to an object that validated by the +tree. The array MUST on contain unique multihashes, that is the array +is the equivalent of a set. The array MUST be sorted, so that a binary +search may be used over the array to find if a multihash is present or +not. If the data is an object, it will contain a key to help locate +the object, with the value being another multihash, refering to either +an object or array again. In all cases, the order of objects MUST be: +tree_hash -> [ object -> ]* array -> authenticated object. If objects +are used, the keys SHALL be based upon the last modified date of the +object. The first level MUST be year, then month, then day, then hour, +then minute, then second, then milisecond, then microsecond. If the +encoded array is longer than 256KiB, it MUST be broken up, and a new +level of objects MUST be added. + +Note that the contents of the multihash are NOT distributed w/ the +Identity object. The entire tree may be very large, and a complete +tree is NOT needed to verify a subset of the tree. It is expected that +the parts will be hosted via IPFS, or another mechanism allowing the +retrival of the data. + +Questions: +- Should ranges be supported for keys? That is, days could be `05-13`. + Advantages, easier to split nodes. Actually, better will be to use + a proper B-tree style structure, where there's a left node, and then + each key has all the values between it and the next node. +- Use Base64URL or Base32? JSF uses Base64URL though. +- Should hard limits be enforced on the array length? +- IPFS has a 1MiB block size limit, and it looks like UnixFS uses a + default block size of 256KiB, so something similar should be used. + Maybe recommend even smaller, say 8KiB? +- What should block garbage collection be? That is when a block is + no longer in the tree, how long should it be "available" for? This + partly depends upon how often the Identity object is published, that + is, only push a complete tree when an Identity hash is "published" or + fetched publicly. +- When distributing a set, use the IPFS CAR format? or something else? +- Should the merkle tree objects be a proper object themselves? That + is have their own UUID? If anything, this is more like a UUIDv5 type + thing where the object would have a UUIDv5, BUT why use that when + hashing the object directly gives the same results? Advantage, the + objects can be passed as normal, everyday objects, disadvantage is + that there will be more overhead, and cannot use IPFS directly for + serving the blocks. + +Answered: +- Should a [Rabin fingerprint] be used? Other option is to create a + n-tree. No, as this needs to be an append (in time) friendly + structure, where inserting hashes into a sorted list will be random, + causing lots of blocks to be created and unable to be cached. + +[Rabin fingerprint]: https://en.wikipedia.org/wiki/Rabin_fingerprint +[multihash]: https://multiformats.io/multihash/ +[JCS]: https://tools.ietf.org/html/rfc8785 +[JSF]: https://cyberphone.github.io/doc/security/jsf.html