Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here is a full implementation of a persistence unaware SecuredPassword class</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; public class SecuredPassword { private const int saltSize = 256; private readonly byte[] hash; private readonly byte[] salt; public byte[] Hash { get { return hash; } } public byte[] Salt { get { return salt; } } public SecuredPassword(string plainPassword) { if (string.IsNullOrWhiteSpace(plainPassword)) return; using (var deriveBytes = new Rfc2898DeriveBytes(plainPassword, saltSize)) { salt = deriveBytes.Salt; hash = deriveBytes.GetBytes(saltSize); } } public SecuredPassword(byte[] hash, byte[] salt) { this.hash = hash; this.salt = salt; } public bool Verify(string password) { if (string.IsNullOrWhiteSpace(password)) return false; using (var deriveBytes = new Rfc2898DeriveBytes(password, salt)) { byte[] newKey = deriveBytes.GetBytes(saltSize); return newKey.SequenceEqual(hash); } } } </code></pre> <p>And tests:</p> <pre><code> public class SecuredPasswordTests { [Test] public void IsHashed_AsExpected() { var securedPassword = new SecuredPassword("password"); Assert.That(securedPassword.Hash, Is.Not.EqualTo("password")); Assert.That(securedPassword.Hash.Length, Is.EqualTo(256)); } [Test] public void Generates_Unique_Salt() { var securedPassword = new SecuredPassword("password"); var securedPassword2 = new SecuredPassword("password"); Assert.That(securedPassword.Salt, Is.Not.Null); Assert.That(securedPassword2.Salt, Is.Not.Null); Assert.That(securedPassword.Salt, Is.Not.EqualTo(securedPassword2.Salt)); } [Test] public void Generates_Unique_Hash() { var securedPassword = new SecuredPassword("password"); var securedPassword2 = new SecuredPassword("password"); Assert.That(securedPassword.Hash, Is.Not.Null); Assert.That(securedPassword2.Hash, Is.Not.Null); Assert.That(securedPassword.Hash, Is.Not.EqualTo(securedPassword2.Hash)); } [Test] public void Verify_WhenMatching_ReturnsTrue() { var securedPassword = new SecuredPassword("password"); var result = securedPassword.Verify("password"); Assert.That(result, Is.True); } [Test] public void Verify_WhenDifferent_ReturnsFalse() { var securedPassword = new SecuredPassword("password"); var result = securedPassword.Verify("Password"); Assert.That(result, Is.False); } [Test] public void Verify_WhenRehydrated_AndMatching_ReturnsTrue() { var securedPassword = new SecuredPassword("password123"); var rehydrated = new SecuredPassword(securedPassword.Hash, securedPassword.Salt); var result = rehydrated.Verify("password123"); Assert.That(result, Is.True); } [Test] public void Constructor_Handles_Null_Password() { Assert.DoesNotThrow(() =&gt; new SecuredPassword(null)); } [Test] public void Constructor_Handles_Empty_Password() { Assert.DoesNotThrow(() =&gt; new SecuredPassword(string.Empty)); } [Test] public void Verify_Handles_Null_Password() { Assert.DoesNotThrow(() =&gt; new SecuredPassword("password").Verify(null)); } [Test] public void Verify_Handles_Empty_Password() { Assert.DoesNotThrow(() =&gt; new SecuredPassword("password").Verify(string.Empty)); } [Test] public void Verify_When_Null_Password_ReturnsFalse() { Assert.That(new SecuredPassword("password").Verify(null), Is.False); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload