git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: SHA1 collisions found

From
Jeff King <peff@peff.net>
Date
Feb 24, 2017, 23:39 UTC
Message-ID
<20170224233929.p2yckbc6ksyox5nu@sigill.intra.peff.net>
In-Reply-To
<xmqq60jz5wbm.fsf@gitster.mtv.corp.google.com>
On Fri, Feb 24, 2017 at 09:32:13AM -0800, Junio C Hamano wrote:
Show 22 quoted lines
> >  * Therefore the transition needs to be done by giving every object
> >    two names (old and new hash function).  Objects may refer to each
> >    other by either name, but must pick one.  The usual shape of
> 
> I do not think it is necessrily so.  Existing code may not be able
> to read anything new, but you can make the new code understand
> object names in both formats, and for a smooth transition, I think
> the new code needs to.
> 
> For example, a new commit that records a merge of an old and a new
> commit whose resulting tree happens to be the same as the tree of
> the old commit may begin like so:
> 
>     tree 21b97d4c4f968d1335f16292f954dfdbb91353f0
>     parent 20769079d22a9f8010232bdf6131918c33a1bf6910232bdf6131918c33a1bf69
>     parent 22af6fef9b6538c9e87e147a920be9509acf1ddd
> 
> naming the only object whose name was done with new hash with the
> new longer hash, while recording the names of the other existing
> objects with SHA-1.  We would need to extend the object format for
> tag (which would be trivial as the object reference is textual and
> similar to a commit) and tree (much harder), of course.

One thing I worry about in a mixed-hash setting is how often the two will be mixed. That will lead to interoperability complications, but I also think it creates security hazards (if I can convince you somehow to refer to my evil colliding file by its sha1, for example, then I can subvert the strength of the new hash).

So I'd much rather see strong rules like:
  1. Once a repo has flag-day switched over to the new hash format[1],
     new references are _always_ done with the new hash. Even ones that
     point to pre-flag-day objects!
     So you get a "commit-v2" object instead of a "commit", and it has a
     distinct hash identity from its "commit" counterpart. You can point
     to a classic "commit", but you do so by its new-hash.
     The flag-day switch would probably be a repo config flag based on
     repositoryformatversion (so old versions would just punt if they
     see it). Let's call this flag "newhash" for lack of a better term.
  2. Repos that have new-hash set will consider the new hash
     format as primary, and always use it when writing and referring to
     new objects (e.g., in refs). A (purely local) sha1->new mapping can
     be maintained for doing old-style object lookups, or for quick
     equivalence checks (this mapping might need to be bi-directional
     for some use cases; I haven't thought hard enough about it to say
     either way).
  3. For protocol interop, the rules would be something like[2]:
      a. If upload-pack is serving a newhash repo, it advertises
         so in the capabilities.
	 Recent clients know that the rest of the conversation will
	 involve the new hash format. If they're cloning, they set the
	 newhash flag in their local config.  If they're fetching, they
	 probably abort and say "please enable newhash" (because for an
	 existing repo, it probably needs to migrate refs, for example).
	 An old client would fail to send back the newhash capability,
	 and the server would abort the conversation at that point.
	 A new upload-pack serving a non-newhash repo behaves the same
	 as now (use sha1, happily interoperate with existing and new
	 clients).
      b. receive-pack is more or less the mirror image.
         A server for a newhash-flagged repo has a capability for "this
	 is a newhash repo" and advertises newhash refs. An existing
	 client might still try to push, but the server would reject it
	 unless it advertises "newhash" back to the server.
	 A newhash-enabled client on a non-newhash repo would abort more
	 gracefully ("please upgrade your local repo to newhash").
	 For a newhash-enabled server with a non-newhash repo, it would
	 probably not advertise anything (not even "I understand
	 newhash"). Because the process for converting to newhash is not
	 "just push some newhash objects", but an out-of-band flag-day
	 to convert it over.

That's just a sketch I came up with. There are probably holes. And it definitely leaves a lot of _possible_ interoperability on the table in favor of the flag-day approach. But I think the flag-day approach is a lot easier to reason about. Both in the code, and in terms of the security properties.

-Peff
[1] I was intentionally vague on "new hash format" here. Obviously there
    are various contenders like SHA-256. But I think there's also an
    open question of whether the new format should be a multi-hash
    format. That would ease further transitions. At the same time, we
    really _don't_ want people picking bespoke hashes for their
    repositories. It creates complications in the code, and it destroys
    a bunch of optimizations (like knowing when we are both talking
    about the same object based on the hash).
    So I am torn between "move to SHA-256 (or whatever)" and "move to a
    hash format that encodes the hash-type in the first byte, but refuse
    to allocate more than one hash for now".
[2] If we're having a flag-day event, this _might_ be time to consider
    some of the breaking protocol changes that have been under
    discussion.  I'm really hesitant to complicate this already-tricky
    issue by throwing in the kitchen sink. But if there's going to be a
    flag day where you need to upgrade Git to access certain repos, it
    might be nice if there's only one. I dunno.
Previous: Philip OakleyNext: Linus Torvalds
Message 60 of 136 in “SHA1 collisions found”
  1. Joey HessFeb 23, 2017
  2. Junio C HamanoFeb 23, 2017
  3. Junio C HamanoFeb 23, 2017
  4. David LangFeb 23, 2017
  5. Jakub NarębskiFeb 23, 2017
  6. Jeff KingFeb 23, 2017
  7. Joey HessFeb 23, 2017
  8. Linus TorvaldsFeb 23, 2017
  9. Joey HessFeb 23, 2017
  10. Linus TorvaldsFeb 23, 2017
  11. Jeff KingFeb 23, 2017
  12. Linus TorvaldsFeb 23, 2017
  13. Jeff KingFeb 23, 2017
  14. Linus TorvaldsFeb 23, 2017
  15. Jeff KingFeb 23, 2017
  16. Øyvind A. HolmFeb 23, 2017
  17. Joey HessFeb 23, 2017
  18. Joey HessFeb 23, 2017
  19. Morten WelinderFeb 23, 2017
  20. Geert UytterhoevenFeb 24, 2017
  21. Jeff KingFeb 23, 2017
  22. David LangFeb 23, 2017
  23. David LangFeb 23, 2017
  24. David LangFeb 23, 2017
  25. Linus TorvaldsFeb 23, 2017
  26. Linus TorvaldsFeb 23, 2017
  27. Joey HessFeb 23, 2017
  28. Linus TorvaldsFeb 23, 2017
  29. Junio C HamanoFeb 23, 2017
  30. Duy NguyenFeb 24, 2017
  31. brian m. carlsonFeb 25, 2017
  32. René ScharfeFeb 27, 2017
  33. brian m. carlsonFeb 28, 2017
  34. Ian JacksonFeb 24, 2017
  35. ankostisFeb 24, 2017
  36. Junio C HamanoFeb 24, 2017
  37. David LangFeb 24, 2017
  38. Junio C HamanoFeb 24, 2017
  39. Stefan BellerFeb 24, 2017
  40. Junio C HamanoFeb 24, 2017
  41. Junio C HamanoFeb 24, 2017
  42. ankostisFeb 24, 2017
  43. Junio C HamanoFeb 24, 2017
  44. ankostisFeb 25, 2017
  45. Jason CooperFeb 26, 2017
  46. brian m. carlsonFeb 26, 2017
  47. Linus TorvaldsFeb 26, 2017
  48. Ævar Arnfjörð BjarmasonFeb 26, 2017
  49. Jeff KingFeb 26, 2017
  50. Transition plan for git to move to a new hash functionIan Jackson, Feb 27, 2017
  51. Markus TrippelsdorfFeb 27, 2017
  52. Ian JacksonFeb 27, 2017
  53. Tony FinchFeb 27, 2017
  54. brian m. carlsonFeb 28, 2017
  55. Ian JacksonMar 2, 2017
  56. brian m. carlsonMar 4, 2017
  57. Ian JacksonMar 5, 2017
  58. brian m. carlsonMar 5, 2017
  59. Philip OakleyFeb 24, 2017
  60. Jeff KingFeb 24, 2017
  61. Linus TorvaldsFeb 25, 2017
  62. Linus TorvaldsFeb 25, 2017
  63. Jeff KingFeb 25, 2017
  64. Junio C HamanoFeb 26, 2017
  65. Junio C HamanoFeb 25, 2017
  66. Jason CooperFeb 26, 2017
  67. Jeff KingFeb 26, 2017
  68. brian m. carlsonFeb 26, 2017
  69. Brandon WilliamsMar 2, 2017
  70. Jeff KingMar 3, 2017
  71. Ian JacksonMar 3, 2017
  72. Jeff KingMar 3, 2017
  73. Linus TorvaldsMar 2, 2017
  74. Junio C HamanoMar 2, 2017
  75. Linus TorvaldsMar 2, 2017
  76. Joey HessMar 2, 2017
  77. Linus TorvaldsMar 2, 2017
  78. Mike HommeyMar 3, 2017
  79. Linus TorvaldsMar 3, 2017
  80. Jeff KingMar 3, 2017
  81. Stefan BellerMar 3, 2017
  82. David LangFeb 25, 2017
  83. Stefan BellerFeb 25, 2017
  84. Jeff KingFeb 25, 2017
  85. David LangFeb 25, 2017
  86. Jeff KingFeb 25, 2017
  87. David LangFeb 25, 2017
  88. Jacob KellerFeb 25, 2017
  89. Jacob KellerFeb 25, 2017
  90. grarpampFeb 25, 2017
  91. Ian JacksonFeb 24, 2017
  92. Ian JacksonFeb 25, 2017
  93. brian m. carlsonFeb 25, 2017
  94. Jeff KingFeb 25, 2017
  95. Mike HommeyFeb 25, 2017
  96. brian m. carlsonFeb 26, 2017
  97. Jason CooperFeb 24, 2017
  98. ankostisFeb 25, 2017
  99. Jakub NarębskiFeb 24, 2017
  100. Santiago TorresFeb 24, 2017
  101. Jakub NarębskiFeb 24, 2017
  102. Øyvind A. HolmFeb 24, 2017
  103. Jeff KingFeb 24, 2017
  104. Jakub NarębskiFeb 24, 2017
  105. Lars SchneiderFeb 25, 2017
  106. Jeff KingFeb 26, 2017
  107. Junio C HamanoFeb 26, 2017
  108. Thomas BraunFeb 26, 2017
  109. Jeff KingFeb 26, 2017
  110. Geert UytterhoevenFeb 27, 2017
  111. Jeff KingFeb 27, 2017
  112. Morten WelinderFeb 27, 2017
  113. Jeff KingFeb 23, 2017
  114. Linus TorvaldsFeb 23, 2017
  115. Jeff KingFeb 23, 2017
  116. 1/3 add collision-detecting sha1 implementationJeff King, Feb 23, 2017
  117. Stefan BellerFeb 23, 2017
  118. Jeff KingFeb 24, 2017
  119. Linus TorvaldsFeb 24, 2017
  120. Jeff KingFeb 24, 2017
  121. 2/3 sha1dc: adjust header includes for gitJeff King, Feb 23, 2017
  122. 3/3 Makefile: add USE_SHA1DC knobJeff King, Feb 23, 2017
  123. HW42Feb 24, 2017
  124. Jeff KingFeb 24, 2017
  125. Linus TorvaldsFeb 23, 2017
  126. Junio C HamanoFeb 28, 2017
  127. Junio C HamanoFeb 28, 2017
  128. Jeff KingFeb 28, 2017
  129. Dan ShumowMar 1, 2017
  130. Linus TorvaldsFeb 28, 2017
  131. Shawn PearceFeb 28, 2017
  132. Linus TorvaldsFeb 28, 2017
  133. Dan ShumowFeb 28, 2017
  134. Marc StevensFeb 28, 2017
  135. Linus TorvaldsFeb 28, 2017
  136. Jeff KingMar 1, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.