Advertisement
Guest User

Untitled

a guest
Mar 27th, 2017
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.37 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Security.Cryptography;
  6.  
  7. namespace RedacaoOnline.Models.Utilities
  8. {
  9. public class PasswordStorage
  10. {
  11. // These constants may be changed without breaking existing hashes.
  12. public const int SALT_BYTES = 24;
  13. public const int HASH_BYTES = 18;
  14. public const int PBKDF2_ITERATIONS = 64000;
  15.  
  16. // These constants define the encoding and may not be changed.
  17. public const int HASH_SECTIONS = 5;
  18. public const int HASH_ALGORITHM_INDEX = 0;
  19. public const int ITERATION_INDEX = 1;
  20. public const int HASH_SIZE_INDEX = 2;
  21. public const int SALT_INDEX = 3;
  22. public const int PBKDF2_INDEX = 4;
  23.  
  24. public static string CreateHash(string password)
  25. {
  26. // Generate a random salt
  27. byte[] salt = new byte[SALT_BYTES];
  28. try
  29. {
  30. using (RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider())
  31. {
  32. csprng.GetBytes(salt);
  33. }
  34. }
  35. catch (Exception ex)
  36. {
  37. throw new Exception(ex.Message);
  38. }
  39.  
  40. byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTES);
  41.  
  42. // format: algorithm:iterations:hashSize:salt:hash
  43. String parts = "sha1:" +
  44. PBKDF2_ITERATIONS +
  45. ":" +
  46. hash.Length +
  47. ":" +
  48. Convert.ToBase64String(salt) +
  49. ":" +
  50. Convert.ToBase64String(hash);
  51. return parts;
  52. }
  53.  
  54. public static bool VerifyPassword(string password, string goodHash)
  55. {
  56. char[] delimiter = { ':' };
  57. string[] split = goodHash.Split(delimiter);
  58.  
  59. if (split.Length != HASH_SECTIONS)
  60. {
  61. throw new Exception("Fields are missing from the password hash.");
  62. }
  63.  
  64. // We only support SHA1 with C#.
  65. if (split[HASH_ALGORITHM_INDEX] != "sha1")
  66. {
  67. throw new Exception("Unsupported hash type.");
  68. }
  69.  
  70. int iterations = 0;
  71. try
  72. {
  73. iterations = Int32.Parse(split[ITERATION_INDEX]);
  74. }
  75. catch (Exception ex)
  76. {
  77. throw new Exception(ex.Message);
  78. }
  79.  
  80. if (iterations < 1)
  81. {
  82. throw new Exception("Invalid number of iterations. Must be >= 1.");
  83. }
  84.  
  85. byte[] salt = null;
  86. try
  87. {
  88. salt = Convert.FromBase64String(split[SALT_INDEX]);
  89. }
  90. catch (Exception ex)
  91. {
  92. throw new Exception(ex.Message);
  93. }
  94.  
  95. byte[] hash = null;
  96. try
  97. {
  98. hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
  99. }
  100. catch (Exception ex)
  101. {
  102. throw new Exception(ex.Message);
  103. }
  104.  
  105. int storedHashSize = 0;
  106. try
  107. {
  108. storedHashSize = Int32.Parse(split[HASH_SIZE_INDEX]);
  109. }
  110. catch (Exception ex)
  111. {
  112. throw new Exception(ex.Message);
  113. }
  114.  
  115. if (storedHashSize != hash.Length)
  116. {
  117. throw new Exception("Hash length doesn't match stored hash length.");
  118. }
  119.  
  120. byte[] testHash = PBKDF2(password, salt, iterations, hash.Length);
  121. return SlowEquals(hash, testHash);
  122. }
  123.  
  124. private static bool SlowEquals(byte[] a, byte[] b)
  125. {
  126. uint diff = (uint)a.Length ^ (uint)b.Length;
  127. for (int i = 0; i < a.Length && i < b.Length; i++)
  128. {
  129. diff |= (uint)(a[i] ^ b[i]);
  130. }
  131. return diff == 0;
  132. }
  133.  
  134. private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
  135. {
  136. using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt))
  137. {
  138. pbkdf2.IterationCount = iterations;
  139. return pbkdf2.GetBytes(outputBytes);
  140. }
  141. }
  142. }
  143. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement