You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
11 KiB

4 years ago
  1. #if MYSQL_6_10
  2. // Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
  3. //
  4. // MySQL Connector/NET is licensed under the terms of the GPLv2
  5. // <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
  6. // MySQL Connectors. There are special exceptions to the terms and
  7. // conditions of the GPLv2 as it is applied to this software, see the
  8. // FLOSS License Exception
  9. // <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
  10. //
  11. // This program is free software; you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published
  13. // by the Free Software Foundation; version 2 of the License.
  14. //
  15. // This program is distributed in the hope that it will be useful, but
  16. // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  18. // for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License along
  21. // with this program; if not, write to the Free Software Foundation, Inc.,
  22. // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. /*
  24. Original Source from: http://www.faqs.org/rfcs/rfc3174.html
  25. Copyright (C) The Internet Society (2001). All Rights Reserved.
  26. This document and translations of it may be copied and furnished to
  27. others, and derivative works that comment on or otherwise explain it
  28. or assist in its implementation may be prepared, copied, published
  29. and distributed, in whole or in part, without restriction of any
  30. kind, provided that the above copyright notice and this paragraph are
  31. included on all such copies and derivative works. However, this
  32. document itself may not be modified in any way, such as by removing
  33. the copyright notice or references to the Internet Society or other
  34. Internet organizations, except as needed for the purpose of
  35. developing Internet standards in which case the procedures for
  36. copyrights defined in the Internet Standards process must be
  37. followed, or as required to translate it into languages other than
  38. English.
  39. The limited permissions granted above are perpetual and will not be
  40. revoked by the Internet Society or its successors or assigns.
  41. This document and the information contained herein is provided on an
  42. "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
  43. TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
  44. BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
  45. HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
  46. MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  47. Acknowledgement
  48. Funding for the RFC Editor function is currently provided by the
  49. Internet Society.
  50. */
  51. using System;
  52. namespace Externals.MySql.Data.Common
  53. {
  54. class SHA1Hash
  55. {
  56. private const int SHA1_HASH_SIZE = 20; // Hash size in bytes
  57. // Constants defined in SHA-1
  58. private static uint[] K = new uint[4] {
  59. 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
  60. private static uint[] sha_const_key = new uint[5] {
  61. 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
  62. private ulong length; // Message length in bits
  63. private uint[] intermediateHash; // Message Digest
  64. private bool computed; // Is the digest computed?
  65. // private bool corrupted; // Is the message digest corrupted?
  66. private short messageBlockIndex; // Index into message block array
  67. private byte[] messageBlock; // 512-bit message blocks
  68. public SHA1Hash()
  69. {
  70. intermediateHash = new uint[SHA1_HASH_SIZE / 4];
  71. messageBlock = new byte[64];
  72. Reset();
  73. }
  74. public void Reset()
  75. {
  76. // /*#ifndef DBUG_OFF
  77. // if (!context)
  78. // return SHA_NULL;
  79. // #endif*/
  80. length = 0;
  81. messageBlockIndex = 0;
  82. intermediateHash[0] = sha_const_key[0];
  83. intermediateHash[1] = sha_const_key[1];
  84. intermediateHash[2] = sha_const_key[2];
  85. intermediateHash[3] = sha_const_key[3];
  86. intermediateHash[4] = sha_const_key[4];
  87. computed = false;
  88. // corrupted = false;
  89. }
  90. public byte[] ComputeHash(byte[] buffer)
  91. {
  92. Reset();
  93. Input(buffer, 0, buffer.Length);
  94. return Result();
  95. }
  96. public void Input(byte[] buffer, int index, int bufLen)
  97. {
  98. if (buffer == null || bufLen == 0) return;
  99. if (index < 0 || index > buffer.Length - 1)
  100. throw new ArgumentException("Index must be a value between 0 and buffer.Length-1", "index");
  101. if (bufLen < 0)
  102. throw new ArgumentException("Length must be a value > 0", "length");
  103. if ((bufLen + index) > buffer.Length)
  104. throw new ArgumentException("Length + index would extend past the end of buffer", "length");
  105. // /*#ifndef DBUG_OFF
  106. // // We assume client konows what it is doing in non-debug mode
  107. // if (!context || !message_array)
  108. // return SHA_NULL;
  109. // if (context->Computed)
  110. // return (context->Corrupted= SHA_STATE_ERROR);
  111. // if (context->Corrupted)
  112. // return context->Corrupted;
  113. // #endif*/
  114. while (bufLen-- > 0)
  115. {
  116. messageBlock[messageBlockIndex++] = (byte)(buffer[index++] & 0xFF);
  117. length += 8; /* Length is in bits */
  118. // /*#ifndef DBUG_OFF
  119. //
  120. // // Then we're not debugging we assume we never will get message longer
  121. // //2^64 bits.
  122. //
  123. // if (context->Length == 0)
  124. // return (context->Corrupted= 1); // Message is too long
  125. // #endif*/
  126. if (messageBlockIndex == 64)
  127. ProcessMessageBlock();
  128. }
  129. }
  130. private void ProcessMessageBlock()
  131. {
  132. uint temp; // Temporary word value
  133. uint[] W; // Word sequence
  134. uint A, B, C, D, E; // Word buffers
  135. W = new uint[80];
  136. //Initialize the first 16 words in the array W
  137. for (int t = 0; t < 16; t++)
  138. {
  139. int index = t * 4;
  140. W[t] = (uint)messageBlock[index] << 24;
  141. W[t] |= (uint)messageBlock[index + 1] << 16;
  142. W[t] |= (uint)messageBlock[index + 2] << 8;
  143. W[t] |= (uint)messageBlock[index + 3];
  144. }
  145. for (int t = 16; t < 80; t++)
  146. {
  147. W[t] = CircularShift(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
  148. }
  149. A = intermediateHash[0];
  150. B = intermediateHash[1];
  151. C = intermediateHash[2];
  152. D = intermediateHash[3];
  153. E = intermediateHash[4];
  154. for (int t = 0; t < 20; t++)
  155. {
  156. temp = CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
  157. E = D;
  158. D = C;
  159. C = CircularShift(30, B);
  160. B = A;
  161. A = temp;
  162. }
  163. for (int t = 20; t < 40; t++)
  164. {
  165. temp = CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[1];
  166. E = D;
  167. D = C;
  168. C = CircularShift(30, B);
  169. B = A;
  170. A = temp;
  171. }
  172. for (int t = 40; t < 60; t++)
  173. {
  174. temp = (CircularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]);
  175. E = D;
  176. D = C;
  177. C = CircularShift(30, B);
  178. B = A;
  179. A = temp;
  180. }
  181. for (int t = 60; t < 80; t++)
  182. {
  183. temp = CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[3];
  184. E = D;
  185. D = C;
  186. C = CircularShift(30, B);
  187. B = A;
  188. A = temp;
  189. }
  190. intermediateHash[0] += A;
  191. intermediateHash[1] += B;
  192. intermediateHash[2] += C;
  193. intermediateHash[3] += D;
  194. intermediateHash[4] += E;
  195. messageBlockIndex = 0;
  196. }
  197. private static uint CircularShift(int bits, uint word)
  198. {
  199. return (((word) << (bits)) | ((word) >> (32 - (bits))));
  200. }
  201. private void PadMessage()
  202. {
  203. /*
  204. Check to see if the current message block is too small to hold
  205. the initial padding bits and length. If so, we will pad the
  206. block, process it, and then continue padding into a second
  207. block.
  208. */
  209. int i = messageBlockIndex;
  210. if (i > 55)
  211. {
  212. messageBlock[i++] = 0x80;
  213. Array.Clear(messageBlock, i, 64 - i);
  214. //bzero((char*) &context->Message_Block[i], sizeof(messageBlock[0])*(64-i));
  215. messageBlockIndex = 64;
  216. /* This function sets messageBlockIndex to zero */
  217. ProcessMessageBlock();
  218. Array.Clear(messageBlock, 0, 56);
  219. //bzero((char*) &context->Message_Block[0], sizeof(messageBlock[0])*56);
  220. messageBlockIndex = 56;
  221. }
  222. else
  223. {
  224. messageBlock[i++] = 0x80;
  225. Array.Clear(messageBlock, i, 56 - i);
  226. //bzero((char*) &messageBlock[i], sizeof(messageBlock[0])*(56-i));
  227. messageBlockIndex = 56;
  228. }
  229. // Store the message length as the last 8 octets
  230. messageBlock[56] = (byte)(length >> 56);
  231. messageBlock[57] = (byte)(length >> 48);
  232. messageBlock[58] = (byte)(length >> 40);
  233. messageBlock[59] = (byte)(length >> 32);
  234. messageBlock[60] = (byte)(length >> 24);
  235. messageBlock[61] = (byte)(length >> 16);
  236. messageBlock[62] = (byte)(length >> 8);
  237. messageBlock[63] = (byte)length;
  238. ProcessMessageBlock();
  239. }
  240. public byte[] Result()
  241. {
  242. // /*#ifndef DBUG_OFF
  243. // if (!context || !Message_Digest)
  244. // return SHA_NULL;
  245. //
  246. // if (context->Corrupted)
  247. // return context->Corrupted;
  248. // #endif*/
  249. if (!computed)
  250. {
  251. PadMessage();
  252. // message may be sensitive, clear it out
  253. Array.Clear(messageBlock, 0, 64);
  254. //bzero((char*) messageBlock,64);
  255. length = 0; /* and clear length */
  256. computed = true;
  257. }
  258. byte[] messageDigest = new byte[SHA1_HASH_SIZE];
  259. for (int i = 0; i < SHA1_HASH_SIZE; i++)
  260. messageDigest[i] = (byte)((intermediateHash[i >> 2] >> 8 * (3 - (i & 0x03))));
  261. return messageDigest;
  262. }
  263. }
  264. }
  265. #endif