Writing Extended ASCII codes with BinaryWriter in .Net

by martin 12. October 2011 16:10
Ok, so this seems simple enough, but it took me a bit of Googling to figure out that I needed to pass the magic number 1252 to the GetEncoding method to get this to work correctly.  ASCIIEncoding only encodes values from 0 to 127 correctly, but values 128 to 255 do not get written out properly.  1252 refers to the Window Code Page for the Latin Alphabet for Western languages, and is sometimes incorrectly referred to as ANSI.  Hopefully this will save someone else some time searching for the solution.....
 
Code Snippet
  1. String strEscapeCode = new String('\xC4', 5);
  2.  
  3. using (FileStream stream = new FileStream("TestFile.bin", FileMode.Create))
  4. {              
  5.     using (BinaryWriter writer = new BinaryWriter(stream, Encoding.GetEncoding(1252)))
  6.     {
  7.         writer.Write(strEscapeCode.ToCharArray());
  8.         writer.Close();
  9.     }
  10. }

Currently rated 2.7 by 6 people

  • Currently 2.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

C#

Using Secure Hashing safely in .Net

by martin 5. October 2011 22:41

SHA 1 and SHA 256 are both great hashing algorithms, but both are susceptible to a Rainbow Table attack and with Moore's law and the great race by Google, Bing, and other search engines to index absolutely every bit of data out there on the internet, the chances of these attack succeeding grows every day.  As a developer fending off this kind of vector, it is considered a best practice to not only always salt your data before hashing it, but to always make sure that the salt is completely random in nature.  Additionally, since both SHA 1 and SHA 256 are Big - O(n) algorithms as far as performance cost is concerned and relatively inexpensive to execute on modern hardware, it is also a good idea to have multiple iterative calls to the hashing algorithm to come up with the hash.  And while we are at it, we might as well switch up between using both algorithms just in case one has a yet undiscovered flaw similar to that which was discovered with MD-5 or even SHA-0 before that.  Below is a C# implementation of a secure hash helper class to help you do all this.  It provides a way to create a hash from a value and to confirm that a hash was made from a given value.  It currently does additional Base64 encoding/decoding of the hash value for ease of use in web applications (tamper proofing forms against request forgery, storing password hashes, etc), but this can easily be removed if you'd prefer to deal in raw byte arrays.

 
Code Snippet
  1. using System;
  2. using System.Security.Cryptography;
  3.  
  4. namespace SecureHashTestConsole
  5. {
  6.     public static class SecureHashHelper
  7.     {
  8.         // set this to a relatively small number that you like.  (4 to 25 suggested range)  Larger number = longer random hash
  9.         private const int defaultNumBytesForSeed = 9;
  10.  
  11.         // set this to a decent number, not too low, not to high (5 to 1000 suggested range)  Larger number = slower performance but less likely rainbow table cracking possibility
  12.         private const int defaultIterations = 88;     
  13.  
  14.         public static bool CompareSecureHash(string TestHash, string TestValue, int numRandBytesForSeed = defaultNumBytesForSeed, int iterations = defaultIterations)
  15.         {
  16.             byte[] hashArray = Convert.FromBase64String(TestHash);
  17.             byte[] derivedSalt = new byte[numRandBytesForSeed];
  18.             Buffer.BlockCopy(hashArray, 0, derivedSalt, 0, numRandBytesForSeed);
  19.             string strComp = CreateSecureHash(TestValue, derivedSalt, iterations);
  20.             return strComp.Equals(TestHash);
  21.         }
  22.  
  23.         public static string CreateSecureHash(byte[] sbuffer, int numRandBytesForSeed = defaultNumBytesForSeed, int iterations = defaultIterations)
  24.         {
  25.             RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
  26.             byte[] randSalt = new byte[numRandBytesForSeed];
  27.             rand.GetBytes(randSalt);
  28.             return CreateSecureHash(randSalt, sbuffer, iterations);
  29.         }
  30.  
  31.         public static string CreateSecureHash(string ValueToHash, int numRandBytesForSeed = defaultNumBytesForSeed, int iterations = defaultIterations)
  32.         {
  33.             RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
  34.             byte[] randSalt = new byte[numRandBytesForSeed];
  35.             rand.GetBytes(randSalt);
  36.             System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
  37.             Byte[] bytes = encoding.GetBytes(ValueToHash);
  38.             return CreateSecureHash(randSalt, bytes, iterations);
  39.         }
  40.  
  41.         private static string CreateSecureHash(string ValueToHash, byte[] randSalt, int iterations = defaultIterations)
  42.         {
  43.             System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
  44.             Byte[] bytes = encoding.GetBytes(ValueToHash);
  45.             return CreateSecureHash(randSalt, bytes, iterations);
  46.         }
  47.         private static string CreateSecureHash(byte[] randSalt, byte[] sbuffer, int iterations = defaultIterations)
  48.         {
  49.             SHA1Managed sha1 = new SHA1Managed();
  50.             SHA256Managed sha256 = new SHA256Managed();
  51.  
  52.             byte[] buffer = new byte[randSalt.Length + sbuffer.Length];
  53.             Buffer.BlockCopy(randSalt, 0, buffer, 0, randSalt.Length);
  54.             Buffer.BlockCopy(sbuffer, 0, buffer, randSalt.Length, sbuffer.Length);
  55.  
  56.             for (int i = 0; i < iterations; i++)
  57.             {
  58.                 // flip the order of using these two around if you want longer hashes
  59.                 sha256.ComputeHash(buffer);
  60.                 buffer = sha256.Hash;
  61.                 sha1.ComputeHash(buffer);
  62.                 buffer = sha1.Hash;
  63.             }
  64.  
  65.             byte[] output = new byte[buffer.Length + randSalt.Length];
  66.             Buffer.BlockCopy(randSalt, 0, output, 0, randSalt.Length);
  67.             Buffer.BlockCopy(buffer, 0, output, randSalt.Length, buffer.Length);
  68.  
  69.             return Convert.ToBase64String(output);
  70.         }
  71.     }
  72. }

Here is a simple console driver application that demonstrates its usage:

Code Snippet
  1. using System;
  2.  
  3. namespace SecureHashTestConsole
  4. {
  5.     class Program
  6.     {
  7.         static void Main(string[] args)
  8.         {
  9.             var testValues = new[] {"Testing" , "2", "4343", "help", "This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here"};
  10.             foreach (string strTestValue in testValues)
  11.             {
  12.                 for (int i = 0; i < 10; i++)
  13.                 {
  14.                     String hash = SecureHashHelper.CreateSecureHash(strTestValue);
  15.                     Console.WriteLine("Hash #{0} of '{1}' = '{2}'", i+1, strTestValue, hash);
  16.                     Console.WriteLine("Comparison = {0} (should be True)", SecureHashHelper.CompareSecureHash(hash, strTestValue));
  17.                     Console.WriteLine("Comparison = {0} (should be False)", SecureHashHelper.CompareSecureHash(hash, strTestValue + " "));
  18.                 }
  19.             }
  20.         }
  21.     }
  22. }

Example Output

Hash #1 of 'Testing' = 'qxj1uwwjKs+4sP9mUc96gpUIVYRcyD2FliNh'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #2 of 'Testing' = '4E7baUemZRmM7oYWk2aWdQ5jpnQ8OJcr4HmS'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #3 of 'Testing' = '0RRhLyFefkcLP9X5qWp/Nih8RNjezPzHm2hM'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #4 of 'Testing' = '/c2cdFCuc+eWAOxp192gSeSdNzWkddxkOuvD'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #5 of 'Testing' = 'OWrWE/821zy8siYjnGA+VD6UYXFRJjaW9gom'

Comparison = True (should be True)

Comparison = False (should be False)

 

.....................................

 

 

Hash #10 of 'help' = 'yiTptJocrqyFRpp6Hlk4/cXF04T6SQdsqqt7'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #1 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'qeIzv06CJeDXzu4p3K/uFSxcqVH45Wm6ESjo'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #2 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'xrQm1kuNrczVrdONoS8sRjddq0zq2si02hyN'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #3 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'WO7aN2lXoZgg7m0EYDnKqoRQw7mg3CSH0ori'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #4 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'CgQq75ZBm40P2IrNzaVZRBBCjjn3QdlN2Ivt'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #5 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'wXGXvdU1TBQCluwL2Kce1x4SbUU0YuFup31V'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #6 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'Xzpdr5p4RHJ1O24LdDxruL4+nw+NOp0tjrsh'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #7 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'kYFQgmaZp3VG1LjwYslKdGHZg7nnlZfLHDHB'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #8 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'nA/7Ky7xbMpAZ1OVuLF7Ku/0YarzZXpKIfA8'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #9 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'b875hD3alHDPv4yrl46GsvgGtuQOLpsECj7o'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #10 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'BJHwf4plv/t0Hpx1oi0l0VuZa9Dq0FppYI2J'

Comparison = True (should be True)

Comparison = False (should be False)

Currently rated 1.6 by 83 people

  • Currently 1.554216/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

ASP.Net | C#

Welcome

Please contact me if you have a great idea for a project and need technical expertise in designing, developing, or integrating a custom software solution.

Recent Comments

Comment RSS