KIP core concept Sum
Checksum information is part of the lower-level API that KIP itself uses.
The Sum class collects checksum information, and can be updated
with new data at any time. It offers a few advanced facilities,
such as forking or cloning the hash and marking syntactical spots
of interest that should not cause security problems as a result
of invisible binary boundaries.
The need for a separate checksum is not just because of the more
powerful functionality than the MAC included in kip_up(), but
there are strong security reasons, such as the number of bits
involved, the data spanned and the longevity of the data. Try
to think of the MAC as a short-lived, message-specific protection
against accidental changes, whereas a Sum protects against
deliberate assaults on your security. And yes, it takes some
determination to mount an attack on a MAC and if you test it a
few times by hand you should see you bit changes or byte removals
trigger alerts quite consistently; but if you really wanted to
put in the effort and compute power you would probably find a
way to trick the MAC. Not so with the Sum. So when you need
to protect anything but messages in transit as KIP does for its
internal purposes, use a Sum. Really, don't be shy and just
always use a Sum.
Every internal Key has a Sum attached to it.
Not all Sum instances are also Key instances, though.
Interface.
A few useful calls for the Sum class:
-
Sum(context,keyid)creates a newSumobject, to manage the checksum with the support of the identified key. Note that everyKeyalready has aSumbuiltin by being a subclass hereof. Note that "keyid" is actually a sum-or-key-id, which is a larger set of values than just key-id. -
sumid()returns the identity for thisSum. Note that the set of all sum identities includes the set of all key identities, because everyKeyhas aSumbuilt in. This is a superset, the reverse need not be true. It is true however that everySumconnects to oneKey. -
append(bytes)appends data bytes to thisSumobject or, if this object happens to also be aKey, insert it between data that passes throughkip_up()andkip_down()calls. -
restart()theSumobject in a state that has not seen any data passing in yet. This works forKeyobjects too, and then forgets allkip_up()andkip_down()data too. -
fork()the Sum in its current state, and allow the old and new to continue in different or same directions without any further relation; do however share the history up to the moment of thisfork()call. The forkedSumwill be tied to the sameKey, but it will not be updated by itskip_up()andkip_down()operations, while that aspect of the originalSumcontinues to exist or not, as before. -
mark(typing=None)inserts a separation marker into the hash flow. This is a new idea. It allows clear separation between bits that must never been seen to connect, and follows the basic philosophy that hash input is secure if it could be parsed back. In this case, markers are inserted in the input flow, as well as an extra one at the end, in a reproducable manner that requires no escaping and no special characters. To yield the best possible result, you could add a textual hint about the marker point, such as a syntactical choice made on account of prior and/or following data. Providing no typing differs from providing any string value, even an empty string. You are welcome to use international type; we will map it in a repeatable manner to a sequence of bytes. Note that it is text, so there are no intermediate 0x00 bytes. This imposes no restrictions on the other bytes, though. -
merge(*addends)other sums' current/intermediate hash values into this one and then continue. This allows the merging of data flows. The addends are processed in the order in which they appear as arguments. -
sign()produces signature mud for the currentSumstate, where the boundKeyis used to produce the signature. Note that everySumhas an associatedKey, not just the ones that happen to play the role ofKeythrough subclassing. Operations likesum_start()andfork()always share theKeyID into the newly createdSumobject. -
verify()checks signature mud bytes against the currentSumstate, and use the bound Key to verify the signature. To make this work, the sameKeyID must have been associated with thisSumas was shared before the verifiedsign()call; that is the responsibility for the application programmer.