sha1.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * sha1.cpp
  3. *
  4. * Copyright (C) The Internet Society (2001). All Rights Reserved.
  5. * This document and translations of it may be copied and furnished to others,
  6. * and derivative works that comment on or otherwise explain it or assist in its
  7. * implementation may be prepared, copied, published and distributed, in whole or in part,
  8. * without restriction of any kind, provided that the above copyright notice and this paragraph
  9. * are included on all such copies and derivative works. However, this document itself may not
  10. * be modified in any way, such as by removing the copyright notice or references to the Internet Society
  11. * or other Internet organizations, except as needed for the purpose of developing Internet standards in
  12. * which case the procedures for copyrights defined in the Internet Standards process must be followed,
  13. * or as required to translate it into languages other than English.
  14. *
  15. * The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.
  16. *
  17. * This document and the information contained herein is provided on an "AS IS" basis and
  18. * THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  19. * INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS
  20. * OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  21. *
  22. * Source:
  23. * http://www.faqs.org/rfcs/rfc3174.html
  24. *
  25. * Description:
  26. * This file implements the Secure Hashing Algorithm 1 as
  27. * defined in FIPS PUB 180-1 published April 17, 1995.
  28. *
  29. * The SHA-1, produces a 160-bit message digest for a given
  30. * data stream. It should take about 2**n steps to find a
  31. * message with the same digest as a given message and
  32. * 2**(n/2) to find any two messages with the same digest,
  33. * when n is the digest size in bits. Therefore, this
  34. * algorithm can serve as a means of providing a
  35. * "fingerprint" for a message.
  36. *
  37. * Portability Issues:
  38. * SHA-1 is defined in terms of 32-bit "words". This code
  39. * uses <stdint.h> (included via "sha1.h" to define 32 and 8
  40. * bit unsigned integer types. If your C compiler does not
  41. * support 32 bit unsigned integers, this code is not
  42. * appropriate.
  43. *
  44. * Caveats:
  45. * SHA-1 is designed to work with messages less than 2^64 bits
  46. * long. Although SHA-1 allows a message digest to be generated
  47. * for messages of any number of bits less than 2^64, this
  48. * implementation only works with messages with a length that is
  49. * a multiple of the size of an 8-bit character.
  50. *
  51. */
  52. #include "platform/winrt/sha1.h"
  53. /*
  54. * Define the SHA1 circular left shift macro
  55. */
  56. #define SHA1CircularShift(bits,word) \
  57. (((word) << (bits)) | ((word) >> (32-(bits))))
  58. /* Local Function Prototyptes */
  59. void SHA1PadMessage(SHA1Context *);
  60. void SHA1ProcessMessageBlock(SHA1Context *);
  61. /*
  62. * SHA1Reset
  63. *
  64. * Description:
  65. * This function will initialize the SHA1Context in preparation
  66. * for computing a new SHA1 message digest.
  67. *
  68. * Parameters:
  69. * context: [in/out]
  70. * The context to reset.
  71. *
  72. * Returns:
  73. * sha Error Code.
  74. *
  75. */
  76. int SHA1Reset(SHA1Context *context)
  77. {
  78. if (!context)
  79. {
  80. return shaNull;
  81. }
  82. context->Length_Low = 0;
  83. context->Length_High = 0;
  84. context->Message_Block_Index = 0;
  85. context->Intermediate_Hash[0] = 0x67452301;
  86. context->Intermediate_Hash[1] = 0xEFCDAB89;
  87. context->Intermediate_Hash[2] = 0x98BADCFE;
  88. context->Intermediate_Hash[3] = 0x10325476;
  89. context->Intermediate_Hash[4] = 0xC3D2E1F0;
  90. context->Computed = 0;
  91. context->Corrupted = 0;
  92. return shaSuccess;
  93. }
  94. /*
  95. * SHA1Result
  96. *
  97. * Description:
  98. * This function will return the 160-bit message digest into the
  99. * Message_Digest array provided by the caller.
  100. * NOTE: The first octet of hash is stored in the 0th element,
  101. * the last octet of hash in the 19th element.
  102. *
  103. * Parameters:
  104. * context: [in/out]
  105. * The context to use to calculate the SHA-1 hash.
  106. * Message_Digest: [out]
  107. * Where the digest is returned.
  108. *
  109. * Returns:
  110. * sha Error Code.
  111. *
  112. */
  113. int SHA1Result( SHA1Context *context,
  114. uint8_t Message_Digest[SHA1HashSize])
  115. {
  116. int i;
  117. if (!context || !Message_Digest)
  118. {
  119. return shaNull;
  120. }
  121. if (context->Corrupted)
  122. {
  123. return context->Corrupted;
  124. }
  125. if (!context->Computed)
  126. {
  127. SHA1PadMessage(context);
  128. for(i=0; i<64; ++i)
  129. {
  130. /* message may be sensitive, clear it out */
  131. context->Message_Block[i] = 0;
  132. }
  133. context->Length_Low = 0; /* and clear length */
  134. context->Length_High = 0;
  135. context->Computed = 1;
  136. }
  137. for(i = 0; i < SHA1HashSize; ++i)
  138. {
  139. Message_Digest[i] = context->Intermediate_Hash[i>>2]
  140. >> 8 * ( 3 - ( i & 0x03 ) );
  141. }
  142. return shaSuccess;
  143. }
  144. /*
  145. * SHA1Input
  146. *
  147. * Description:
  148. * This function accepts an array of octets as the next portion
  149. * of the message.
  150. *
  151. * Parameters:
  152. * context: [in/out]
  153. * The SHA context to update
  154. * message_array: [in]
  155. * An array of characters representing the next portion of
  156. * the message.
  157. * length: [in]
  158. * The length of the message in message_array
  159. *
  160. * Returns:
  161. * sha Error Code.
  162. *
  163. */
  164. int SHA1Input( SHA1Context *context,
  165. const uint8_t *message_array,
  166. unsigned length)
  167. {
  168. if (!length)
  169. {
  170. return shaSuccess;
  171. }
  172. if (!context || !message_array)
  173. {
  174. return shaNull;
  175. }
  176. if (context->Computed)
  177. {
  178. context->Corrupted = shaStateError;
  179. return shaStateError;
  180. }
  181. if (context->Corrupted)
  182. {
  183. return context->Corrupted;
  184. }
  185. while(length-- && !context->Corrupted)
  186. {
  187. context->Message_Block[context->Message_Block_Index++] =
  188. (*message_array & 0xFF);
  189. context->Length_Low += 8;
  190. if (context->Length_Low == 0)
  191. {
  192. context->Length_High++;
  193. if (context->Length_High == 0)
  194. {
  195. /* Message is too long */
  196. context->Corrupted = 1;
  197. }
  198. }
  199. if (context->Message_Block_Index == 64)
  200. {
  201. SHA1ProcessMessageBlock(context);
  202. }
  203. message_array++;
  204. }
  205. return shaSuccess;
  206. }
  207. /*
  208. * SHA1ProcessMessageBlock
  209. *
  210. * Description:
  211. * This function will process the next 512 bits of the message
  212. * stored in the Message_Block array.
  213. *
  214. * Parameters:
  215. * None.
  216. *
  217. * Returns:
  218. * Nothing.
  219. *
  220. * Comments:
  221. * Many of the variable names in this code, especially the
  222. * single character names, were used because those were the
  223. * names used in the publication.
  224. *
  225. *
  226. */
  227. void SHA1ProcessMessageBlock(SHA1Context *context)
  228. {
  229. const uint32_t K[] = { /* Constants defined in SHA-1 */
  230. 0x5A827999,
  231. 0x6ED9EBA1,
  232. 0x8F1BBCDC,
  233. 0xCA62C1D6
  234. };
  235. int t; /* Loop counter */
  236. uint32_t temp; /* Temporary word value */
  237. uint32_t W[80]; /* Word sequence */
  238. uint32_t A, B, C, D, E; /* Word buffers */
  239. /*
  240. * Initialize the first 16 words in the array W
  241. */
  242. for(t = 0; t < 16; t++)
  243. {
  244. W[t] = context->Message_Block[t * 4] << 24;
  245. W[t] |= context->Message_Block[t * 4 + 1] << 16;
  246. W[t] |= context->Message_Block[t * 4 + 2] << 8;
  247. W[t] |= context->Message_Block[t * 4 + 3];
  248. }
  249. for(t = 16; t < 80; t++)
  250. {
  251. W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
  252. }
  253. A = context->Intermediate_Hash[0];
  254. B = context->Intermediate_Hash[1];
  255. C = context->Intermediate_Hash[2];
  256. D = context->Intermediate_Hash[3];
  257. E = context->Intermediate_Hash[4];
  258. for(t = 0; t < 20; t++)
  259. {
  260. temp = SHA1CircularShift(5,A) +
  261. ((B & C) | ((~B) & D)) + E + W[t] + K[0];
  262. E = D;
  263. D = C;
  264. C = SHA1CircularShift(30,B);
  265. B = A;
  266. A = temp;
  267. }
  268. for(t = 20; t < 40; t++)
  269. {
  270. temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
  271. E = D;
  272. D = C;
  273. C = SHA1CircularShift(30,B);
  274. B = A;
  275. A = temp;
  276. }
  277. for(t = 40; t < 60; t++)
  278. {
  279. temp = SHA1CircularShift(5,A) +
  280. ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
  281. E = D;
  282. D = C;
  283. C = SHA1CircularShift(30,B);
  284. B = A;
  285. A = temp;
  286. }
  287. for(t = 60; t < 80; t++)
  288. {
  289. temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
  290. E = D;
  291. D = C;
  292. C = SHA1CircularShift(30,B);
  293. B = A;
  294. A = temp;
  295. }
  296. context->Intermediate_Hash[0] += A;
  297. context->Intermediate_Hash[1] += B;
  298. context->Intermediate_Hash[2] += C;
  299. context->Intermediate_Hash[3] += D;
  300. context->Intermediate_Hash[4] += E;
  301. context->Message_Block_Index = 0;
  302. }
  303. /*
  304. * SHA1PadMessage
  305. *
  306. * Description:
  307. * According to the standard, the message must be padded to an even
  308. * 512 bits. The first padding bit must be a '1'. The last 64
  309. * bits represent the length of the original message. All bits in
  310. * between should be 0. This function will pad the message
  311. * according to those rules by filling the Message_Block array
  312. * accordingly. It will also call the ProcessMessageBlock function
  313. * provided appropriately. When it returns, it can be assumed that
  314. * the message digest has been computed.
  315. *
  316. * Parameters:
  317. * context: [in/out]
  318. * The context to pad
  319. * ProcessMessageBlock: [in]
  320. * The appropriate SHA*ProcessMessageBlock function
  321. * Returns:
  322. * Nothing.
  323. *
  324. */
  325. void SHA1PadMessage(SHA1Context *context)
  326. {
  327. /*
  328. * Check to see if the current message block is too small to hold
  329. * the initial padding bits and length. If so, we will pad the
  330. * block, process it, and then continue padding into a second
  331. * block.
  332. */
  333. if (context->Message_Block_Index > 55)
  334. {
  335. context->Message_Block[context->Message_Block_Index++] = 0x80;
  336. while(context->Message_Block_Index < 64)
  337. {
  338. context->Message_Block[context->Message_Block_Index++] = 0;
  339. }
  340. SHA1ProcessMessageBlock(context);
  341. while(context->Message_Block_Index < 56)
  342. {
  343. context->Message_Block[context->Message_Block_Index++] = 0;
  344. }
  345. }
  346. else
  347. {
  348. context->Message_Block[context->Message_Block_Index++] = 0x80;
  349. while(context->Message_Block_Index < 56)
  350. {
  351. context->Message_Block[context->Message_Block_Index++] = 0;
  352. }
  353. }
  354. /*
  355. * Store the message length as the last 8 octets
  356. */
  357. context->Message_Block[56] = context->Length_High >> 24;
  358. context->Message_Block[57] = context->Length_High >> 16;
  359. context->Message_Block[58] = context->Length_High >> 8;
  360. context->Message_Block[59] = context->Length_High;
  361. context->Message_Block[60] = context->Length_Low >> 24;
  362. context->Message_Block[61] = context->Length_Low >> 16;
  363. context->Message_Block[62] = context->Length_Low >> 8;
  364. context->Message_Block[63] = context->Length_Low;
  365. SHA1ProcessMessageBlock(context);
  366. }
  367. static const char alphabet[] = "0123456789ABCDEF";
  368. void SHA1ConvertMessageToString(uint8_t *hash_binary, char* hash_string)
  369. {
  370. for (int i = 0; i != SHA1HashSize; ++i)
  371. {
  372. hash_string[2*i] = alphabet[hash_binary[i] / 16];
  373. hash_string[2*i + 1] = alphabet[hash_binary[i] % 16];
  374. }
  375. hash_string[SHA1HashSize * 2] = '\0';
  376. }