Portierung von bcrypt.codeplex.com mit erhöhter Sicherheit, fehlenden Korrekturen, Funktionen und besserer .net-Unterstützung.
Herunterladen mit Nuget oder Paket (https://fsprojects.github.io/Paket/)
Paket: https://www.nuget.org/packages/BCrypt.Net-Next/
Signiertes Paket – https://www.nuget.org/packages/BCrypt.Net-Next.StrongName/
Es gibt verschiedene Beispiele in unserem Test-Harness-Ordner und Unit-Tests
Die einfachste Verwendung ist wie folgt...
So hashen Sie ein Passwort:
Es werden dateibezogene Namespaces angezeigt. Stellen Sie sich bei Bedarf geschweifte Klammern vor.
Top level namespace
namespace DotNetSix ;
using BCrypt . Net ;
string passwordHash = BCrypt . HashPassword ( "my password" ) ;
Wenn sich der Namespace aufgrund der Benennung der Bibliothek nach den using-Anweisungen befindet, ändert sich der Aufruf, da .net die Benennung nicht korrekt auflösen kann. Ich würde Ihnen raten, statt den gesamten Namespace einzugeben, einfach das Import-Aliasing wie unten beschrieben zu verwenden.
using BC = BCrypt . Net . BCrypt ;
namespace DotNetSix ;
string passwordHash = BC . HashPassword ( "my password" ) ;
Sie können Aliasing auch auf CSProj-Ebene durchführen; und müsste die using-Anweisung überhaupt nicht hinzufügen
Dieses Beispiel würde es Ihnen ermöglichen, einen Alias BC.HashPassword() in Ihrem Code zu verwenden
< ItemGroup >
<!-- emits global using BcryptNet = global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Alias = " BC " />
</ ItemGroup >
Mit dieser Version können Sie ohne weitere Referenz einfach Verify
und HashPassword
in Ihrer Codebasis aufrufen.
< ItemGroup >
<!-- emits global using static global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Static = " True " />
</ ItemGroup >
Hinweis: Obwohl Sie mit dieser Bibliothek Ihr eigenes Salz bereitstellen können, ist es sehr empfehlenswert, dass Sie der Bibliothek erlauben, das Salz für Sie zu generieren. Diese Methoden werden zur Aufrechterhaltung der Kompatibilität und für erweiterte plattformübergreifende Anforderungen bereitgestellt, die ihre Verwendung möglicherweise erforderlich machen.
So überprüfen Sie ein Passwort anhand eines Hashs (vorausgesetzt, Sie haben den Hash gespeichert und zur Überprüfung aus dem Speicher abgerufen):
Auch hier gelten alle bisherigen Hinweise zum Namensraum
BCrypt . Verify ( "my password" , passwordHash ) ;
Diese Hashing-Implementierung generiert automatisch einen Salt für Sie, wobei der Arbeitsfaktor (2^Anzahl der Runden) auf 11 eingestellt ist (was der Standardeinstellung bei den meisten Implementierungen entspricht und derzeit als gutes Sicherheits-/Risikoniveau angesehen wird).
Um Ihnen die Mathematik zu ersparen, finden Sie unten eine kleine Tabelle mit den Iterationen. Der in dieser Bibliothek zulässige Mindestwert beträgt aus Kompatibilitätsgründen 4, der Höchstwert 31 (bei 31 wird sich Ihr Prozessor den Tod wünschen).
| 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
und einen einfachen Benchmark, den Sie ausführen können, indem Sie ein Konsolenprogramm erstellen, diese BCrypt-Bibliothek hinzufügen und diesen Code verwenden.
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 ( ) ;
Dies beginnt bei 16, was 65,536 iterations
entspricht, und reduziert die Kosten, bis das Zeitziel erreicht ist. Es liegt an Ihnen, was Sie als zulässige Zeit betrachten, aber wenn sie unter 10 liegt, würde ich Ihnen ernsthaft raten, sie bei 10 zu belassen und vielleicht in ein größeres Serverpaket zu investieren.
Das empfohlene Passwortlimit von 56 Byte (einschließlich Nullterminierungsbyte) für bcrypt bezieht sich auf das 448-Bit-Limit des Blowfish-Schlüssels; Alle über diese Grenze hinausgehenden Bytes werden nicht vollständig in den Hash eingemischt, sodass die absolute Grenze von 72 Byte für Bcrypt-Passwörter weniger relevant ist, wenn man bedenkt, welche tatsächliche Auswirkung diese Bytes auf den resultierenden Hash haben.
Andere Sprachen haben dieses vermeintliche Problem gelöst, indem sie die Passphrase/das Passwort vorab gehasht haben, um die verwendete Entropie zu erhöhen. Dropbox ist einer der öffentlicheren Artikel zu diesem Thema.
Sie können sich für erweitertes Hashing entscheiden, indem Sie einfach den folgenden Code verwenden (den Methodenaufrufen grundsätzlich „Erweitert“ voranstellen).
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword ) ;
Standardmäßig verwendet die Bibliothek SHA384-Hashing der Passphrase. Das generierte Material wird dann an bcrypt übergeben, um über die übliche bcrypt-Routine Ihren Hash zu bilden. Wenn Sie eine andere Version von SHA angeben möchten oder einfach in Ihrem Code explizit die verwendete Version festlegen möchten, für den Fall, dass sie sich jemals in einer Hauptversion der Bibliothek ändert, können Sie dies tun, indem Sie die folgende Änderung an den oben genannten vornehmen.
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword , hashType : HashType . SHA384 ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword , hashType : HashType . SHA384 ) ;
Warum SHA384? Es bietet ein gutes Gleichgewicht zwischen Leistung, Sicherheit und Kollisionsschutz und ist die einzige Version, die nicht anfällig für Längenerweiterungsangriffe ist https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash -length-extension-attacks .
Sollte ich Enhanced Entropy verwenden? Sie verlieren nichts, wenn Sie es verwenden
Warum sollte ich den SHA-Typ ändern müssen? Einige Bibliotheken wie PassLib hashen mit SHA256, also hauptsächlich aus Kompatibilitätsgründen. DropBox verwendet SHA512. Wenn Sie also bei Dropbox arbeiten, möchten Sie Kompatibilität. Bei der Erweiterung handelt es sich größtenteils um eine praktische Erweiterung, da Sie bereits einen Vorab-Hash durchführen und an die Standardmethodenaufrufe übergeben können.
Was macht es? Wir nehmen die utf8-Bytes Ihres Passworts als Eingabebytes, hashen sie mit SHA, konvertieren sie in Base64 (zur Kompatibilität mit anderen Sprachimplementierungen) und verwenden diese Bytes dann, um den Standard-Bcrypt-Aufruf durchzuführen.
Sie benötigen mindestens VS2022 mit dem aktuellen SDK https://www.microsoft.com/net/download;
Die Nuget-Pakete können durch Ausführen von buildfornuget.cmd
oder erstellt werden
dotnet restore . s rc
dotnet pack . s rc B Crypt.Net --configuration Release
Sie können die Tests im Hauptordner ausführen, indem dotnet test .srcBCrypt.Net.UnitTests
eingeben. Das Ausführen TestGenerateSaltWithMaxWorkFactor
nimmt viel Zeit in Anspruch.
Ein .Net-Port von jBCrypt, implementiert in C#. Es verwendet eine Variante des Schlüsselplans des Blowfish-Verschlüsselungsalgorithmus und führt einen Arbeitsfaktor ein, mit dem Sie bestimmen können, wie teuer die Hash-Funktion sein wird, sodass der Algorithmus „zukunftssicher“ ist.
Dies ist im Grunde eine direkte Portierung von jBCrypt, geschrieben von Damien Miller. Die Hauptunterschiede bestehen in der Hinzufügung einiger praktischer Methoden und einer geringfügigen Umgestaltung. Der einfachste Weg, die Parität von BCrypt.Net mit jBCrypt zu überprüfen, ist der Vergleich der Unit-Tests.
Einen Überblick darüber, warum BCrypt wichtig ist, finden Sie unter So speichern Sie ein Passwort sicher. Im Allgemeinen handelt es sich um einen Hashing-Algorithmus, der im Laufe der Zeit angepasst werden kann, um mehr CPU-Leistung zum Generieren der Hashes zu benötigen. Dies bietet im Wesentlichen einen gewissen Schutz vor dem Mooreschen Gesetz. Das heißt, wenn Computer schneller werden, kann dieser Algorithmus angepasst werden, um mehr CPU-Leistung zu benötigen. Je mehr CPU-Leistung erforderlich ist, um ein bestimmtes Passwort zu hashen, desto mehr Zeit muss ein „Hacker“ pro Passwort investieren. Da der „Arbeitsfaktor“ in den resultierenden Hash eingebettet ist, sind die von diesem Algorithmus generierten Hashes vorwärts-/rückwärtskompatibel.
Es verwendet eine Variante des Schlüsselplans des Blowfish-Verschlüsselungsalgorithmus und führt einen Arbeitsfaktor ein, mit dem Sie bestimmen können, wie teuer die Hash-Funktion sein wird. Aus diesem Grund kann BCrypt mit dem Mooreschen Gesetz Schritt halten. Wenn Computer schneller werden, können Sie den Arbeitsfaktor erhöhen und der Hash wird langsamer.
Niels Provos und David Mazières entwarfen ein auf Blowfish basierendes crypt()-Schema namens bcrypt und stellten es 1999 auf der USENIX vor.[14]
Die druckbare Form dieser Hashes beginnt mit
$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$.
In erster Linie entstand diese Bibliothek als Port von jBCrypt von mindrot
, und anschließend wurde die bcrypt-Revision entsprechend eingestellt, in diesem Fall $2a$
. Dies wurde geändert, da die Handhabung nur der einzelnen Revision plattformübergreifend Probleme mit Implementierungen verursacht, deren Revision geändert wurde, um Migrationen und andere Probleme zu bewältigen.
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'.
Es gibt keinen Unterschied zwischen 2a, 2x, 2y und 2b. Sie alle geben das gleiche Ergebnis aus.
Versionshinweise finden Sie hier: https://github.com/BcryptNet/bcrypt.net/releases
v4.0.3 – Hinzufügung von .net 6-Targeting; Ziele aufräumen.
v4.0.2 – Hinzufügung von .net 5-Targeting; Wickeln Sie shaxxx
Erstellung ein, um sie freizugeben.
v4.0.0 (wichtige Änderungen) – Es wurde ein Fehler im Enhanced Hashing
entdeckt, der dazu führt, dass die erstellten Hashes zwischen verschiedenen Sprachen nicht funktionsfähig sind. V4 bietet die Lösung hierfür und fügt Testvektoren von PHP und Python hinzu, um sicherzustellen, dass das Problem auch in Zukunft behoben bleibt. V4 entfernt außerdem die alte 384-Option, die vor der Hinzufügung von Base64 verfügbar war.
v3.5.0 – Es wurde ein Fehler im Enhanced Hashing
entdeckt, der dazu führt, dass die erstellten Hashes zwischen verschiedenen Sprachen nicht funktionsfähig sind. Als Teil des Fixes enthält die Version 3.5 die Möglichkeit, Verify
und HashPassword
mit einem zusätzlichen v4CompatibleEnhancedEntropy
-Parameter zu versehen. Dadurch kann der Benutzer seinen erweiterten Hash wie gewohnt überprüfen. dann erneut hashen und mit V4 speichern. Diese Funktionalität dient lediglich der Migration und wird in V4 entfernt.
v3.3.3 – Leistung (Heap-Reduktion) für Netcore und Entfernung von Regex https://github.com/BcryptNet/bcrypt.net/releases/tag/3.3.0
v2.1.3 -
v2.1.2 -
PasswordNeedsReshash
in PasswordNeedsRehash
v2.1.1 -
v2.1.0 -
PasswordNeedsReshash(string hash, int newMinimumWorkLoad)
als Hilfsmethode hinzu, die Entwickler beim Anmelden eines Benutzers verwenden können, um die Legacy-Arbeitslast zu erhöhenValidateAndReplacePassword
-Methode hinzu, um die Inline-Passwortvalidierung und -Ersetzung zu ermöglichen. Löst BcryptAuthenticationException
aus, wenn die Authentifizierung fehlschlägt.v2.0.1 -
v2.0.0 -
Neue Version, verpackt für die meisten .net-Anwendungen und mit Safe-Equals, um die Risiken von Timing-Angriffen zu reduzieren https://en.wikipedia.org/wiki/Timing_attack / https://cryptocoding.net/index.php/Coding_rules#Compare_secret_strings_in_constant_time Technisch gesehen schützen die Implementierungsdetails von BCrypt theoretisch vor Timing-Angriffen. Die offizielle Validierungsfunktion von Bcrypt.net war jedoch anfällig für Timing-Angriffe, da sie zurückkehrte, sobald im Hash-Vergleich ein nicht übereinstimmendes Byte gefunden wurde.