BCrypt.Net-Next 4.2.0

dotnet add package BCrypt.Net-Next --version 4.2.0
                    
NuGet\Install-Package BCrypt.Net-Next -Version 4.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BCrypt.Net-Next" Version="4.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BCrypt.Net-Next" Version="4.2.0" />
                    
Directory.Packages.props
<PackageReference Include="BCrypt.Net-Next" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BCrypt.Net-Next --version 4.2.0
                    
#r "nuget: BCrypt.Net-Next, 4.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BCrypt.Net-Next@4.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BCrypt.Net-Next&version=4.2.0
                    
Install as a Cake Addin
#tool nuget:?package=BCrypt.Net-Next&version=4.2.0
                    
Install as a Cake Tool

SWUbanner

bcrypt.net - next

Porting of bcrypt.codeplex.com with enhanced security, missing fixes, features and better .net support.

Build status

Nuget

Download using nuget or Paket (https://fsprojects.github.io/Paket/)

Package: https://www.nuget.org/packages/BCrypt.Net-Next/ NuGet

Signed Package - https://www.nuget.org/packages/BCrypt.Net-Next.StrongName/ NuGet Signed Package

How to use

There are various examples in our test-harness folder and unit-tests

The simplest usage is as follows...

To Hash a password:

DotNet5+

File-scoped namespaces are shown; imagine curly brackets if you need to.

Top level namespace

namespace DotNetSix;

using BCrypt.Net;

string passwordHash =  BCrypt.HashPassword("my password");

DotNet4/6 etc

Due to the naming of the library if the namespace is after the using statements the call changes as .net fails to resolve naming correctly I'd advise rather than enter the entire namespace you simply use the import aliasing as below.


using BC = BCrypt.Net.BCrypt;

namespace DotNetTen;

string passwordHash =  BC.HashPassword("my password");

DotNetSix

You can also do aliasing at the CSProj level; and wouldn't need to add the using statement at all

This example would allow you to use an alias BC.HashPassword() in your code

    <ItemGroup>
        
        <Using Include="BCrypt.Net.BCrypt" Alias="BC"/>
    </ItemGroup>

This version would allow you to just call Verify and HashPassword in your code base without any other reference.

    <ItemGroup>
        
        <Using Include="BCrypt.Net.BCrypt" Static="True"/>
    </ItemGroup>

Note: Although this library allows you to supply your own salt, it is highly advisable that you allow the library to generate the salt for you. These methods are supplied to maintain compatibility and for more advanced cross-platform requirements that may necessitate their use.

To Verify a password against a hash (assuming you've stored the hash and retrieved from storage for verification):

All previous notes about namespacing apply here too

BCrypt.Verify("my password", passwordHash);

This implementation on hashing will generate a salt automatically for you with the work factor (2^number of rounds) set to 11 (which matches the default across most implementation and is currently viewed as a good level of security/risk).

To save you the maths a small table covering the iterations is provided below. The minimum allowed in this library is 4 for compatibility, the maximum is 31 (at 31 your processor will be wishing for death).

| 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

and a simple benchmark you can run by creating a console program, adding this BCrypt Library and using this 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();

This will start at 16 which is 65,536 iterations and reduce the cost until the time target is reached. It's up to you what you consider an allowable time, but if it's below 10, I'd seriously advice leaving it at 10 and maybe investing in a larger server package.

Enhanced Entropy

The recommended 56 byte password limit (including null termination byte) for bcrypt relates to the 448 bit limit of the Blowfish key; Any bytes beyond that limit are not fully mixed into the hash, as such making the 72 byte absolute limit on bcrypt passwords less relevant considering what actual effect on the resulting hash by those bytes.

Other languages have handled this perceived issue by pre-hashing the passphrase/password to increase the used entropy, dropbox being one of the more public articles on this.