== How to fix it in BouncyCastle

=== Code examples

==== Noncompliant code example

Using SCrypt:
[source,csharp,diff-id=301,diff-type=noncompliant]
----
using Org.BouncyCastle.Crypto.Generators;

string password = Request.Query["password"];
byte[] salt = RandomNumberGenerator.GetBytes(128 / 8); // divide by 8 to convert bits to bytes

string hashed = Convert.ToBase64String(SCrypt.Generate(Encoding.Unicode.GetBytes(password), salt, 4, 2, 1, 32));  // Noncompliant    
----

Using BCrypt:
[source,csharp,diff-id=302,diff-type=noncompliant]
----
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;

string password = Request.Query["password"];
byte[] salt = RandomNumberGenerator.GetBytes(128 / 8);

string hashed = OpenBsdBCrypt.Generate(password.ToCharArray(), salt, 4); // Noncompliant
----

Using PBKDF2:
[source,csharp,diff-id=303,diff-type=noncompliant]
----
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using System.Security.Cryptography;

string password = Request.Query["password"];
byte[] salt = RandomNumberGenerator.GetBytes(128 / 8);
Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator();
gen.Init(Encoding.Unicode.GetBytes(password), salt, 100);  // Noncompliant
KeyParameter keyParam = (KeyParameter) gen.GenerateDerivedMacParameters(256);
string hashed = Convert.ToBase64String(keyParam.GetKey());
----

==== Compliant solution

Using SCrypt:
[source,csharp,diff-id=301,diff-type=compliant]
----
using Org.BouncyCastle.Crypto.Generators;

string password = Request.Query["password"];
byte[] salt = RandomNumberGenerator.GetBytes(128 / 8); // divide by 8 to convert bits to bytes

string hashed = Convert.ToBase64String(SCrypt.Generate(Encoding.Unicode.GetBytes(password), salt, 1<<12, 8, 1, 32));  // Noncompliant    
----

Using BCrypt:
[source,csharp,diff-id=302,diff-type=compliant]
----
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;

string password = Request.Query["password"];
byte[] salt = RandomNumberGenerator.GetBytes(128 / 8);

string hashed = OpenBsdBCrypt.Generate(password.ToCharArray(), salt, 14); // Noncompliant
----

Using PBKDF2:
[source,csharp,diff-id=303,diff-type=compliant]
----
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using System.Security.Cryptography;

string password = Request.Query["password"];
byte[] salt = RandomNumberGenerator.GetBytes(128 / 8);
Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator();
gen.Init(Encoding.Unicode.GetBytes(password), salt, 100_000);  // Noncompliant
KeyParameter keyParam = (KeyParameter) gen.GenerateDerivedMacParameters(256);
string hashed = Convert.ToBase64String(keyParam.GetKey());
----

=== How does this work?

include::../../common/fix/bcrypt-parameters.adoc[]

include::../../common/fix/scrypt-parameters.adoc[]

include::../../common/fix/pbkdf2-parameters.adoc[]

=== Going the extra mile

include::../../common/extra-mile/peppering.adoc[]

