Skip to content

Instantly share code, notes, and snippets.

@smonn
Last active December 14, 2015 00:59

Revisions

  1. smonn revised this gist Mar 13, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion encrypt.md
    Original file line number Diff line number Diff line change
    @@ -2,4 +2,4 @@

    [This answer on Stack Overflow](http://stackoverflow.com/questions/472906/net-string-to-byte-array-c-sharp#answer-10380166).

    [Small library implementing this](https://github.com/parsley/encryptor)
    [Small library implementing this](https://github.com/smonn/encryptor)
  2. smonn renamed this gist Feb 21, 2013. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion credits.md → encrypt.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    [Salted Password Hashing - Doing it Right](http://crackstation.net/hashing-security.htm)

    [This answer on Stack Overflow](http://stackoverflow.com/questions/472906/net-string-to-byte-array-c-sharp#answer-10380166).
    [This answer on Stack Overflow](http://stackoverflow.com/questions/472906/net-string-to-byte-array-c-sharp#answer-10380166).

    [Small library implementing this](https://github.com/parsley/encryptor)
  3. smonn revised this gist Feb 21, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion encrypt.cs
    Original file line number Diff line number Diff line change
    @@ -49,7 +49,7 @@
    // This is done by comparing the entire array:

    var a = bytes;
    var b = bytes;
    var b = bytes; // This should obivously be generated from a login attempt.

    uint diff = (uint)a.Length ^ (uint)b.Length;
    for (int i = 0; i < a.Length && i < b.Length; i++)
  4. smonn revised this gist Feb 21, 2013. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion encrypt.cs
    Original file line number Diff line number Diff line change
    @@ -45,7 +45,8 @@
    // we can convert it back to a byte array easily):
    var base64 = Convert.ToBase64String(bytes);

    // When comparing two byte arrays it is suggested to use a slow equals, comparing the entire array:
    // When comparing two byte arrays it is suggested to use a slow equals.
    // This is done by comparing the entire array:

    var a = bytes;
    var b = bytes;
  5. smonn revised this gist Feb 21, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion encrypt.cs
    Original file line number Diff line number Diff line change
    @@ -45,7 +45,7 @@
    // we can convert it back to a byte array easily):
    var base64 = Convert.ToBase64String(bytes);

    // When comparing two byte arrays, it is suggested to use a slow equals, comparing the entire array:
    // When comparing two byte arrays it is suggested to use a slow equals, comparing the entire array:

    var a = bytes;
    var b = bytes;
  6. smonn revised this gist Feb 21, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions encrypt.cs
    Original file line number Diff line number Diff line change
    @@ -41,8 +41,8 @@
    // A simple way to calculate the hexadecimal string, however, would be to use something like this:
    var hex = new string(bytes.SelectMany(x => x.ToString(@"X2").ToCharArray()).ToArray());

    // Another option would be to use Convert.ToBase64String (a benefit with this approach is that we can convert it
    // back to a byte array easily):
    // Another option would be to use Convert.ToBase64String (a benefit with this approach is that
    // we can convert it back to a byte array easily):
    var base64 = Convert.ToBase64String(bytes);

    // When comparing two byte arrays, it is suggested to use a slow equals, comparing the entire array:
  7. smonn revised this gist Feb 21, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion encrypt.cs
    Original file line number Diff line number Diff line change
    @@ -41,7 +41,7 @@
    // A simple way to calculate the hexadecimal string, however, would be to use something like this:
    var hex = new string(bytes.SelectMany(x => x.ToString(@"X2").ToCharArray()).ToArray());

    // Another option would be to use Base64 (a benefit with this approach is that we can convert it
    // Another option would be to use Convert.ToBase64String (a benefit with this approach is that we can convert it
    // back to a byte array easily):
    var base64 = Convert.ToBase64String(bytes);

  8. smonn revised this gist Feb 21, 2013. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions credits.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    [Salted Password Hashing - Doing it Right](http://crackstation.net/hashing-security.htm)

    [This answer on Stack Overflow](http://stackoverflow.com/questions/472906/net-string-to-byte-array-c-sharp#answer-10380166).
  9. smonn renamed this gist Feb 21, 2013. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  10. smonn revised this gist Feb 21, 2013. 1 changed file with 19 additions and 0 deletions.
    19 changes: 19 additions & 0 deletions sample.cs
    Original file line number Diff line number Diff line change
    @@ -40,3 +40,22 @@
    // to a hexadecimal string and store that in the database (or worse, using Encoding.XXX.GetString).
    // A simple way to calculate the hexadecimal string, however, would be to use something like this:
    var hex = new string(bytes.SelectMany(x => x.ToString(@"X2").ToCharArray()).ToArray());

    // Another option would be to use Base64 (a benefit with this approach is that we can convert it
    // back to a byte array easily):
    var base64 = Convert.ToBase64String(bytes);

    // When comparing two byte arrays, it is suggested to use a slow equals, comparing the entire array:

    var a = bytes;
    var b = bytes;

    uint diff = (uint)a.Length ^ (uint)b.Length;
    for (int i = 0; i < a.Length && i < b.Length; i++)
    diff |= (uint)(a[i] ^ b[i]);

    if (diff == 0)
    Console.WriteLine("The passwords match!");
    else
    Console.WriteLine("Wrong password");

  11. smonn renamed this gist Feb 21, 2013. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  12. smonn revised this gist Feb 21, 2013. No changes.
  13. smonn revised this gist Feb 21, 2013. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions gistfile1.cs
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,11 @@
    /*
    using System;
    using System.Linq;
    using System.Security.Cryptography;
    */

    // The user's password in pure text.
    var password = string.Empty;

  14. smonn revised this gist Feb 21, 2013. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion gistfile1.cs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    // The user's password in pure text.
    var password = string.Empty;

  15. smonn created this gist Feb 21, 2013.
    35 changes: 35 additions & 0 deletions gistfile1.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,35 @@

    // The user's password in pure text.
    var password = string.Empty;

    // Generate a random salt, this should be stored in its own column in the database,
    // preferably in a binary format (i.e. binary(32) in this case, adjust length accordingly).
    // The salt should be at least as long as the generated hash, for SHA256 that is 32 bytes.
    var rng = new RNGCryptoServiceProvider();
    var salt = new byte[32];

    // Basically, this will fill the salt array with random bytes.
    rng.GetBytes(salt);

    // Use at least SHA256 since SHA1 is very weak in comparison.
    var sha256 = new SHA256CryptoServiceProvider();

    // We don't care about encoding in this scenario, and using Buffer.BlockCopy saves
    // us a tiny bit of memory and time over Encoding.XXX.GetBytes.
    var passwordBytes = new byte[password.Length * sizeof(char)];
    Buffer.BlockCopy(password.ToCharArray(), 0, passwordBytes, 0, passwordBytes.Length);

    // Compute the password hash (this step is kind of optional, but the more we
    // hash the more difficult it will be for attackers).
    var hash = sha256.ComputeHash(passwordBytes);

    // Prepend the salt and hash it all one more time. Mandatory step.
    var bytes = sha256.ComputeHash(salt.Concat(hash).ToArray());

    // What we have in the bytes variable should now be stored in the database in its own column.
    // Just like the salt, store it in binary format.

    // The reason for storing in binary format is basically to save us from having to convert the hash
    // to a hexadecimal string and store that in the database (or worse, using Encoding.XXX.GetString).
    // A simple way to calculate the hexadecimal string, however, would be to use something like this:
    var hex = new string(bytes.SelectMany(x => x.ToString(@"X2").ToCharArray()).ToArray());