web-dev-qa-db-ja.com

Gitのハッシュ衝突

Gitの使用中にハッシュ衝突が発生した場合、実際にはどうなりますか?

例えば。同じsha1チェックサムを使用して2つのファイルをコミットできますが、gitはそれを認識しますか、ファイルの1つを破損しますか?

Gitを改善してそれと共存できますか、それとも新しいハッシュアルゴリズムに変更する必要がありますか?

(ありそうもないことを議論することによってこの質問をそらさないでください-ありがとう)

161
Sec

10の月で原子を選ぶ

SHA-1ハッシュは40の16進文字列です。つまり、1文字あたり4ビットに40 ... 160ビットを掛けたものです。 10ビットは約1000(正確には1024)であることがわかります。つまり、1 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 SHA-1ハッシュがあります... 1048

これに相当するものは何ですか?まあ月は約10で構成されています47 原子。したがって、10個の月がある場合、これらの月のいずれかでランダムに1つatomを選択します...そして、ランダムにatom再び......同じatomを2回選択する可能性は、与えられた2つのgitコミットが同じSHA-1ハッシュを持つ可能性です。

これを展開して、質問をすることができます...

衝突を心配し始める前に、リポジトリにいくつのコミットが必要ですか?

これは、いわゆる「バースデイアタック」に関連しています。「バースデイアタック」は、「バースデイパラドックス」または「バースデイプロブレム」を指します。二度何かを選んだしかし、ここでは「驚くほど少数」というのは非常に相対的な用語です。

ウィキペディアには 誕生日のパラドックス衝突の確率に関する表 があります。 40文字のハッシュのエントリはありません。しかし、32文字と48文字のエントリを補間すると、5 * 10の範囲になります22 gitは0.1%の衝突確率でコミットします。これは、衝突が発生する可能性が0.1%に達する前に、500千億のコミット、つまり50Zettacommitsです。

これらのコミットのハッシュのみのバイト合計は、1年間に地球上で生成されたすべてのデータよりも多くのデータになります。つまり、YouTubeがビデオをストリーミングするよりも早くコードをチャーンアウトする必要があります。それで頑張ってください。 :D

これのポイントは、誰かが故意に衝突を引き起こさない限り、ランダムに起こる確率は非常に小さいため、この問題を無視できることです

「しかし、衝突が発生した場合、実際に何が起こるのか?」

さて、ありそうもないことが起こると仮定するか、誰かが 意図的なSHA-1ハッシュ衝突 を調整することに成功したと仮定します。それではどうなりますか?

その場合、 誰かが実験した素晴らしい答え があります。その答えから引用します:

  1. 同じハッシュを持つblobが既に存在する場合、警告はまったく表示されません。すべては大丈夫のようですが、プッシュしたり、誰かがクローンを作成したり、元に戻したりすると、最新バージョンが失われます(上記で説明したとおり)。
  2. ツリーオブジェクトが既に存在し、同じハッシュでblobを作成する場合:Pushを試みるか、誰かがリポジトリを複製するまで、すべてが正常に見えます。次に、レポが破損していることがわかります。
  3. コミットオブジェクトが既に存在し、同じハッシュでblobを作成する場合:#2と同じ-破損
  4. Blobが既に存在し、同じハッシュでコミットオブジェクトを作成すると、「ref」を更新するときに失敗します。
  5. BLOBが既に存在し、同じハッシュでツリーオブジェクトを作成する場合。コミットの作成時に失敗します。
  6. ツリーオブジェクトがすでに存在し、同じハッシュでコミットオブジェクトを作成すると、「ref」を更新するときに失敗します。
  7. ツリーオブジェクトが既に存在し、同じハッシュでツリーオブジェクトを作成する場合、すべてが正常に見えるでしょう。ただし、コミットすると、すべてのリポジトリが間違ったツリーを参照します。
  8. コミットオブジェクトがすでに存在し、同じハッシュでコミットオブジェクトを作成する場合、すべてが正常に見えるでしょう。ただし、コミットすると、コミットは作成されず、HEADポインターは古いコミットに移動します。
  9. コミットオブジェクトが既に存在し、同じハッシュでツリーオブジェクトを作成すると、コミットの作成時に失敗します。

おわかりのように、いくつかのケースは良くありません。特にケース#2と#3はリポジトリを台無しにします。ただし、障害はそのリポジトリ内にとどまり、攻撃/奇妙な可能性は他のリポジトリに伝播しないようです。

また、意図的な衝突の問題は実際の脅威として認識されているようですので、たとえば GitHubはそれを防ぐための対策を講じています

83
MichaelK

2つのファイルがgitで同じハッシュ和を持つ場合、それらのファイルは同一として扱われます。これが発生する可能性が非常に低い場合、常に1つのコミットに戻り、ファイル内の何かを変更して、それらが衝突しないようにすることができます...

gitメーリングリストのスレッド「sha-256について考え始めていますか?」のスレッド内のLinus Torvaldsの投稿 を参照してください。

63
klaustopher

なぜそれが問題ではないのかを説明せずに、この質問に正しい「しかし」と答えることは本当に不可能です。ハッシュが実際に何であるかを実際に把握していなければ、それを行うことはできません。これは、CSプログラムで遭遇する可能性のある単純なケースよりも複雑です。

ここには情報理論の基本的な誤解があります。大量の情報(ハッシュなど)を破棄して大量の情報を少量に減らすと、データの長さに直接関係する衝突の可能性があります。データが短いほど、データは少なくなります。これで、衝突の大部分は意味不明になり、実際に発生する可能性がはるかに高くなります(意味不明なコードをチェックインすることはありません...バイナリイメージであっても構造化されています)。最終的に、チャンスはわずかです。あなたの質問に答えるために、はい、gitはそれらを同じように扱います、ハッシュアルゴリズムを変更しても役に立たず、何らかの「二次チェック」が必要になりますが、最終的には、「追加チェック」データが必要になりますデータの長さが100%であることを確認してください... 99.99999になることを心に留めてください。 SHA-xは暗号学的に強力なハッシュです。つまり、一般的に、両方とも非常に類似していて、同じハッシュを持つ2つのソースデータセットを意図的に作成することは難しくありません。データの1ビットの変更は、ハッシュ出力に複数の(できればできるだけ多くの)ビットの変更を作成する必要があります。これは、ハッシュから完全なセットに戻ることは非常に難しい(しかし、不可能ではない)ことを意味します衝突、そしてそれによってその衝突のセットから元のメッセージを引き出します-少数を除いてすべては意味不明であり、メッセージの長さがかなりの長さである場合、それ以外のものはまだふるいにかけます。暗号化ハッシュの欠点は、一般的に計算が遅いことです。

では、Gitにとってそれはどういう意味ですか?あまりない。ハッシュが(他のすべてと比べて)まれにしか実行されないため、操作全体の計算ペナルティは低くなります。衝突のペアが発生する可能性は非常に低いため、発生してすぐに検出されない現実的な機会ではないため(つまり、コードが突然ビルドを停止する可能性が高い)、ユーザーは問題を修正できます(リビジョンをバックアップし、もう一度変更を加えると、時間の変更のためにほぼ確実に別のハッシュが取得されます。これにより、ハッシュがgitに送られます)。 gitに任意のバイナリを保存している場合、実際の問題になる可能性が高くなりますが、これは実際の主な使用モデルではありません。それをしたい場合は、おそらく従来のデータベースを使用する方が良いでしょう。

これについて考えるのは間違いではありません-多くの人が「考えるほど価値がない」と偽装するのは良い質問ですが、それよりも少し複雑です。発生した場合、非常に簡単に検出できるはずであり、通常のワークフローでのサイレントな破損ではありません。

25
Steve

Gitを改善してそれと共存できますか、それとも新しいハッシュアルゴリズムに変更する必要がありますか?

ハッシュアルゴリズムでは衝突が発生する可能性があるため、ハッシュ関数を変更しても問題が排除されるわけではなく、発生する可能性が低くなります。そのため、本当に良いハッシュ関数を選択する必要があります(SHA-1は既にありますが、言わないように頼みました:)

8

GitがblobでSHA-1衝突をどのように処理するか? 」で、良い研究を見ることができます。

SHA1衝突が可能になったため( この答え with shattered.io )、Git 2.13(2017年第2四半期)が、「衝突を作成する試みを検出」バリアントの現在の状況を改善/緩和することを知っています Marc Stevens(CWI)およびDan Shumow(Microsoft)によるSHA-1実装 =。

commit f5f5e7fcommit 8325e4commit c0c2006commit 45a574ecommit 28dc98e を参照してください(2017年3月16日)by Jeff King(peff
浜野潤夫-gitster- in commit 48b369 、2017年3月24日)

MakefileDC_SHA1 デフォルト

以前は、デフォルトでOpenSSLライブラリのSHA1実装を使用していました。
最近の「粉々になった」発表の後、衝突攻撃に注意しようとしているので、デフォルトを切り替えて、代わりにDC_SHA1実装の使用を推奨します。
OpenSSLの実装を使用する場合は、OPENSSL_SHA1=YesPleasemake」の実行時。

実際にはGitオブジェクトの衝突はありません。そのため、できることはtest-sha1を介して粉砕されたPDFの1つを実行することです。これにより、衝突チェックがトリガーされて終了します。


それに合わせてGitを改善できますか、それとも新しいハッシュアルゴリズムに変更する必要がありますか?

Git 2.16(2018年第1四半期)で2017年12月を更新:代替SHAをサポートする取り組みが進行中です:を参照" Gitが最新のSHAを使用しない理由

別のハッシュアルゴリズムを使用できます。SH1はGitの唯一のアルゴリズムではなくなりました。


Git 2.18(2018年第2四半期)はそのプロセスを文書化します。

commit 5988eb6commit 45fa195 (2018年3月26日)by ÆvarArnfjörðBjarmason(avar を参照してください。
C浜野順夫-gitster- in commit d877975 、2018年4月11日)

doc hash-function-transition:SHAtteredの意味を明確にする

Gitの実際のSHAttered攻撃の意味を明確にしようとします。
前のバージョンのテキストでは、Gitがこの特定の攻撃に対する緩和策を既に持っていることについては何も言及していませんでした。

ニュアンスが間違っているかもしれませんが、この新しいテキストは、gitのSHA-1の現在の状況を正確に要約しています。つまりgitは実際にはSHA-1を使用せず、Hardened-SHA-1を使用します(同じ出力を99.99999999999で生成します...時間の割合)。

したがって、前のテキストは次のことを主張する際に間違っていました。

[...] [SHAtteredの]結果として、SHA-1は暗号的に安全であるとは考えられなくなりました[...]

そうではありません。 SHAtteredに対する緩和策がありますが、将来のSHA-1またはHardened-SHA-1の脆弱性に備えてNewHashに向けて作業することは賢明であると考えています出現します。

新しいドキュメント は次のようになります。

Git v2.13.0以降は、デフォルトで強化されたSHA-1実装に移行しましたが、SHAttered攻撃に対して脆弱ではありません。

したがって、GitはすでにSHA-1ではなく、脆弱性を共有しない新しいハッシュに既に移行されています。その新しいハッシュ関数は、SHAtteredによって公開された2つのPDFを除き、既知のすべての入力に対してまったく同じ出力を生成するだけです研究者、および新しい実装(それらの研究者によって書かれた)は、将来の暗号解析的衝突攻撃を検出すると主張しています。

とにかく、SHA-1のすべてのバリアントを通過して新しいハッシュに移動するのが賢明と考えられています。 SHA-1に対する将来の攻撃が将来公開されないという保証はなく、これらの攻撃には実行可能な緩和策がない可能性があります。

SHA-1とそのバリアントが本当に壊れた場合、Gitのハッシュ関数は暗号的に安全であると見なすことができなくなります。これはハッシュ値の通信に影響を与えます。特定のハッシュ値が、スピーカーが意図したコンテンツの既知の良好なバージョンを表していることを信頼できないためです。

注:同じドキュメント(2018年第3四半期、Git 2.19)は、明示的に「新しいハッシュ」をSHA-256として明示的に参照しています:「 Why Gitは最新のSHAを使用しませんか? "。

7
VonC

Googleは現在、SHA-1の衝突が特定の前提条件の下で可能であると主張しています: https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html

GitはSHA-1を使用してファイルの整合性をチェックするため、これはgitのファイルの整合性が損なわれることを意味します。

IMO、意図的な衝突が可能になったため、gitは間違いなくより良いハッシュアルゴリズムを使用する必要があります。

5

ハッシュ衝突は非常に起こりそうにないので、本当に心を吹き飛ばされます!世界中の科学者は、それを達成しようと懸命に努力していますが、まだそれを管理していません。ただし、MD5などの特定のアルゴリズムでは成功しました。

オッズは何ですか?

SHA-256には2 ^ 256個のハッシュがあります。それは約10 ^ 78です。または、よりグラフィックにするために、衝突の可能性は約

1:100,000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000

宝くじに当たる確率は、約1:14 Mioです。 SHA-256との衝突の可能性は、11日間連続して宝くじに当たるようなものです

数学的な説明: 14 000 0 ^ 11〜2 ^ 256

さらに、 niverse には約10 ^ 80個の原子があります。これは、SHA-256の組み合わせの100倍です。

成功したMD5コリジョン

MD5の場合でも、チャンスはわずかです。ただし、数学者はなんとか衝突を起こすことができました。

d131dd02c5e6eec4 693d9a0698aff95c 2fcab58712467eab 4004583eb8fb7f89 
 55ad340609f4b302 83e488832571415a 085125e8f7cdc99f d91dbdf280373c5b 
 d8823e3156348f5b ae6dacd436c919c6 dd53e2b487da03fd 02396306d248cda0 
 e99f33420f577ee8 ce54b67080a80d1e c69821bcb6a88393 96f9652b6ff72a70

と同じMD5を持つ

d131dd02c5e6eec4 693d9a0698aff95c 2fcab5712467eab 4004583eb8fb7f89 
 55ad340609f4b302 83e4888325f1415a 085125e8f7cdc99f d91dbd7280373c5b 
 d8823e3156348f5b ae6dacd436c919c6 dd53e23487da03fd 02396306d248cda0 
 e99f33420f577ee8 ce54b67080280d1e c69821bcb6a88393 96f965ab6ff72a70

これは、MD5のアルゴリズムがクラックされたため、MD5の安全性が低下したことを意味するものではありません。 MD5コリジョンは意図的に作成できますが、偶発的なMD5コリジョンの可能性はまだ2 ^ 128であり、これはまだ多くあります。

結論

衝突について心配する必要はありません。ハッシュアルゴリズムは、ファイルの同一性をチェックする2番目に安全な方法です。唯一の安全な方法は、バイナリ比較です。

2
bytecode77

私は最近、2013年4月29日の投稿をBSDディスカッショングループで見つけました。

http://openbsd-archive.7691.n7.nabble.com/Why-does-OpenBSD-use-CVS-td226952.html

ポスターの主張:

Git rebaseを使用して、一度ハッシュ衝突に遭遇しました。

残念ながら、彼は彼の主張の証拠を提供していません。しかし、あなたは彼に連絡して、この想定される出来事について彼に尋ねたいと思うかもしれません。

しかし、より一般的なレベルでは、誕生日攻撃のために、SHA-1ハッシュ衝突の可能性はpow(2、80)で1です。

これは非常に聞こえがよく、確かに、世界中のすべてのGitリポジトリに存在する個々のファイルのバージョンの合計数をはるかに超えています。

ただし、これはバージョン履歴に実際に残っているバージョンにのみ適用されます。

開発者がリベースに大きく依存している場合、ブランチに対してリベースが実行されるたびに、そのブランチのすべてのバージョン(またはブランチのリベースされた部分)のすべてのコミットが新しいハッシュを取得します。同じことは、「git filter-branch」で変更するすべてのファイルに当てはまります。したがって、「rebase」と「filter-branch」は、すべてが実際に保持されるわけではありませんが、時間の経過とともに生成されるハッシュ数の大きな乗数になる可能性があります。 )、元のブランチは破棄されます。

ただし、リベースまたはフィルター分岐中に衝突が発生した場合でも、悪影響が生じる可能性があります。

もう1つのことは、gitリポジトリ内のハッシュされたエンティティの総数を推定し、pow(2、80)からどれだけ離れているかを確認することです。

約80億人の人がいて、全員がgitを実行していて、1人あたり100のgitリポジトリでバージョンを管理しているとします。さらに、平均的なリポジトリには100個のコミットと10個のファイルがあり、これらのファイルの1つだけがコミットごとに変更されると仮定します。

リビジョンごとに、少なくともツリーオブジェクトとコミットオブジェクト自体のハッシュがあります。変更されたファイルと共に、リビジョンごとに3つのハッシュがあり、リポジトリごとに300のハッシュがあります。

80億人の100のリポジトリに対して、これはpow(2、47)を与えますが、それはまだpow(2、80)からはほど遠いです。

ただし、この推定にどのようにそれを含めるかは不明であるため、これには上記の想定される乗算効果は含まれていません。たぶん、衝突の可能性をかなり高める可能性があります。特に、(Linuxカーネルのような)長いコミット履歴を持つ非常に大きなリポジトリが、小さな変更のために多くの人々によってリベースされ、それにもかかわらず、影響を受けるすべてのコミットに対して異なるハッシュを作成する場合。

1

さて、私たちは今何が起こるかを知っていると思います-あなたのリポジトリが破損することを期待すべきです( source )。

1
Conor Bradley