1Git hash function transition 2============================ 3 4Objective 5--------- 6Migrate Git from SHA-1 to a stronger hash function. 7 8Background 9---------- 10At its core, the Git version control system is a content addressable 11filesystem. It uses the SHA-1 hash function to name content. For 12example, files, directories, and revisions are referred to by hash 13values unlike in other traditional version control systems where files 14or versions are referred to via sequential numbers. The use of a hash 15function to address its content delivers a few advantages: 16 17* Integrity checking is easy. Bit flips, for example, are easily 18 detected, as the hash of corrupted content does not match its name. 19* Lookup of objects is fast. 20 21Using a cryptographically secure hash function brings additional 22advantages: 23 24* Object names can be signed and third parties can trust the hash to 25 address the signed object and all objects it references. 26* Communication using Git protocol and out of band communication 27 methods have a short reliable string that can be used to reliably 28 address stored content. 29 30Over time some flaws in SHA-1 have been discovered by security 31researchers. https://shattered.io demonstrated a practical SHA-1 hash 32collision. As a result, SHA-1 cannot be considered cryptographically 33secure any more. This impacts the communication of hash values because 34we cannot trust that a given hash value represents the known good 35version of content that the speaker intended. 36 37SHA-1 still possesses the other properties such as fast object lookup 38and safe error checking, but other hash functions are equally suitable 39that are believed to be cryptographically secure. 40 41Goals 42----- 43Where NewHash is a strong 256-bit hash function to replace SHA-1 (see 44"Selection of a New Hash", below): 45 461. The transition to NewHash can be done one local repository at a time. 47 a. Requiring no action by any other party. 48 b. A NewHash repository can communicate with SHA-1 Git servers 49 (push/fetch). 50 c. Users can use SHA-1 and NewHash identifiers for objects 51 interchangeably (see "Object names on the command line", below). 52 d. New signed objects make use of a stronger hash function than 53 SHA-1 for their security guarantees. 542. Allow a complete transition away from SHA-1. 55 a. Local metadata for SHA-1 compatibility can be removed from a 56 repository if compatibility with SHA-1 is no longer needed. 573. Maintainability throughout the process. 58 a. The object format is kept simple and consistent. 59 b. Creation of a generalized repository conversion tool. 60 61Non-Goals 62--------- 631. Add NewHash support to Git protocol. This is valuable and the 64 logical next step but it is out of scope for this initial design. 652. Transparently improving the security of existing SHA-1 signed 66 objects. 673. Intermixing objects using multiple hash functions in a single 68 repository. 694. Taking the opportunity to fix other bugs in Git's formats and 70 protocols. 715. Shallow clones and fetches into a NewHash repository. (This will 72 change when we add NewHash support to Git protocol.) 736. Skip fetching some submodules of a project into a NewHash 74 repository. (This also depends on NewHash support in Git 75 protocol.) 76 77Overview 78-------- 79We introduce a new repository format extension. Repositories with this 80extension enabled use NewHash instead of SHA-1 to name their objects. 81This affects both object names and object content --- both the names 82of objects and all references to other objects within an object are 83switched to the new hash function. 84 85NewHash repositories cannot be read by older versions of Git. 86 87Alongside the packfile, a NewHash repository stores a bidirectional 88mapping between NewHash and SHA-1 object names. The mapping is generated 89locally and can be verified using "git fsck". Object lookups use this 90mapping to allow naming objects using either their SHA-1 and NewHash names 91interchangeably. 92 93"git cat-file" and "git hash-object" gain options to display an object 94in its sha1 form and write an object given its sha1 form. This 95requires all objects referenced by that object to be present in the 96object database so that they can be named using the appropriate name 97(using the bidirectional hash mapping). 98 99Fetches from a SHA-1 based server convert the fetched objects into 100NewHash form and record the mapping in the bidirectional mapping table 101(see below for details). Pushes to a SHA-1 based server convert the 102objects being pushed into sha1 form so the server does not have to be 103aware of the hash function the client is using. 104 105Detailed Design 106--------------- 107Repository format extension 108~~~~~~~~~~~~~~~~~~~~~~~~~~~ 109A NewHash repository uses repository format version `1` (see 110Documentation/technical/repository-version.txt) with extensions 111`objectFormat` and `compatObjectFormat`: 112 113 [core] 114 repositoryFormatVersion = 1 115 [extensions] 116 objectFormat = newhash 117 compatObjectFormat = sha1 118 119Specifying a repository format extension ensures that versions of Git 120not aware of NewHash do not try to operate on these repositories, 121instead producing an error message: 122 123 $ git status 124 fatal: unknown repository extensions found: 125 objectformat 126 compatobjectformat 127 128See the "Transition plan" section below for more details on these 129repository extensions. 130 131Object names 132~~~~~~~~~~~~ 133Objects can be named by their 40 hexadecimal digit sha1-name or 64 134hexadecimal digit newhash-name, plus names derived from those (see 135gitrevisions(7)). 136 137The sha1-name of an object is the SHA-1 of the concatenation of its 138type, length, a nul byte, and the object's sha1-content. This is the 139traditional <sha1> used in Git to name objects. 140 141The newhash-name of an object is the NewHash of the concatenation of its 142type, length, a nul byte, and the object's newhash-content. 143 144Object format 145~~~~~~~~~~~~~ 146The content as a byte sequence of a tag, commit, or tree object named 147by sha1 and newhash differ because an object named by newhash-name refers to 148other objects by their newhash-names and an object named by sha1-name 149refers to other objects by their sha1-names. 150 151The newhash-content of an object is the same as its sha1-content, except 152that objects referenced by the object are named using their newhash-names 153instead of sha1-names. Because a blob object does not refer to any 154other object, its sha1-content and newhash-content are the same. 155 156The format allows round-trip conversion between newhash-content and 157sha1-content. 158 159Object storage 160~~~~~~~~~~~~~~ 161Loose objects use zlib compression and packed objects use the packed 162format described in Documentation/technical/pack-format.txt, just like 163today. The content that is compressed and stored uses newhash-content 164instead of sha1-content. 165 166Pack index 167~~~~~~~~~~ 168Pack index (.idx) files use a new v3 format that supports multiple 169hash functions. They have the following format (all integers are in 170network byte order): 171 172- A header appears at the beginning and consists of the following: 173 - The 4-byte pack index signature: '\377t0c' 174 - 4-byte version number: 3 175 - 4-byte length of the header section, including the signature and 176 version number 177 - 4-byte number of objects contained in the pack 178 - 4-byte number of object formats in this pack index: 2 179 - For each object format: 180 - 4-byte format identifier (e.g., 'sha1' for SHA-1) 181 - 4-byte length in bytes of shortened object names. This is the 182 shortest possible length needed to make names in the shortened 183 object name table unambiguous. 184 - 4-byte integer, recording where tables relating to this format 185 are stored in this index file, as an offset from the beginning. 186 - 4-byte offset to the trailer from the beginning of this file. 187 - Zero or more additional key/value pairs (4-byte key, 4-byte 188 value). Only one key is supported: 'PSRC'. See the "Loose objects 189 and unreachable objects" section for supported values and how this 190 is used. All other keys are reserved. Readers must ignore 191 unrecognized keys. 192- Zero or more NUL bytes. This can optionally be used to improve the 193 alignment of the full object name table below. 194- Tables for the first object format: 195 - A sorted table of shortened object names. These are prefixes of 196 the names of all objects in this pack file, packed together 197 without offset values to reduce the cache footprint of the binary 198 search for a specific object name. 199 200 - A table of full object names in pack order. This allows resolving 201 a reference to "the nth object in the pack file" (from a 202 reachability bitmap or from the next table of another object 203 format) to its object name. 204 205 - A table of 4-byte values mapping object name order to pack order. 206 For an object in the table of sorted shortened object names, the 207 value at the corresponding index in this table is the index in the 208 previous table for that same object. 209 210 This can be used to look up the object in reachability bitmaps or 211 to look up its name in another object format. 212 213 - A table of 4-byte CRC32 values of the packed object data, in the 214 order that the objects appear in the pack file. This is to allow 215 compressed data to be copied directly from pack to pack during 216 repacking without undetected data corruption. 217 218 - A table of 4-byte offset values. For an object in the table of 219 sorted shortened object names, the value at the corresponding 220 index in this table indicates where that object can be found in 221 the pack file. These are usually 31-bit pack file offsets, but 222 large offsets are encoded as an index into the next table with the 223 most significant bit set. 224 225 - A table of 8-byte offset entries (empty for pack files less than 226 2 GiB). Pack files are organized with heavily used objects toward 227 the front, so most object references should not need to refer to 228 this table. 229- Zero or more NUL bytes. 230- Tables for the second object format, with the same layout as above, 231 up to and not including the table of CRC32 values. 232- Zero or more NUL bytes. 233- The trailer consists of the following: 234 - A copy of the 20-byte NewHash checksum at the end of the 235 corresponding packfile. 236 237 - 20-byte NewHash checksum of all of the above. 238 239Loose object index 240~~~~~~~~~~~~~~~~~~ 241A new file $GIT_OBJECT_DIR/loose-object-idx contains information about 242all loose objects. Its format is 243 244 # loose-object-idx 245 (newhash-name SP sha1-name LF)* 246 247where the object names are in hexadecimal format. The file is not 248sorted. 249 250The loose object index is protected against concurrent writes by a 251lock file $GIT_OBJECT_DIR/loose-object-idx.lock. To add a new loose 252object: 253 2541. Write the loose object to a temporary file, like today. 2552. Open loose-object-idx.lock with O_CREAT | O_EXCL to acquire the lock. 2563. Rename the loose object into place. 2574. Open loose-object-idx with O_APPEND and write the new object 2585. Unlink loose-object-idx.lock to release the lock. 259 260To remove entries (e.g. in "git pack-refs" or "git-prune"): 261 2621. Open loose-object-idx.lock with O_CREAT | O_EXCL to acquire the 263 lock. 2642. Write the new content to loose-object-idx.lock. 2653. Unlink any loose objects being removed. 2664. Rename to replace loose-object-idx, releasing the lock. 267 268Translation table 269~~~~~~~~~~~~~~~~~ 270The index files support a bidirectional mapping between sha1-names 271and newhash-names. The lookup proceeds similarly to ordinary object 272lookups. For example, to convert a sha1-name to a newhash-name: 273 274 1. Look for the object in idx files. If a match is present in the 275 idx's sorted list of truncated sha1-names, then: 276 a. Read the corresponding entry in the sha1-name order to pack 277 name order mapping. 278 b. Read the corresponding entry in the full sha1-name table to 279 verify we found the right object. If it is, then 280 c. Read the corresponding entry in the full newhash-name table. 281 That is the object's newhash-name. 282 2. Check for a loose object. Read lines from loose-object-idx until 283 we find a match. 284 285Step (1) takes the same amount of time as an ordinary object lookup: 286O(number of packs * log(objects per pack)). Step (2) takes O(number of 287loose objects) time. To maintain good performance it will be necessary 288to keep the number of loose objects low. See the "Loose objects and 289unreachable objects" section below for more details. 290 291Since all operations that make new objects (e.g., "git commit") add 292the new objects to the corresponding index, this mapping is possible 293for all objects in the object store. 294 295Reading an object's sha1-content 296~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 297The sha1-content of an object can be read by converting all newhash-names 298its newhash-content references to sha1-names using the translation table. 299 300Fetch 301~~~~~ 302Fetching from a SHA-1 based server requires translating between SHA-1 303and NewHash based representations on the fly. 304 305SHA-1s named in the ref advertisement that are present on the client 306can be translated to NewHash and looked up as local objects using the 307translation table. 308 309Negotiation proceeds as today. Any "have"s generated locally are 310converted to SHA-1 before being sent to the server, and SHA-1s 311mentioned by the server are converted to NewHash when looking them up 312locally. 313 314After negotiation, the server sends a packfile containing the 315requested objects. We convert the packfile to NewHash format using 316the following steps: 317 3181. index-pack: inflate each object in the packfile and compute its 319 SHA-1. Objects can contain deltas in OBJ_REF_DELTA format against 320 objects the client has locally. These objects can be looked up 321 using the translation table and their sha1-content read as 322 described above to resolve the deltas. 3232. topological sort: starting at the "want"s from the negotiation 324 phase, walk through objects in the pack and emit a list of them, 325 excluding blobs, in reverse topologically sorted order, with each 326 object coming later in the list than all objects it references. 327 (This list only contains objects reachable from the "wants". If the 328 pack from the server contained additional extraneous objects, then 329 they will be discarded.) 3303. convert to newhash: open a new (newhash) packfile. Read the topologically 331 sorted list just generated. For each object, inflate its 332 sha1-content, convert to newhash-content, and write it to the newhash 333 pack. Record the new sha1<->newhash mapping entry for use in the idx. 3344. sort: reorder entries in the new pack to match the order of objects 335 in the pack the server generated and include blobs. Write a newhash idx 336 file 3375. clean up: remove the SHA-1 based pack file, index, and 338 topologically sorted list obtained from the server in steps 1 339 and 2. 340 341Step 3 requires every object referenced by the new object to be in the 342translation table. This is why the topological sort step is necessary. 343 344As an optimization, step 1 could write a file describing what non-blob 345objects each object it has inflated from the packfile references. This 346makes the topological sort in step 2 possible without inflating the 347objects in the packfile for a second time. The objects need to be 348inflated again in step 3, for a total of two inflations. 349 350Step 4 is probably necessary for good read-time performance. "git 351pack-objects" on the server optimizes the pack file for good data 352locality (see Documentation/technical/pack-heuristics.txt). 353 354Details of this process are likely to change. It will take some 355experimenting to get this to perform well. 356 357Push 358~~~~ 359Push is simpler than fetch because the objects referenced by the 360pushed objects are already in the translation table. The sha1-content 361of each object being pushed can be read as described in the "Reading 362an object's sha1-content" section to generate the pack written by git 363send-pack. 364 365Signed Commits 366~~~~~~~~~~~~~~ 367We add a new field "gpgsig-newhash" to the commit object format to allow 368signing commits without relying on SHA-1. It is similar to the 369existing "gpgsig" field. Its signed payload is the newhash-content of the 370commit object with any "gpgsig" and "gpgsig-newhash" fields removed. 371 372This means commits can be signed 3731. using SHA-1 only, as in existing signed commit objects 3742. using both SHA-1 and NewHash, by using both gpgsig-newhash and gpgsig 375 fields. 3763. using only NewHash, by only using the gpgsig-newhash field. 377 378Old versions of "git verify-commit" can verify the gpgsig signature in 379cases (1) and (2) without modifications and view case (3) as an 380ordinary unsigned commit. 381 382Signed Tags 383~~~~~~~~~~~ 384We add a new field "gpgsig-newhash" to the tag object format to allow 385signing tags without relying on SHA-1. Its signed payload is the 386newhash-content of the tag with its gpgsig-newhash field and "-----BEGIN PGP 387SIGNATURE-----" delimited in-body signature removed. 388 389This means tags can be signed 3901. using SHA-1 only, as in existing signed tag objects 3912. using both SHA-1 and NewHash, by using gpgsig-newhash and an in-body 392 signature. 3933. using only NewHash, by only using the gpgsig-newhash field. 394 395Mergetag embedding 396~~~~~~~~~~~~~~~~~~ 397The mergetag field in the sha1-content of a commit contains the 398sha1-content of a tag that was merged by that commit. 399 400The mergetag field in the newhash-content of the same commit contains the 401newhash-content of the same tag. 402 403Submodules 404~~~~~~~~~~ 405To convert recorded submodule pointers, you need to have the converted 406submodule repository in place. The translation table of the submodule 407can be used to look up the new hash. 408 409Loose objects and unreachable objects 410~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 411Fast lookups in the loose-object-idx require that the number of loose 412objects not grow too high. 413 414"git gc --auto" currently waits for there to be 6700 loose objects 415present before consolidating them into a packfile. We will need to 416measure to find a more appropriate threshold for it to use. 417 418"git gc --auto" currently waits for there to be 50 packs present 419before combining packfiles. Packing loose objects more aggressively 420may cause the number of pack files to grow too quickly. This can be 421mitigated by using a strategy similar to Martin Fick's exponential 422rolling garbage collection script: 423https://gerrit-review.googlesource.com/c/gerrit/+/35215 424 425"git gc" currently expels any unreachable objects it encounters in 426pack files to loose objects in an attempt to prevent a race when 427pruning them (in case another process is simultaneously writing a new 428object that refers to the about-to-be-deleted object). This leads to 429an explosion in the number of loose objects present and disk space 430usage due to the objects in delta form being replaced with independent 431loose objects. Worse, the race is still present for loose objects. 432 433Instead, "git gc" will need to move unreachable objects to a new 434packfile marked as UNREACHABLE_GARBAGE (using the PSRC field; see 435below). To avoid the race when writing new objects referring to an 436about-to-be-deleted object, code paths that write new objects will 437need to copy any objects from UNREACHABLE_GARBAGE packs that they 438refer to to new, non-UNREACHABLE_GARBAGE packs (or loose objects). 439UNREACHABLE_GARBAGE are then safe to delete if their creation time (as 440indicated by the file's mtime) is long enough ago. 441 442To avoid a proliferation of UNREACHABLE_GARBAGE packs, they can be 443combined under certain circumstances. If "gc.garbageTtl" is set to 444greater than one day, then packs created within a single calendar day, 445UTC, can be coalesced together. The resulting packfile would have an 446mtime before midnight on that day, so this makes the effective maximum 447ttl the garbageTtl + 1 day. If "gc.garbageTtl" is less than one day, 448then we divide the calendar day into intervals one-third of that ttl 449in duration. Packs created within the same interval can be coalesced 450together. The resulting packfile would have an mtime before the end of 451the interval, so this makes the effective maximum ttl equal to the 452garbageTtl * 4/3. 453 454This rule comes from Thirumala Reddy Mutchukota's JGit change 455https://git.eclipse.org/r/90465. 456 457The UNREACHABLE_GARBAGE setting goes in the PSRC field of the pack 458index. More generally, that field indicates where a pack came from: 459 460 - 1 (PACK_SOURCE_RECEIVE) for a pack received over the network 461 - 2 (PACK_SOURCE_AUTO) for a pack created by a lightweight 462 "gc --auto" operation 463 - 3 (PACK_SOURCE_GC) for a pack created by a full gc 464 - 4 (PACK_SOURCE_UNREACHABLE_GARBAGE) for potential garbage 465 discovered by gc 466 - 5 (PACK_SOURCE_INSERT) for locally created objects that were 467 written directly to a pack file, e.g. from "git add ." 468 469This information can be useful for debugging and for "gc --auto" to 470make appropriate choices about which packs to coalesce. 471 472Caveats 473------- 474Invalid objects 475~~~~~~~~~~~~~~~ 476The conversion from sha1-content to newhash-content retains any 477brokenness in the original object (e.g., tree entry modes encoded with 478leading 0, tree objects whose paths are not sorted correctly, and 479commit objects without an author or committer). This is a deliberate 480feature of the design to allow the conversion to round-trip. 481 482More profoundly broken objects (e.g., a commit with a truncated "tree" 483header line) cannot be converted but were not usable by current Git 484anyway. 485 486Shallow clone and submodules 487~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 488Because it requires all referenced objects to be available in the 489locally generated translation table, this design does not support 490shallow clone or unfetched submodules. Protocol improvements might 491allow lifting this restriction. 492 493Alternates 494~~~~~~~~~~ 495For the same reason, a newhash repository cannot borrow objects from a 496sha1 repository using objects/info/alternates or 497$GIT_ALTERNATE_OBJECT_REPOSITORIES. 498 499git notes 500~~~~~~~~~ 501The "git notes" tool annotates objects using their sha1-name as key. 502This design does not describe a way to migrate notes trees to use 503newhash-names. That migration is expected to happen separately (for 504example using a file at the root of the notes tree to describe which 505hash it uses). 506 507Server-side cost 508~~~~~~~~~~~~~~~~ 509Until Git protocol gains NewHash support, using NewHash based storage 510on public-facing Git servers is strongly discouraged. Once Git 511protocol gains NewHash support, NewHash based servers are likely not 512to support SHA-1 compatibility, to avoid what may be a very expensive 513hash reencode during clone and to encourage peers to modernize. 514 515The design described here allows fetches by SHA-1 clients of a 516personal NewHash repository because it's not much more difficult than 517allowing pushes from that repository. This support needs to be guarded 518by a configuration option --- servers like git.kernel.org that serve a 519large number of clients would not be expected to bear that cost. 520 521Meaning of signatures 522~~~~~~~~~~~~~~~~~~~~~ 523The signed payload for signed commits and tags does not explicitly 524name the hash used to identify objects. If some day Git adopts a new 525hash function with the same length as the current SHA-1 (40 526hexadecimal digit) or NewHash (64 hexadecimal digit) objects then the 527intent behind the PGP signed payload in an object signature is 528unclear: 529 530 object e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7 531 type commit 532 tag v2.12.0 533 tagger Junio C Hamano <gitster@pobox.com> 1487962205 -0800 534 535 Git 2.12 536 537Does this mean Git v2.12.0 is the commit with sha1-name 538e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7 or the commit with 539new-40-digit-hash-name e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7? 540 541Fortunately NewHash and SHA-1 have different lengths. If Git starts 542using another hash with the same length to name objects, then it will 543need to change the format of signed payloads using that hash to 544address this issue. 545 546Object names on the command line 547~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 548To support the transition (see Transition plan below), this design 549supports four different modes of operation: 550 551 1. ("dark launch") Treat object names input by the user as SHA-1 and 552 convert any object names written to output to SHA-1, but store 553 objects using NewHash. This allows users to test the code with no 554 visible behavior change except for performance. This allows 555 allows running even tests that assume the SHA-1 hash function, to 556 sanity-check the behavior of the new mode. 557 558 2. ("early transition") Allow both SHA-1 and NewHash object names in 559 input. Any object names written to output use SHA-1. This allows 560 users to continue to make use of SHA-1 to communicate with peers 561 (e.g. by email) that have not migrated yet and prepares for mode 3. 562 563 3. ("late transition") Allow both SHA-1 and NewHash object names in 564 input. Any object names written to output use NewHash. In this 565 mode, users are using a more secure object naming method by 566 default. The disruption is minimal as long as most of their peers 567 are in mode 2 or mode 3. 568 569 4. ("post-transition") Treat object names input by the user as 570 NewHash and write output using NewHash. This is safer than mode 3 571 because there is less risk that input is incorrectly interpreted 572 using the wrong hash function. 573 574The mode is specified in configuration. 575 576The user can also explicitly specify which format to use for a 577particular revision specifier and for output, overriding the mode. For 578example: 579 580git --output-format=sha1 log abac87a^{sha1}..f787cac^{newhash} 581 582Selection of a New Hash 583----------------------- 584In early 2005, around the time that Git was written, Xiaoyun Wang, 585Yiqun Lisa Yin, and Hongbo Yu announced an attack finding SHA-1 586collisions in 2^69 operations. In August they published details. 587Luckily, no practical demonstrations of a collision in full SHA-1 were 588published until 10 years later, in 2017. 589 590The hash function NewHash to replace SHA-1 should be stronger than 591SHA-1 was: we would like it to be trustworthy and useful in practice 592for at least 10 years. 593 594Some other relevant properties: 595 5961. A 256-bit hash (long enough to match common security practice; not 597 excessively long to hurt performance and disk usage). 598 5992. High quality implementations should be widely available (e.g. in 600 OpenSSL). 601 6023. The hash function's properties should match Git's needs (e.g. Git 603 requires collision and 2nd preimage resistance and does not require 604 length extension resistance). 605 6064. As a tiebreaker, the hash should be fast to compute (fortunately 607 many contenders are faster than SHA-1). 608 609Some hashes under consideration are SHA-256, SHA-512/256, SHA-256x16, 610K12, and BLAKE2bp-256. 611 612Transition plan 613--------------- 614Some initial steps can be implemented independently of one another: 615- adding a hash function API (vtable) 616- teaching fsck to tolerate the gpgsig-newhash field 617- excluding gpgsig-* from the fields copied by "git commit --amend" 618- annotating tests that depend on SHA-1 values with a SHA1 test 619 prerequisite 620- using "struct object_id", GIT_MAX_RAWSZ, and GIT_MAX_HEXSZ 621 consistently instead of "unsigned char *" and the hardcoded 622 constants 20 and 40. 623- introducing index v3 624- adding support for the PSRC field and safer object pruning 625 626 627The first user-visible change is the introduction of the objectFormat 628extension (without compatObjectFormat). This requires: 629- implementing the loose-object-idx 630- teaching fsck about this mode of operation 631- using the hash function API (vtable) when computing object names 632- signing objects and verifying signatures 633- rejecting attempts to fetch from or push to an incompatible 634 repository 635 636Next comes introduction of compatObjectFormat: 637- translating object names between object formats 638- translating object content between object formats 639- generating and verifying signatures in the compat format 640- adding appropriate index entries when adding a new object to the 641 object store 642- --output-format option 643- ^{sha1} and ^{newhash} revision notation 644- configuration to specify default input and output format (see 645 "Object names on the command line" above) 646 647The next step is supporting fetches and pushes to SHA-1 repositories: 648- allow pushes to a repository using the compat format 649- generate a topologically sorted list of the SHA-1 names of fetched 650 objects 651- convert the fetched packfile to newhash format and generate an idx 652 file 653- re-sort to match the order of objects in the fetched packfile 654 655The infrastructure supporting fetch also allows converting an existing 656repository. In converted repositories and new clones, end users can 657gain support for the new hash function without any visible change in 658behavior (see "dark launch" in the "Object names on the command line" 659section). In particular this allows users to verify NewHash signatures 660on objects in the repository, and it should ensure the transition code 661is stable in production in preparation for using it more widely. 662 663Over time projects would encourage their users to adopt the "early 664transition" and then "late transition" modes to take advantage of the 665new, more futureproof NewHash object names. 666 667When objectFormat and compatObjectFormat are both set, commands 668generating signatures would generate both SHA-1 and NewHash signatures 669by default to support both new and old users. 670 671In projects using NewHash heavily, users could be encouraged to adopt 672the "post-transition" mode to avoid accidentally making implicit use 673of SHA-1 object names. 674 675Once a critical mass of users have upgraded to a version of Git that 676can verify NewHash signatures and have converted their existing 677repositories to support verifying them, we can add support for a 678setting to generate only NewHash signatures. This is expected to be at 679least a year later. 680 681That is also a good moment to advertise the ability to convert 682repositories to use NewHash only, stripping out all SHA-1 related 683metadata. This improves performance by eliminating translation 684overhead and security by avoiding the possibility of accidentally 685relying on the safety of SHA-1. 686 687Updating Git's protocols to allow a server to specify which hash 688functions it supports is also an important part of this transition. It 689is not discussed in detail in this document but this transition plan 690assumes it happens. :) 691 692Alternatives considered 693----------------------- 694Upgrading everyone working on a particular project on a flag day 695~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 696Projects like the Linux kernel are large and complex enough that 697flipping the switch for all projects based on the repository at once 698is infeasible. 699 700Not only would all developers and server operators supporting 701developers have to switch on the same flag day, but supporting tooling 702(continuous integration, code review, bug trackers, etc) would have to 703be adapted as well. This also makes it difficult to get early feedback 704from some project participants testing before it is time for mass 705adoption. 706 707Using hash functions in parallel 708~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 709(e.g. https://public-inbox.org/git/22708.8913.864049.452252@chiark.greenend.org.uk/ ) 710Objects newly created would be addressed by the new hash, but inside 711such an object (e.g. commit) it is still possible to address objects 712using the old hash function. 713* You cannot trust its history (needed for bisectability) in the 714 future without further work 715* Maintenance burden as the number of supported hash functions grows 716 (they will never go away, so they accumulate). In this proposal, by 717 comparison, converted objects lose all references to SHA-1. 718 719Signed objects with multiple hashes 720~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 721Instead of introducing the gpgsig-newhash field in commit and tag objects 722for newhash-content based signatures, an earlier version of this design 723added "hash newhash <newhash-name>" fields to strengthen the existing 724sha1-content based signatures. 725 726In other words, a single signature was used to attest to the object 727content using both hash functions. This had some advantages: 728* Using one signature instead of two speeds up the signing process. 729* Having one signed payload with both hashes allows the signer to 730 attest to the sha1-name and newhash-name referring to the same object. 731* All users consume the same signature. Broken signatures are likely 732 to be detected quickly using current versions of git. 733 734However, it also came with disadvantages: 735* Verifying a signed object requires access to the sha1-names of all 736 objects it references, even after the transition is complete and 737 translation table is no longer needed for anything else. To support 738 this, the design added fields such as "hash sha1 tree <sha1-name>" 739 and "hash sha1 parent <sha1-name>" to the newhash-content of a signed 740 commit, complicating the conversion process. 741* Allowing signed objects without a sha1 (for after the transition is 742 complete) complicated the design further, requiring a "nohash sha1" 743 field to suppress including "hash sha1" fields in the newhash-content 744 and signed payload. 745 746Lazily populated translation table 747~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 748Some of the work of building the translation table could be deferred to 749push time, but that would significantly complicate and slow down pushes. 750Calculating the sha1-name at object creation time at the same time it is 751being streamed to disk and having its newhash-name calculated should be 752an acceptable cost. 753 754Document History 755---------------- 756 7572017-03-03 758bmwill@google.com, jonathantanmy@google.com, jrnieder@gmail.com, 759sbeller@google.com 760 761Initial version sent to 762http://public-inbox.org/git/20170304011251.GA26789@aiede.mtv.corp.google.com 763 7642017-03-03 jrnieder@gmail.com 765Incorporated suggestions from jonathantanmy and sbeller: 766* describe purpose of signed objects with each hash type 767* redefine signed object verification using object content under the 768 first hash function 769 7702017-03-06 jrnieder@gmail.com 771* Use SHA3-256 instead of SHA2 (thanks, Linus and brian m. carlson).[1][2] 772* Make sha3-based signatures a separate field, avoiding the need for 773 "hash" and "nohash" fields (thanks to peff[3]). 774* Add a sorting phase to fetch (thanks to Junio for noticing the need 775 for this). 776* Omit blobs from the topological sort during fetch (thanks to peff). 777* Discuss alternates, git notes, and git servers in the caveats 778 section (thanks to Junio Hamano, brian m. carlson[4], and Shawn 779 Pearce). 780* Clarify language throughout (thanks to various commenters, 781 especially Junio). 782 7832017-09-27 jrnieder@gmail.com, sbeller@google.com 784* use placeholder NewHash instead of SHA3-256 785* describe criteria for picking a hash function. 786* include a transition plan (thanks especially to Brandon Williams 787 for fleshing these ideas out) 788* define the translation table (thanks, Shawn Pearce[5], Jonathan 789 Tan, and Masaya Suzuki) 790* avoid loose object overhead by packing more aggressively in 791 "git gc --auto" 792 793[1] http://public-inbox.org/git/CA+55aFzJtejiCjV0e43+9oR3QuJK2PiFiLQemytoLpyJWe6P9w@mail.gmail.com/ 794[2] http://public-inbox.org/git/CA+55aFz+gkAsDZ24zmePQuEs1XPS9BP_s8O7Q4wQ7LV7X5-oDA@mail.gmail.com/ 795[3] http://public-inbox.org/git/20170306084353.nrns455dvkdsfgo5@sigill.intra.peff.net/ 796[4] http://public-inbox.org/git/20170304224936.rqqtkdvfjgyezsht@genre.crustytoothpaste.net 797[5] https://public-inbox.org/git/CAJo=hJtoX9=AyLHHpUJS7fueV9ciZ_MNpnEPHUz8Whui6g9F0A@mail.gmail.com/