On 03/06/2017 12:43 AM, Jeff King wrote:
Overall the basics of the conversion seem sound to me. The "nohash"
things seems more complicated than I think it ought to be, which
probably just means I'm missing something. I left a few related
comments on the google doc, so I won't repeat them here.
I think "nohash" can be explained in 2 points:
1. When creating signed objects, "nohash" is almost never written. Just
create the object as usual and add "hash" lines for every other hash
function that you want the signature to cover.
2. When converting from function A to function B, add "nohash B" if
there were no "hash B" lines in the original object.
The "nohash" thing was in the hope of requiring only one signature to
sign all the hashes (in all the functions) that the user wants, while
preserving round-tripping ability.
Maybe some examples would help to address the apparent complexity. These
examples are the same as those in the document. I'll also show future
compatibility with a hypothetical NEW hash function, and extend the rule
about signing/verification to 'sign in the earliest supported hash
function in ({object's hash function} + {functions in "hash" lines} -
{function in "nohash" line})'.
Example 1 (existing signed commit)
<sha-1 object stuff> <sha256 object stuff> <NEW object stuff>
nohash sha256 nohash new
hash sha1 ... hash sha1 ...
This object was probably created in a SHA-1 repository with no knowledge
that we were going to transition to SHA256 (but there is nothing
preventing us from creating the middle or right object and then
translating it to the other functions).
Example 2 (recommended way to sign a commit in a SHA256 repo)
<sha-1 object stuff> <sha256 object stuff> <NEW object stuff>
hash sha256 ... hash sha1 ... nohash new
hash sha1 ...
hash sha256 ...
This is the recommended way to create a SHA256 object in a SHA256 repo.
The rule about signing/verification (as stated above) is to sign in
SHA-1, so when signing or verifying, we convert the object to SHA-1 and
use that as the payload. Note that the signature covers both the SHA-1
and SHA256 hashes, and that existing Git implementations can verify the
signature.
Example 3 (a signer that does not care about SHA-1 anymore)
<sha-1 object stuff> <sha256 object stuff> <NEW object stuff>
nohash sha1 nohash new
hash sha256 ... hash sha256 ...
If we were to create a SHA256 object without any mentions of SHA-1, the
rule about signing/verification (as stated above) states that the
signature payload is the SHA256 object. This means that existing Git
implementations cannot verify the signature, but we can still round-trip
to SHA-1 and back without losing any information (as far as I can tell).