| @@ -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 | |||