Portage de bcrypt.codeplex.com avec une sécurité améliorée, des correctifs manquants, des fonctionnalités et une meilleure prise en charge .net.
Téléchargez à l'aide de nuget ou Paket (https://fsprojects.github.io/Paket/)
Forfait : https://www.nuget.org/packages/BCrypt.Net-Next/
Package signé - https://www.nuget.org/packages/BCrypt.Net-Next.StrongName/
Il existe divers exemples dans notre dossier de tests et de tests unitaires
L'utilisation la plus simple est la suivante...
Pour hacher un mot de passe :
Les espaces de noms étendus aux fichiers sont affichés ; imaginez des accolades si vous en avez besoin.
Top level namespace
namespace DotNetSix ;
using BCrypt . Net ;
string passwordHash = BCrypt . HashPassword ( "my password" ) ;
En raison du nom de la bibliothèque, si l'espace de noms est après les instructions using, l'appel change car .net ne parvient pas à résoudre correctement le nom. Je vous conseille plutôt que d'entrer l'intégralité de l'espace de noms d'utiliser simplement l'alias d'importation comme ci-dessous.
using BC = BCrypt . Net . BCrypt ;
namespace DotNetSix ;
string passwordHash = BC . HashPassword ( "my password" ) ;
Vous pouvez également créer un alias au niveau CSProj ; et je n'aurais pas du tout besoin d'ajouter l'instruction using
Cet exemple vous permettrait d'utiliser un alias BC.HashPassword() dans votre code
< ItemGroup >
<!-- emits global using BcryptNet = global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Alias = " BC " />
</ ItemGroup >
Cette version vous permettrait d'appeler simplement Verify
et HashPassword
dans votre base de code sans aucune autre référence.
< ItemGroup >
<!-- emits global using static global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Static = " True " />
</ ItemGroup >
Remarque : Bien que cette bibliothèque vous permette de fournir votre propre sel, il est fortement conseillé de lui permettre de générer le sel pour vous. Ces méthodes sont fournies pour maintenir la compatibilité et pour répondre aux exigences multiplateformes plus avancées qui peuvent nécessiter leur utilisation.
Pour vérifier un mot de passe par rapport à un hachage (en supposant que vous avez stocké le hachage et récupéré du stockage pour vérification) :
Toutes les notes précédentes sur l'espacement des noms s'appliquent également ici
BCrypt . Verify ( "my password" , passwordHash ) ;
Cette implémentation de hachage générera automatiquement un sel pour vous avec le facteur de travail (2 ^ nombre de tours) défini sur 11 (ce qui correspond à la valeur par défaut dans la plupart des implémentations et est actuellement considéré comme un bon niveau de sécurité/risque).
Pour vous éviter les calculs, un petit tableau couvrant les itérations est fourni ci-dessous. Le minimum autorisé dans cette bibliothèque est de 4 pour la compatibilité, le maximum est de 31 (à 31 votre processeur souhaitera la mort).
| Cost | Iterations |
|-------|--------------------------|
| 8 | 256 iterations |
| 9 | 512 iterations |
| 10 | 1,024 iterations |
| 11 | 2,048 iterations |
| 12 | 4,096 iterations |
| 13 | 8,192 iterations |
| 14 | 16,384 iterations |
| 15 | 32,768 iterations |
| 16 | 65,536 iterations |
| 17 | 131,072 iterations |
| 18 | 262,144 iterations |
| 19 | 524,288 iterations |
| 20 | 1,048,576 iterations |
| 21 | 2,097,152 iterations |
| 22 | 4,194,304 iterations |
| 23 | 8,388,608 iterations |
| 24 | 16,777,216 iterations |
| 25 | 33,554,432 iterations |
| 26 | 67,108,864 iterations |
| 27 | 134,217,728 iterations |
| 28 | 268,435,456 iterations |
| 29 | 536,870,912 iterations |
| 30 | 1,073,741,824 iterations |
| 31 | 2,147,483,648 iterations |
etc
et un simple benchmark que vous pouvez exécuter en créant un programme console, en ajoutant cette bibliothèque BCrypt et en utilisant ce code.
var cost = 16 ;
var timeTarget = 100 ; // Milliseconds
long timeTaken ;
do
{
var sw = Stopwatch . StartNew ( ) ;
BCrypt . HashPassword ( "RwiKnN>9xg3*C)1AZl.)y8f_:GCz,vt3T]PI" , workFactor : cost ) ;
sw . Stop ( ) ;
timeTaken = sw . ElapsedMilliseconds ;
cost -= 1 ;
} while ( ( timeTaken ) >= timeTarget ) ;
Console . WriteLine ( "Appropriate Cost Found: " + ( cost + 1 ) ) ;
Console . ReadLine ( ) ;
Cela commencera à 16, soit 65,536 iterations
, et réduira le coût jusqu'à ce que l'objectif de temps soit atteint. C'est à vous de décider ce que vous considérez comme un temps autorisé, mais s'il est inférieur à 10, je vous conseillerais sérieusement de le laisser à 10 et peut-être d'investir dans un package de serveur plus grand.
La limite de mot de passe recommandée de 56 octets (y compris l'octet de terminaison nul) pour bcrypt se rapporte à la limite de 448 bits de la clé Blowfish ; Tous les octets au-delà de cette limite ne sont pas entièrement mélangés dans le hachage, ce qui rend la limite absolue de 72 octets sur les mots de passe bcrypt moins pertinente compte tenu de l'effet réel de ces octets sur le hachage résultant.
D'autres langages ont traité ce problème perçu en pré-hachant la phrase secrète/le mot de passe pour augmenter l'entropie utilisée, Dropbox étant l'un des articles les plus publics à ce sujet.
Vous pouvez opter pour le hachage amélioré simplement en utilisant le code suivant (en préfixant essentiellement les appels de méthode avec Enhanced)
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword ) ;
Par défaut, la bibliothèque utilise le hachage SHA384 de la phrase secrète, le matériel généré est ensuite transmis à bcrypt pour former votre hachage via la routine bcrypt habituelle. Si vous souhaitez spécifier une version différente de SHA, ou souhaitez simplement définir explicitement dans votre code la version utilisée au cas où elle changerait dans une version majeure de la bibliothèque, vous pouvez le faire en utilisant la modification suivante par rapport à ce qui précède.
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword , hashType : HashType . SHA384 ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword , hashType : HashType . SHA384 ) ;
Pourquoi SHA384 ? C'est un bon équilibre entre performances, sécurité et protection contre les collisions et c'est la seule version qui n'était pas vulnérable aux attaques par extension de longueur https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash -longueur-extension-attaques .
Dois-je utiliser l’entropie améliorée ? Vous ne perdez rien à l'utiliser
Pourquoi devrais-je changer le type SHA ? Certaines bibliothèques comme le hachage PassLib utilisant SHA256, donc surtout une question de compatibilité. DropBox utilisait SHA512, donc si vous travailliez chez Dropbox, vous voudriez la compatibilité. L'amélioration est principalement une extension pratique dans la mesure où vous pouvez déjà pré-hacher et transmettre les appels de méthode standard.
Qu'est-ce que ça fait ? Nous prenons les octets utf8 de votre mot de passe comme inputBytes SHA les hachons, les convertissons en base64 (pour la compatibilité avec d'autres implémentations de langage), puis utilisons ces octets pour effectuer l'appel bcrypt standard.
Vous aurez besoin d'au moins VS2022 avec le SDK actuel https://www.microsoft.com/net/download ;
Les packages nuget peuvent être construits en exécutant buildfornuget.cmd
ou
dotnet restore . s rc
dotnet pack . s rc B Crypt.Net --configuration Release
Vous pouvez exécuter les tests à partir du dossier principal en tapant dotnet test .srcBCrypt.Net.UnitTests
L'exécution TestGenerateSaltWithMaxWorkFactor
prendra beaucoup de temps.
Un port .Net de jBCrypt implémenté en C#. Il utilise une variante du programme de chiffrement de l'algorithme de chiffrement Blowfish et introduit un facteur de travail qui vous permet de déterminer le coût de la fonction de hachage, permettant ainsi à l'algorithme d'être « évolutif ».
Il s'agit, à toutes fins utiles, d'un portage direct de jBCrypt écrit par Damien Miller. Les principales différences résident dans l'ajout de certaines méthodes pratiques et d'une légère refactorisation. Le moyen le plus simple de vérifier la parité de BCrypt.Net avec jBCrypt est de comparer les tests unitaires.
Pour un aperçu de l'importance de BCrypt, consultez Comment stocker un mot de passe en toute sécurité. En général, il s'agit d'un algorithme de hachage qui peut être ajusté au fil du temps pour nécessiter plus de puissance CPU pour générer les hachages. Ceci offre essentiellement une certaine protection contre la loi de Moore. Autrement dit, à mesure que les ordinateurs deviennent plus rapides, cet algorithme peut être ajusté pour nécessiter plus de puissance CPU. Plus il faut de puissance CPU pour hacher un mot de passe donné, plus un « hacker » doit investir de temps par mot de passe. Étant donné que le « facteur de travail » est intégré dans le hachage résultant, les hachages générés par cet algorithme sont compatibles vers l'avant/vers l'arrière.
Il utilise une variante du programme de chiffrement de l'algorithme de chiffrement Blowfish et introduit un facteur de travail, qui vous permet de déterminer le coût de la fonction de hachage. Pour cette raison, BCrypt peut suivre la loi de Moore. À mesure que les ordinateurs deviennent plus rapides, vous pouvez augmenter le facteur de travail et le hachage deviendra plus lent.
Niels Provos et David Mazières ont conçu un schéma crypt() appelé bcrypt basé sur Blowfish et l'ont présenté à USENIX en 1999.[14]
La forme imprimable de ces hachages commence par
$2$ – Currently obsolete
$2a$ – The current key used to identify this scheme.
Since a major security flaw was discovered in 2011 in a third-party implementation of the algorithm,
hashes indicated by this string are now ambiguous and might have been generated by the flawed
implementation, or a subsequent fixed, implementation.
The flaw may be triggered by some password strings containing non-ASCII characters, such as specially
crafted password strings.
$2b$ – Used by some recent implementations which include a mitigation to a wraparound problem.
Previous versions of the algorithm have a problem with long passwords. By design, long passwords
are truncated at 72 characters, but there is an 8-bit wraparound problem with certain password
lengths resulting in weak hashes.
$2x$ – Post-2011 bug discovery, old hashes can be renamed to be $2x$ to indicate that they were generated with
the broken algorithm. These hashes are still weak, but at least it's clear which algorithm was used to
generate them.
$2y$ – Post Post-2011 bug discovery, $2y$ may be used to unambiguously use the new, corrected algorithm. On an
implementation suffering from the bug, $2y$ simply won't work. On a newer, fixed implementation, it will
produce the same result as using $2a$.
Avant tout, cette bibliothèque est issue d'un portage de jBCrypt de mindrot
, et par la suite la révision de bcrypt a été définie pour correspondre, qui dans ce cas est $2a$
. Cela a été modifié car la gestion d'une seule révision entraîne des problèmes multiplateformes avec des implémentations qui ont modifié leur révision pour gérer les migrations et d'autres problèmes.
The original bcrypt code (released in OpenBSD 2.1) identified itself as
$2$. Shortly after release, a bug was fixed and the hash identifier
changed to $2a$. Support for "minor" versions wasn't really
planned, but it was backwards compatible.
Solar Designer wrote a second implementation of bcrypt. This
reimplementation suffered from a flaw dealing with 8 bit characters
and led to the introduction of the 'x' and 'y' flavours. OpenBSD did
not have this problem and supports neither 'x' nor 'y' hash versions.
---
Solar found a bug in their OpenBSD implementation of bcrypt when hashing
long passwords. The length is stored in an unsigned char type, which
will overflow and wrap at 256. Although we consider the existence of
affected hashes very rare, in order to differentiate hashes generated
before and after the fix, we are introducing a new minor 'b'.
OpenBSD 5.5 (coming this spring) will accept and verify 'b' hashes,
although it will still generate 'a' hashes. OpenBSD 5.6 (coming this
fall) will change to generating 'b' hashes by default.
A future release of Solar's bcrypt code should also support 'b'.
Il n'y a aucune différence entre 2a, 2x, 2y et 2b. Ils produisent tous le même résultat.
les notes de version sont ici https://github.com/BcryptNet/bcrypt.net/releases
v4.0.3 - Ajout du ciblage .net 6 ; ranger les cibles.
v4.0.2 - Ajout du ciblage .net 5 ; enveloppez la création shaxxx
dans using to release.
v4.0.0 (modifications révolutionnaires) - Un bug dans Enhanced Hashing
a été découvert, ce qui rend les hachages créés inutilisables entre différentes langues. La V4 fournit le correctif pour cela ainsi que l'ajout de vecteurs de test de PHP et Python pour garantir que le problème reste résolu à l'avenir. La V4 supprime également l'ancienne option 384 qui précédait l'ajout de Base64.
v3.5.0 - Un bug dans Enhanced Hashing
a été découvert, ce qui rend les hachages créés inutilisables entre différentes langues. Dans le cadre de la version 3.5 du correctif, la possibilité de Verify
et HashPassword
a reçu un paramètre v4CompatibleEnhancedEntropy
supplémentaire. Cela permet à l'utilisateur de vérifier son hachage amélioré comme d'habitude ; puis re-hachez + stockez en utilisant la V4. Cette fonctionnalité sert uniquement à permettre la migration et est supprimée dans la V4.
v3.3.3 -Performance (réduction du tas) pour netcore et suppression des regex https://github.com/BcryptNet/bcrypt.net/releases/tag/3.3.0
v2.1.3 -
v2.1.2 -
PasswordNeedsReshash
en PasswordNeedsRehash
v2.1.1 -
v2.1.0 -
PasswordNeedsReshash(string hash, int newMinimumWorkLoad)
comme méthode d'assistance que les développeurs peuvent utiliser lors de la connexion d'un utilisateur afin d'augmenter les charges de travail héritées.ValidateAndReplacePassword
pour permettre la validation et le remplacement du mot de passe en ligne. Lève BcryptAuthenticationException
en cas d’échec d’authentification.v2.0.1 -
v2.0.0 -
Nouvelle version packagée pour la majorité de .net et contenant des égaux sûrs pour réduire les risques d'attaques temporelles https://en.wikipedia.org/wiki/Timing_attack / https://cryptocoding.net/index.php/Coding_rules#Compare_secret_strings_in_constant_time Techniquement, les détails de mise en œuvre de BCrypt atténuent théoriquement les attaques temporelles. Mais la fonction de validation officielle de Bcrypt.net était vulnérable aux attaques de synchronisation car elle revenait dès qu'un octet ne correspondant pas était trouvé dans la comparaison de hachage.