97 lines
2.9 KiB
Plaintext
97 lines
2.9 KiB
Plaintext
== 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[]
|
|
|