TlsHMAC.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. //
  2. // Permission is hereby granted, free of charge, to any person obtaining
  3. // a copy of this software and associated documentation files (the
  4. // "Software"), to deal in the Software without restriction, including
  5. // without limitation the rights to use, copy, modify, merge, publish,
  6. // distribute, sublicense, and/or sell copies of the Software, and to
  7. // permit persons to whom the Software is furnished to do so, subject to
  8. // the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be
  11. // included in all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  17. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  18. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  19. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. //
  21. /* Transport Security Layer (TLS)
  22. * Copyright (c) 2003-2004 Carlos Guzman Alvarez
  23. *
  24. * Permission is hereby granted, free of charge, to any person
  25. * obtaining a copy of this software and associated documentation
  26. * files (the "Software"), to deal in the Software without restriction,
  27. * including without limitation the rights to use, copy, modify, merge,
  28. * publish, distribute, sublicense, and/or sell copies of the Software,
  29. * and to permit persons to whom the Software is furnished to do so,
  30. * subject to the following conditions:
  31. *
  32. * The above copyright notice and this permission notice shall be included
  33. * in all copies or substantial portions of the Software.
  34. *
  35. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  36. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  37. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  38. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  39. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  40. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  41. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  42. * DEALINGS IN THE SOFTWARE.
  43. */
  44. using System;
  45. using System.Security.Cryptography;
  46. namespace Mono.Security.Cryptography
  47. {
  48. /*
  49. * References:
  50. * RFC 2104 (http://www.ietf.org/rfc/rfc2104.txt)
  51. * RFC 2202 (http://www.ietf.org/rfc/rfc2202.txt)
  52. * MSDN:
  53. *
  54. * Extending the KeyedHashAlgorithm Class (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconextendingkeyedhashalgorithmclass.asp)
  55. */
  56. internal class HMAC : System.Security.Cryptography.KeyedHashAlgorithm
  57. {
  58. #region Fields
  59. private HashAlgorithm hash;
  60. private bool hashing;
  61. private byte[] innerPad;
  62. private byte[] outerPad;
  63. #endregion
  64. #region Properties
  65. public override byte[] Key
  66. {
  67. get { return (byte[])KeyValue.Clone(); }
  68. set
  69. {
  70. if (hashing)
  71. {
  72. throw new Exception("Cannot change key during hash operation.");
  73. }
  74. /* if key is longer than 64 bytes reset it to rgbKey = Hash(rgbKey) */
  75. if (value.Length > 64)
  76. {
  77. KeyValue = hash.ComputeHash(value);
  78. }
  79. else
  80. {
  81. KeyValue = (byte[])value.Clone();
  82. }
  83. initializePad();
  84. }
  85. }
  86. #endregion
  87. #region Constructors
  88. public HMAC()
  89. {
  90. // Create the hash
  91. hash = MD5.Create();
  92. // Set HashSizeValue
  93. HashSizeValue = hash.HashSize;
  94. // Generate a radom key
  95. byte[] rgbKey = new byte[64];
  96. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  97. rng.GetNonZeroBytes(rgbKey);
  98. KeyValue = (byte[])rgbKey.Clone();
  99. this.Initialize();
  100. }
  101. public HMAC(string hashName, byte[] rgbKey)
  102. {
  103. // Create the hash
  104. if (hashName == null || hashName.Length == 0)
  105. {
  106. hashName = "MD5";
  107. }
  108. hash = HashAlgorithm.Create(hashName);
  109. // Set HashSizeValue
  110. HashSizeValue = hash.HashSize;
  111. /* if key is longer than 64 bytes reset it to rgbKey = Hash(rgbKey) */
  112. if (rgbKey.Length > 64)
  113. {
  114. KeyValue = hash.ComputeHash(rgbKey);
  115. }
  116. else
  117. {
  118. KeyValue = (byte[])rgbKey.Clone();
  119. }
  120. this.Initialize();
  121. }
  122. #endregion
  123. #region Methods
  124. public override void Initialize()
  125. {
  126. hash.Initialize();
  127. initializePad();
  128. hashing = false;
  129. }
  130. protected override byte[] HashFinal()
  131. {
  132. if (!hashing)
  133. {
  134. hash.TransformBlock(innerPad, 0, innerPad.Length, innerPad, 0);
  135. hashing = true;
  136. }
  137. // Finalize the original hash
  138. hash.TransformFinalBlock(new byte[0], 0, 0);
  139. byte[] firstResult = hash.Hash;
  140. hash.Initialize();
  141. hash.TransformBlock(outerPad, 0, outerPad.Length, outerPad, 0);
  142. hash.TransformFinalBlock(firstResult, 0, firstResult.Length);
  143. Initialize();
  144. return hash.Hash;
  145. }
  146. protected override void HashCore(
  147. byte[] array,
  148. int ibStart,
  149. int cbSize)
  150. {
  151. if (!hashing)
  152. {
  153. hash.TransformBlock(innerPad, 0, innerPad.Length, innerPad, 0);
  154. hashing = true;
  155. }
  156. hash.TransformBlock(array, ibStart, cbSize, array, ibStart);
  157. }
  158. #endregion
  159. #region Private Methods
  160. private void initializePad()
  161. {
  162. // Fill pad arrays
  163. innerPad = new byte[64];
  164. outerPad = new byte[64];
  165. /* Pad the key for inner and outer digest */
  166. for (int i = 0 ; i < KeyValue.Length; ++i)
  167. {
  168. innerPad[i] = (byte)(KeyValue[i] ^ 0x36);
  169. outerPad[i] = (byte)(KeyValue[i] ^ 0x5C);
  170. }
  171. for (int i = KeyValue.Length; i < 64; ++i)
  172. {
  173. innerPad[i] = 0x36;
  174. outerPad[i] = 0x5C;
  175. }
  176. }
  177. #endregion
  178. }
  179. }