Pourquoi Git n'utilise-t-il pas un SHA plus moderne?

90

J'ai lu que Git utilise le condensé SHA-1 comme ID pour une révision. Pourquoi n'utilise-t-il pas une version plus moderne de SHA?

qazwsx
la source
2
La performance est la seule raison à laquelle je peux penser, SHA-1 est plus rapide que SHA-2. Personnellement, je considère que c'est une mauvaise décision, car la résistance aux collisions de SHA-1 est plutôt faible.
CodesInChaos
4
stackoverflow.com/questions/9392365/… - pas une correspondance exacte, mais couvre un terrain similaire
logiciel
6
Cela a été discuté sur la liste de diffusion git en 2006. Voir le fil complet . Pour résumer, Linus a déclaré à l'époque que SHA-1 devait seulement être suffisamment unique pour que les collisions ne se produisent pas, ce qui est le cas. SHA-1 n'est pas une fonctionnalité de sécurité pour git. "Quiconque accepte aveuglément des données provenant de sources non fiables est vissé de tellement d'autres façons que l'attaque de hachage n'est tout simplement même pas sur le radar." - Linus
tbc0
28
Mise à jour: Collisions SHA-1 maintenant dans la nature shattered.it
Drewr
2
Q1 2018: cet effort pour soutenir un SHA alternatif est en cours: voir ma réponse ci
VonC

Réponses:

62

Pourquoi n'utilise-t-il pas une version plus moderne de SHA?

Dec.2017: Ça le fera. Et Git 2.16 (Q1 2018) est la première version à illustrer et implémenter cette intention.

Remarque: voir Git 2.19 ci-dessous: ce sera SHA-256 .

Git 2.16 proposera une infrastructure pour définir quelle fonction de hachage est utilisée dans Git, et commencera un effort pour l'exploiter dans divers codepaths.

Voir commit c250e02 (28 novembre 2017) par Ramsay Jones (``) .
Voir commit eb0ccfd , commit 78a6766 , commit f50e766 , commit abade65 (12 novembre 2017) par brian m. carlson ( bk2204) .
(Fusionné par Junio ​​C Hamano - gitster- in commit 721cc43 , 13 déc 2017)


Ajouter une structure représentant l'algorithme de hachage

Étant donné qu'à l'avenir, nous souhaitons prendre en charge un algorithme de hachage supplémentaire, ajouter une structure qui représente un algorithme de hachage et toutes les données qui doivent l'accompagner .
Ajoutez une constante pour permettre une énumération facile des algorithmes de hachage .
Implémentez une fonctiontypedefs pour créer une API abstraite qui peut être utilisée par n'importe quel algorithme de hachage et des wrappers pour les fonctions SHA1 existantes conformes à cette API.

Exposez une valeur pour la taille hexadécimale ainsi que la taille binaire .
Alors que l'un sera toujours le double de l'autre, les deux valeurs sont toutes deux utilisées de manière extrêmement courante dans toute la base de code et fournir les deux conduit à une meilleure lisibilité.

N'incluez pas d'entrée dans la structure de l'algorithme de hachage pour l'ID d'objet nul.
Comme cette valeur est entièrement zéros, n'importe quel ID d'objet entièrement nul peut être utilisé, et il n'est pas nécessaire d'en stocker un par hachage.

Le plan de transition de la fonction de hachage actuel envisage un moment où nous accepterons les entrées de l'utilisateur qui pourraient être au format SHA-1 ou au format NewHash.
Puisque nous ne pouvons pas savoir ce que l'utilisateur a fourni, ajoutez une constante représentant l'algorithme inconnu pour nous permettre d'indiquer que nous devons rechercher la valeur correcte.


Intégrer la prise en charge des algorithmes de hachage avec la configuration du dépôt

Dans les futures versions de Git, nous prévoyons de prendre en charge un algorithme de hachage supplémentaire.
Intégrez l'énumération des algorithmes de hachage à la configuration du référentiel et stockez un pointeur vers les données énumérées dans le référentiel struct .
Bien sûr, nous ne prenons actuellement en charge que SHA-1, donc codez en dur cette valeur dans read_repository_format .
À l'avenir, nous énumérerons cette valeur à partir de la configuration.

Ajoutez une constante,,the_hash_algo qui pointe vers le hash_algopointeur de structure dans le référentiel global.
Notez que c'est le hachage qui est utilisé pour sérialiser les données sur le disque, pas le hachage qui est utilisé pour afficher les éléments à l'utilisateur.
Le plan de transition prévoit que ceux-ci peuvent être différents.
Nous pouvons ajouter un élément supplémentaire à l'avenir (par exemple ui_hash_algo) pour prévoir ce cas.


Mise à jour d'août 2018, pour Git 2.19 (Q3 2018), Git semble choisir SHA-256 comme NewHash.

Voir commit 0ed8d8d (04 août 2018) par Jonathan Nieder ( artagnon) .
Voir commit 13f5e09 (25 juillet 2018) par Ævar Arnfjörð Bjarmason ( avar) .
(Fusionné par Junio ​​C Hamano - gitster- in commit 34f2297 , 20 août 2018)

dochash-function-transition : choisissez SHA-256 comme NewHash

Du point de vue de la sécurité, il semble que SHA-256, BLAKE2, SHA3-256, K12 et ainsi de suite aient tous des propriétés de sécurité similaires.
Ce sont toutes de bonnes options du point de vue de la sécurité.

SHA-256 présente un certain nombre d'avantages:

  • Il existe depuis un certain temps, est largement utilisé et est pris en charge par à peu près toutes les bibliothèques de chiffrement (OpenSSL, mbedTLS, CryptoNG, SecureTransport, etc.).

  • Lorsque vous comparez avec SHA1DC, la plupart des implémentations SHA-256 vectorisées sont en effet plus rapides, même sans accélération.

  • Si nous faisons des signatures avec OpenPGP (ou même, je suppose, CMS), nous allons utiliser SHA-2, il n'est donc pas logique que notre sécurité dépende de deux algorithmes séparés lorsque l'un d'entre eux seul pourrait briser la sécurité alors que nous ne pouvions compter que sur un seul.

C'est donc SHA-256 .
Mettez à jour le document de conception de transition de fonction de hachage pour le dire.

Après ce patch, il n'y a plus d'instances restantes de la chaîne " NewHash", à l'exception d'une utilisation non liée à partir de 2008 comme nom de variable dans t/t9700/test.pl .


Vous pouvez voir cette transition vers SHA 256 en cours avec Git 2.20 (Q4 2018):

Voir commettre 0d7c419 , engager dda6346 , engager eccb5a5 , engager 93eb00f , engager d8a3a69 , engager fbd0e37 , engager f690b6b , engager 49d1660 , engager 268babd , engager fa13080 , engager 7b5e614 , engager 58ce21b , engager 2f0c9e9 , engager 825544a (15 octobre 2018) par brian m . carlson ( bk2204) .
Voir commit 6afedba (15 octobre 2018) par SZEDER Gábor ( szeder) .
(Fusionné parJunio ​​C Hamano - gitster- dans commit d829d49 , 30 octobre 2018)

remplacer les constantes codées en dur

Remplacez plusieurs constantes de base 40 par des références à GIT_MAX_HEXSZou the_hash_algo, selon le cas.
Convertissez toutes les utilisations de GIT_SHA1_HEXSZà utiliser the_hash_algoafin qu'elles soient appropriées pour une longueur de hachage donnée.
Au lieu d'utiliser une constante codée en dur pour la taille d'un ID d'objet hexadécimal, basculez pour utiliser le pointeur calculé à partir de parse_oid_hexces points après l'ID d'objet analysé.

GIT_SHA1_HEXSZest en outre supprimé / remplacé par Git 2.22 (Q2 2019) et commit d4e568b .


Cette transition se poursuit avec Git 2.21 (Q1 2019), qui ajoute le hachage sha-256 et le branche via le code pour permettre la construction de Git avec le "NewHash".

Voir engager 4b4e291 , engager 27dc04c , engager 13eeedb , engager c166599 , engager 37649b7 , engager a2ce0a7 , engager 50c817e , engager 9a3a0ff , engager 0dab712 , engager 47edb64 (14 novembre 2018), et engager 2f90b9d , engager 1ccf07c (22 octobre 2018) par Brian m . carlson ( bk2204) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 33e4ae9 , 29 janvier 2019)

Ajouter une implémentation de base du support SHA-256 (février 2019)

SHA-1 est faible et nous devons passer à une nouvelle fonction de hachage.
Depuis quelque temps, nous avons appelé cette nouvelle fonction NewHash.
Récemment, nous avons décidé de choisir SHA-256 commeNewHash .
Les raisons du choix de SHA-256 sont décrites dans ce fil et dans l'historique des validations pour le document de transition de fonction de hachage.

Ajoutez une implémentation de base de SHA-256 basée sur libtomcrypt, qui est dans le domaine public.
Optimisez-le et restructurez-le pour répondre à nos normes de codage.
Tirez la mise à jour et les fonctions finales de l'implémentation du bloc SHA-1, car nous savons qu'elles fonctionnent correctement avec tous les compilateurs. Cette implémentation est plus lente que SHA-1, mais des implémentations plus performantes seront introduites dans les commits futurs.

Connectez SHA-256 dans la liste des algorithmes de hachage et ajoutez un test indiquant que l'algorithme fonctionne correctement.

Notez qu'avec ce patch, il n'est toujours pas possible de passer à l'utilisation de SHA-256 dans Git.
Des correctifs supplémentaires sont nécessaires pour préparer le code afin de gérer un algorithme de hachage plus volumineux et d'autres correctifs de test sont nécessaires.

hash: ajouter une implémentation SHA-256 en utilisant OpenSSL

Nous avons déjà des routines OpenSSL disponibles pour SHA-1, alors ajoutez également des routines pour SHA-256.

Sur un Core i7-6600U, cette implémentation SHA-256 se compare favorablement à l'implémentation SHA1DC SHA-1:

SHA-1: 157 MiB/s (64 byte chunks); 337 MiB/s (16 KiB chunks)
SHA-256: 165 MiB/s (64 byte chunks); 408 MiB/s (16 KiB chunks)

sha256: ajoutez une implémentation SHA-256 en utilisant libgcrypt

En général, les routines cryptographiques écrites en assemblage sont plus performantes que C, et cela est également vrai pour SHA-256.
De plus, la plupart des distributions Linux ne peuvent pas distribuer Git lié à OpenSSL pour des raisons de licence.

La plupart des systèmes avec GnuPG en auront également libgcrypt, car il s'agit d'une dépendance de GnuPG.
libgcryptest également plus rapide que l'implémentation SHA1DC pour les messages de quelques Ko et plus.

À titre de comparaison, sur un Core i7-6600U, cette implémentation traite 16 blocs de Kio à 355 Mio / s tandis que SHA1DC traite des morceaux équivalents à 337 Mio / s.

En outre, libgcrypt est sous licence LGPL 2.1, qui est compatible avec la GPL. Ajoutez une implémentation de SHA-256 qui utilise libgcrypt.


L'effort de mise à niveau se poursuit avec Git 2.24 (T4 2019)

Voir commit aaa95df , commit be8e172 , commit 3f34d70 , commit fc06be3 , commit 69fa337 , commit 3a4d7aa , commit e0cb7cd , commit 8d4d86b , commit f6ca67d , commit dd336a5 , commit 894c0f6 , commit 4439c7a , commit e0cb7cd , commit 8d4d86b , commit f6ca67d , commit dd336a5 , commit 894c0f6 , commit 4439c7a , commit e0cb7cd , commit 8d4d86b , commit f6ca67d , commit dd336a5 , commit 894c0f6 , commit 4439c7a , commit e0cb7cd , commit 8d4d86b , commit f6ca67d , commit dd336a5 , commit 894c0f6 , commit 4439c7a , commit 95518fa , commite 703d2d4 , validation 9d958cc , validation 7962e04 , frais de validation 4930(18 août 2019) par brian m. carlson ( bk2204) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 676278f , 11 octobre 2019)

Au lieu d'utiliser GIT_SHA1_HEXSZdes constantes codées en dur, passez à using the_hash_algo.


Avec Git 2.26 (Q1 2020), les scripts de test sont prêts pour le jour où les noms d'objets utiliseront SHA-256.

Voir commettre 277eb5a , engager 44b6c05 , engager 7a868c5 , engager 1b8f39f , engager a8c17e3 , engager 8.320.722 , engager 74ad99b , engager ba1be1a , engager cba472d , engager 82d5aeb , engager 3c5e65c , engager 235d3cd , engager 1d86c8f , engager 525a7f1 , engager 7a1bcb2 , engager cb78f4f , commit 717c939 , commit 08a9dd8 , commit 215b60b , commit 194264c(21 décembre 2019) par brian m. carlson ( bk2204) .
(Fusionné par Junio ​​C Hamano - gitster- in commit f52ab33 , 05 fév 2020)

Exemple:

t4204: rendre la taille de hachage indépendante

Signé par: Brian M. Carlson

À utiliser $OID_REGEXau lieu d'une expression régulière codée en dur.

Donc, au lieu d'utiliser:

grep "^[a-f0-9]\{40\} $(git rev-parse HEAD)$" output

Les tests utilisent

grep "^$OID_REGEX $(git rev-parse HEAD)$" output

Et OID_REGEXvient du commit bdee9cd (13 mai 2018) par brian m. carlson ( bk2204) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 9472b13 , 30 mai 2018, Git v2.18.0-rc0)

t/test-lib: présenter OID_REGEX

Signé par: Brian M. Carlson

Actuellement, nous avons une variable, $_x40,qui contient une expression régulière qui correspond à une constante hexadécimale de 40 caractères.

Cependant, avec NewHash, nous aurons des ID d'objet de plus de 40 caractères.

Dans un tel cas, $_x40sera un nom déroutant.

Créez une $OID_REGEXvariable qui reflétera toujours une expression régulière correspondant à l'ID d'objet approprié, quelle que soit la longueur du hachage actuel.

Et, toujours pour les tests:

Voir commettre f303765 , engager edf0424 , engager 5db24dc , engager d341e08 , engager 88ed241 , engager 48c10cc , engager f7ae8e6 , commettre e70649b , commettre a30f93b , commettre a79eec2 , engager 796d138 , engager 417e45e , engager dfa5f53 , engager f743e8f , engager 72f936b , engager 5df0f11 , commit 07877f3 , commit 6025e89 , commit 7b1a182 , commit 94db7e3 ,commit db12505 (07 févr.2020 ) par brian m. carlson ( bk2204) .
(Fusionné par Junio ​​C Hamano - gitster- in commit 5af345a , 17 fév 2020)

t5703: faire fonctionner le test avec SHA-256

Signé par: Brian M. Carlson

Ce test a utilisé un ID d'objet d'une longueur de 40 caractères hexadécimaux, ce qui a non seulement fait en sorte que le test ne réussisse pas, mais qu'il se bloque, lorsqu'il est exécuté avec SHA-256 comme hachage.

Remplacez cette valeur par un ID d'objet factice fixe à l'aide de test_oid_initet test_oid.

De plus, assurez-vous d'extraire un ID d'objet de la longueur appropriée en utilisant une coupe avec des champs au lieu d'une longueur fixe.


Certains codepaths ont reçu une instance de référentiel en tant que paramètre pour fonctionner dans le référentiel, mais ont passé l' the_repositoryinstance à ses appelées, qui a été nettoyée (un peu) avec Git 2.26 (Q1 2020).

Voir commit b98d188 , commit 2dcde20 , commit 7ad5c44 , commit c8123e7 , commit 5ec9b8a , commit a651946 , commit eb999b3 (30 janvier 2020) par Matheus Tavares ( matheustavares) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 78e67cd , 14 février 2020)

sha1-file: permet check_object_signature()de gérer n'importe quel repo

Signé par: Matheus Tavares

Certains appelants de check_object_signature()peuvent travailler sur des référentiels arbitraires, mais le référentiel n'est pas passé à cette fonction. Au lieu de cela, the_repositoryest toujours utilisé en interne.
Pour corriger d'éventuelles incohérences, autorisez la fonction à recevoir un référentiel struct et faites en sorte que ces appelants transmettent le référentiel en cours de traitement.

Basé sur:

sha1-file: passer git_hash_algoàhash_object_file()

Signé par: Matheus Tavares

Permet hash_object_file()de travailler sur des dépôts arbitraires en introduisant un git_hash_algoparamètre. Changez les appelants qui ont un pointeur de référentiel struct dans leur portée pour transmettre le git_hash_algodepuis ledit dépôt.
Pour tous les autres appelants, transmettre the_hash_algo, qui était déjà utilisé en interne à hash_object_file().
Cette fonctionnalité sera utilisée dans le patch suivant pour check_object_signature()pouvoir travailler sur des dépôts arbitraires (qui, à son tour, seront utilisés pour corriger une incohérence au niveau de object.c: parse_object ()).

VonC
la source
1
De plus, n'oubliez pas que Git v2.13.0 et plus tard est passé par défaut à une implémentation SHA-1 renforcée, qui n'est pas vulnérable à l'attaque SHAttered. Voir stackoverflow.com/a/43355918/6309
VonC
1: Google a produit une collision shattered.io en février 2017 (coût estimé à 110000 USD) 2: l'Université technologique de Nanyang a produit une collision sha-mbles.github.io en janvier 2019 (coût estimé entre 11000 et 45000 USD) Il est temps pour Git va dépasser SHA1
bristweb
@bristweb "Il est temps pour Git de passer au-delà de SHA1": Je suis d'accord, et avec Git 2.25 (publié aujourd'hui), ce mouvement va de l'avant. git rev-parseest maintenant capable d'imprimer quel hachage sera utilisé: stackoverflow.com/a/58862319/6309 . Et l'arbre vide a un nouvel identifiant SHA2: stackoverflow.com/a/9766506/6309
VonC le
Avec cette extensibilité d'algo de hachage, CRC32 peut enfin briller à nouveau.
Walf
52

MISE À JOUR : La question ci-dessus et cette réponse datent de 2015. Depuis lors, Google a annoncé la première collision SHA-1: https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html


Évidemment, je ne peux que spéculer de l'extérieur en regardant pourquoi Git continue d'utiliser SHA-1, mais cela peut être l'une des raisons:

  1. Git était la création de Linus Torvald, et Linus ne veut apparemment pas remplacer SHA-1 par un autre algorithme de hachage pour le moment.
  2. Il fait des affirmations plausibles selon lesquelles les attaques réussies basées sur les collisions SHA-1 contre Git sont bien plus difficiles que la réalisation des collisions elles-mêmes, et considérant que SHA-1 est plus faible qu'il ne devrait l'être, pas complètement cassé, cela le rend sensiblement loin d'un attaque réalisable au moins aujourd'hui. De plus, il note qu'une attaque "réussie" ne produirait que très peu de résultats si l'objet en collision arrive plus tard que celui existant, car le dernier serait simplement supposé être le même que celui valide et ignoré (bien que d'autres aient souligné que l'inverse pourrait se produire).
  3. Le changement de logiciel prend du temps et est source d'erreurs, en particulier lorsqu'il existe une infrastructure existante et des données basées sur les protocoles existants qui devront être migrés. Même ceux qui produisent des produits logiciels et matériels où la sécurité cryptographique est le seul point du système sont toujours en train de migrer loin de SHA-1 et d'autres algorithmes faibles par endroits. Imaginez simplement tous ces unsigned char[20]tampons codés en dur partout ;-), il est beaucoup plus facile de programmer l'agilité cryptographique au début, plutôt que de le moderniser plus tard.
  4. Les performances de SHA-1 sont meilleures que les différents hachages SHA-2 (probablement pas au point d'être un facteur décisif maintenant, mais c'était peut-être un point de friction il y a 10 ans), et la taille de stockage de SHA-2 est plus grande .

Quelques liens:

Mon point de vue personnel serait que, même si les attaques pratiques sont probablement un certain temps, et même lorsqu'elles se produisent, les gens les atténueront probablement au départ avec des moyens autres que de changer l'algorithme de hachage lui-même, que si vous vous souciez de la sécurité, vous devriez vous tromper. du côté de la prudence dans vos choix d'algorithmes, et en révisant continuellement à la hausse vos forces de sécurité, car les capacités des attaquants ne vont également que dans une direction, il serait donc imprudent de prendre Git comme modèle, d'autant plus que son objectif dans l'utilisation de SHA-1 ne prétend pas être une sécurité cryptographique.

softwariness
la source
7
"Vous pouvez avoir des gens qui essaient d'être malveillants. Ils ne réussiront pas. N̶o̶b̶o̶d̶y̶ ̶h̶a̶s̶ ̶b̶e̶e̶n̶ ̶a̶b̶l̶e̶ ̶t̶o̶ ̶b̶re̶a̶k̶ ̶S̶H̶H̶A-̶ ̶1̶ . C'est purement un contrôle de cohérence. " -Linus Torvalds
Shakti
9
Les hachages de Git doivent être sécurisés pour que les signatures sécurisées que les gens placent sur leur code vérifient quoi que ce soit. Ces signatures signent un énorme arbre de ces hachages. Si une branche de cet arbre entre en collision, un code malveillant peut être inséré pendant que la signature passe. Git est très largement utilisé maintenant. Une mise à niveau de hachage est nécessaire.
fuzzyTew
Deux choses à considérer à la lumière de "brisé": 1. Utilisation de SHA-1. - SHA-1 est utilisé comme somme de contrôle glorifiée pour vérifier contre la corruption accidentelle. - SHA-1 est utilisé comme une fonction de générateur pour donner un (un peu petit) nombre hexadécimal pratique pour désigner les objets à l'intérieur de son magasin adressable de contenu (c'est-à-dire: générateur de nom de fichier glorifié). - Ce sont des commits signés qui sont responsables de la sécurité (ex: siganture de cryptographie à clé publique. PAS sha-1)
DrYak
2. Faisabilité - après des tonnes de temps GPU, Google a réussi à générer une paire de séries de blocs. - les deux hachés sur la même somme SHA-1 (c'est la collision) - ils sont complètement effrayants (cela va être difficile de justifier pourquoi votre commit a un bloc géant de déchets binaires au milieu). - la démo brisée repose sur le fait d'avoir un moyen de présenter un comportement différent en fonction du indésirable binaire aléatoire présent. C'est possible avec PDF (qui a un langage de script intégré caché derrière). Cela va être beaucoup plus difficile sur la source ordinaire (pensez au concours
S Underhanded
@DrYak For 2: supposons que vous suivez les documents Photoshop avec un champ de commentaire. Ou d'autres fichiers multimédias avec des balises méta. C'est un cas typique dans le développement de jeux. Mais ils ne seront généralement pas vérifiés à chaque changement: pourquoi vérifier la méta-balise si le message de validation dit "optimiser pour la taille"?
Arne Babenhauserheide
5

Ceci est une discussion sur l'urgence de migrer loin de SHA1 pour Mercurial, mais cela s'applique également à Git: https://www.mercurial-scm.org/wiki/mpm/SHA1

En bref: si vous n'êtes pas extrêmement intelligent aujourd'hui, vous avez des vulnérabilités bien pires que sha1. Mais malgré cela, Mercurial a commencé il y a plus de 10 ans à se préparer à migrer loin de sha1.

des travaux sont en cours depuis des années pour moderniser les structures de données et les protocoles de Mercurial pour les successeurs de SHA1. L'espace de stockage a été alloué pour des hachages plus importants dans notre structure de revlog il y a plus de 10 ans dans Mercurial 0.9 avec l'introduction de RevlogNG. Le format bundle2 introduit plus récemment prend en charge l'échange de différents types de hachage sur le réseau. Les seules pièces restantes sont le choix d'une fonction de remplacement et le choix d'une stratégie de rétrocompatibilité.

Si git ne migre pas de sha1 avant Mercurial, vous pouvez toujours ajouter un autre niveau de sécurité en gardant un miroir Mercurial local avec hg-git .

Arne Babenhauserheide
la source
3

Il existe maintenant un plan de transition vers un hachage plus fort, il semble donc qu'à l'avenir, il utilisera un hachage plus moderne que SHA-1. À partir du plan de transition actuel :

Certains hachages considérés sont SHA-256, SHA-512/256, SHA-256x16, K12 et BLAKE2bp-256

Paul Wagland
la source