1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00

Added external hashing library.

This commit is contained in:
Sandu Liviu Catalin 2015-11-01 10:02:15 +02:00
parent 6b16059547
commit 1431cb9e1e
17 changed files with 2832 additions and 0 deletions

431
external/Common/crc32.cpp vendored Normal file
View File

@ -0,0 +1,431 @@
// //////////////////////////////////////////////////////////
// crc32.cpp
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#include "crc32.h"
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
#ifndef _MSC_VER
#include <endian.h>
#endif
/// same as reset()
CRC32::CRC32()
{
reset();
}
/// restart
void CRC32::reset()
{
m_hash = 0;
}
namespace
{
/// look-up table
static const uint32_t crc32Lookup[8][256] =
{
// generated by:
//for (uint32_t i = 0; i <= 0xFF; i++)
//{
// uint32_t crc = i;
// for (unsigned int j = 0; j < 8; j++)
// crc = (crc >> 1) ^ ((crc & 1) * Polynomial);
// crc32Lookup[0][i] = crc;
//}
// slicing-by-8 algorithm (from Intel):
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
// http://sourceforge.net/projects/slicing-by-8/
//for (unsigned int i = 0; i <= 0xFF; i++)
//{
// crc32Lookup[1][i] = (crc32Lookup[0][i] >> 8) ^ crc32Lookup[0][crc32Lookup[0][i] & 0xFF];
// crc32Lookup[2][i] = (crc32Lookup[1][i] >> 8) ^ crc32Lookup[0][crc32Lookup[1][i] & 0xFF];
// crc32Lookup[3][i] = (crc32Lookup[2][i] >> 8) ^ crc32Lookup[0][crc32Lookup[2][i] & 0xFF];
// crc32Lookup[4][i] = (crc32Lookup[3][i] >> 8) ^ crc32Lookup[0][crc32Lookup[3][i] & 0xFF];
// crc32Lookup[5][i] = (crc32Lookup[4][i] >> 8) ^ crc32Lookup[0][crc32Lookup[4][i] & 0xFF];
// crc32Lookup[6][i] = (crc32Lookup[5][i] >> 8) ^ crc32Lookup[0][crc32Lookup[5][i] & 0xFF];
// crc32Lookup[7][i] = (crc32Lookup[6][i] >> 8) ^ crc32Lookup[0][crc32Lookup[6][i] & 0xFF];
//}
{ 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,
0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,
0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,
0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,
0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,
0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,
0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,
0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,
0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,
0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,
0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,
0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,
0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,
0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,
0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,
0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D },
{ 0x00000000,0x191B3141,0x32366282,0x2B2D53C3,0x646CC504,0x7D77F445,0x565AA786,0x4F4196C7,
0xC8D98A08,0xD1C2BB49,0xFAEFE88A,0xE3F4D9CB,0xACB54F0C,0xB5AE7E4D,0x9E832D8E,0x87981CCF,
0x4AC21251,0x53D92310,0x78F470D3,0x61EF4192,0x2EAED755,0x37B5E614,0x1C98B5D7,0x05838496,
0x821B9859,0x9B00A918,0xB02DFADB,0xA936CB9A,0xE6775D5D,0xFF6C6C1C,0xD4413FDF,0xCD5A0E9E,
0x958424A2,0x8C9F15E3,0xA7B24620,0xBEA97761,0xF1E8E1A6,0xE8F3D0E7,0xC3DE8324,0xDAC5B265,
0x5D5DAEAA,0x44469FEB,0x6F6BCC28,0x7670FD69,0x39316BAE,0x202A5AEF,0x0B07092C,0x121C386D,
0xDF4636F3,0xC65D07B2,0xED705471,0xF46B6530,0xBB2AF3F7,0xA231C2B6,0x891C9175,0x9007A034,
0x179FBCFB,0x0E848DBA,0x25A9DE79,0x3CB2EF38,0x73F379FF,0x6AE848BE,0x41C51B7D,0x58DE2A3C,
0xF0794F05,0xE9627E44,0xC24F2D87,0xDB541CC6,0x94158A01,0x8D0EBB40,0xA623E883,0xBF38D9C2,
0x38A0C50D,0x21BBF44C,0x0A96A78F,0x138D96CE,0x5CCC0009,0x45D73148,0x6EFA628B,0x77E153CA,
0xBABB5D54,0xA3A06C15,0x888D3FD6,0x91960E97,0xDED79850,0xC7CCA911,0xECE1FAD2,0xF5FACB93,
0x7262D75C,0x6B79E61D,0x4054B5DE,0x594F849F,0x160E1258,0x0F152319,0x243870DA,0x3D23419B,
0x65FD6BA7,0x7CE65AE6,0x57CB0925,0x4ED03864,0x0191AEA3,0x188A9FE2,0x33A7CC21,0x2ABCFD60,
0xAD24E1AF,0xB43FD0EE,0x9F12832D,0x8609B26C,0xC94824AB,0xD05315EA,0xFB7E4629,0xE2657768,
0x2F3F79F6,0x362448B7,0x1D091B74,0x04122A35,0x4B53BCF2,0x52488DB3,0x7965DE70,0x607EEF31,
0xE7E6F3FE,0xFEFDC2BF,0xD5D0917C,0xCCCBA03D,0x838A36FA,0x9A9107BB,0xB1BC5478,0xA8A76539,
0x3B83984B,0x2298A90A,0x09B5FAC9,0x10AECB88,0x5FEF5D4F,0x46F46C0E,0x6DD93FCD,0x74C20E8C,
0xF35A1243,0xEA412302,0xC16C70C1,0xD8774180,0x9736D747,0x8E2DE606,0xA500B5C5,0xBC1B8484,
0x71418A1A,0x685ABB5B,0x4377E898,0x5A6CD9D9,0x152D4F1E,0x0C367E5F,0x271B2D9C,0x3E001CDD,
0xB9980012,0xA0833153,0x8BAE6290,0x92B553D1,0xDDF4C516,0xC4EFF457,0xEFC2A794,0xF6D996D5,
0xAE07BCE9,0xB71C8DA8,0x9C31DE6B,0x852AEF2A,0xCA6B79ED,0xD37048AC,0xF85D1B6F,0xE1462A2E,
0x66DE36E1,0x7FC507A0,0x54E85463,0x4DF36522,0x02B2F3E5,0x1BA9C2A4,0x30849167,0x299FA026,
0xE4C5AEB8,0xFDDE9FF9,0xD6F3CC3A,0xCFE8FD7B,0x80A96BBC,0x99B25AFD,0xB29F093E,0xAB84387F,
0x2C1C24B0,0x350715F1,0x1E2A4632,0x07317773,0x4870E1B4,0x516BD0F5,0x7A468336,0x635DB277,
0xCBFAD74E,0xD2E1E60F,0xF9CCB5CC,0xE0D7848D,0xAF96124A,0xB68D230B,0x9DA070C8,0x84BB4189,
0x03235D46,0x1A386C07,0x31153FC4,0x280E0E85,0x674F9842,0x7E54A903,0x5579FAC0,0x4C62CB81,
0x8138C51F,0x9823F45E,0xB30EA79D,0xAA1596DC,0xE554001B,0xFC4F315A,0xD7626299,0xCE7953D8,
0x49E14F17,0x50FA7E56,0x7BD72D95,0x62CC1CD4,0x2D8D8A13,0x3496BB52,0x1FBBE891,0x06A0D9D0,
0x5E7EF3EC,0x4765C2AD,0x6C48916E,0x7553A02F,0x3A1236E8,0x230907A9,0x0824546A,0x113F652B,
0x96A779E4,0x8FBC48A5,0xA4911B66,0xBD8A2A27,0xF2CBBCE0,0xEBD08DA1,0xC0FDDE62,0xD9E6EF23,
0x14BCE1BD,0x0DA7D0FC,0x268A833F,0x3F91B27E,0x70D024B9,0x69CB15F8,0x42E6463B,0x5BFD777A,
0xDC656BB5,0xC57E5AF4,0xEE530937,0xF7483876,0xB809AEB1,0xA1129FF0,0x8A3FCC33,0x9324FD72 },
{ 0x00000000,0x01C26A37,0x0384D46E,0x0246BE59,0x0709A8DC,0x06CBC2EB,0x048D7CB2,0x054F1685,
0x0E1351B8,0x0FD13B8F,0x0D9785D6,0x0C55EFE1,0x091AF964,0x08D89353,0x0A9E2D0A,0x0B5C473D,
0x1C26A370,0x1DE4C947,0x1FA2771E,0x1E601D29,0x1B2F0BAC,0x1AED619B,0x18ABDFC2,0x1969B5F5,
0x1235F2C8,0x13F798FF,0x11B126A6,0x10734C91,0x153C5A14,0x14FE3023,0x16B88E7A,0x177AE44D,
0x384D46E0,0x398F2CD7,0x3BC9928E,0x3A0BF8B9,0x3F44EE3C,0x3E86840B,0x3CC03A52,0x3D025065,
0x365E1758,0x379C7D6F,0x35DAC336,0x3418A901,0x3157BF84,0x3095D5B3,0x32D36BEA,0x331101DD,
0x246BE590,0x25A98FA7,0x27EF31FE,0x262D5BC9,0x23624D4C,0x22A0277B,0x20E69922,0x2124F315,
0x2A78B428,0x2BBADE1F,0x29FC6046,0x283E0A71,0x2D711CF4,0x2CB376C3,0x2EF5C89A,0x2F37A2AD,
0x709A8DC0,0x7158E7F7,0x731E59AE,0x72DC3399,0x7793251C,0x76514F2B,0x7417F172,0x75D59B45,
0x7E89DC78,0x7F4BB64F,0x7D0D0816,0x7CCF6221,0x798074A4,0x78421E93,0x7A04A0CA,0x7BC6CAFD,
0x6CBC2EB0,0x6D7E4487,0x6F38FADE,0x6EFA90E9,0x6BB5866C,0x6A77EC5B,0x68315202,0x69F33835,
0x62AF7F08,0x636D153F,0x612BAB66,0x60E9C151,0x65A6D7D4,0x6464BDE3,0x662203BA,0x67E0698D,
0x48D7CB20,0x4915A117,0x4B531F4E,0x4A917579,0x4FDE63FC,0x4E1C09CB,0x4C5AB792,0x4D98DDA5,
0x46C49A98,0x4706F0AF,0x45404EF6,0x448224C1,0x41CD3244,0x400F5873,0x4249E62A,0x438B8C1D,
0x54F16850,0x55330267,0x5775BC3E,0x56B7D609,0x53F8C08C,0x523AAABB,0x507C14E2,0x51BE7ED5,
0x5AE239E8,0x5B2053DF,0x5966ED86,0x58A487B1,0x5DEB9134,0x5C29FB03,0x5E6F455A,0x5FAD2F6D,
0xE1351B80,0xE0F771B7,0xE2B1CFEE,0xE373A5D9,0xE63CB35C,0xE7FED96B,0xE5B86732,0xE47A0D05,
0xEF264A38,0xEEE4200F,0xECA29E56,0xED60F461,0xE82FE2E4,0xE9ED88D3,0xEBAB368A,0xEA695CBD,
0xFD13B8F0,0xFCD1D2C7,0xFE976C9E,0xFF5506A9,0xFA1A102C,0xFBD87A1B,0xF99EC442,0xF85CAE75,
0xF300E948,0xF2C2837F,0xF0843D26,0xF1465711,0xF4094194,0xF5CB2BA3,0xF78D95FA,0xF64FFFCD,
0xD9785D60,0xD8BA3757,0xDAFC890E,0xDB3EE339,0xDE71F5BC,0xDFB39F8B,0xDDF521D2,0xDC374BE5,
0xD76B0CD8,0xD6A966EF,0xD4EFD8B6,0xD52DB281,0xD062A404,0xD1A0CE33,0xD3E6706A,0xD2241A5D,
0xC55EFE10,0xC49C9427,0xC6DA2A7E,0xC7184049,0xC25756CC,0xC3953CFB,0xC1D382A2,0xC011E895,
0xCB4DAFA8,0xCA8FC59F,0xC8C97BC6,0xC90B11F1,0xCC440774,0xCD866D43,0xCFC0D31A,0xCE02B92D,
0x91AF9640,0x906DFC77,0x922B422E,0x93E92819,0x96A63E9C,0x976454AB,0x9522EAF2,0x94E080C5,
0x9FBCC7F8,0x9E7EADCF,0x9C381396,0x9DFA79A1,0x98B56F24,0x99770513,0x9B31BB4A,0x9AF3D17D,
0x8D893530,0x8C4B5F07,0x8E0DE15E,0x8FCF8B69,0x8A809DEC,0x8B42F7DB,0x89044982,0x88C623B5,
0x839A6488,0x82580EBF,0x801EB0E6,0x81DCDAD1,0x8493CC54,0x8551A663,0x8717183A,0x86D5720D,
0xA9E2D0A0,0xA820BA97,0xAA6604CE,0xABA46EF9,0xAEEB787C,0xAF29124B,0xAD6FAC12,0xACADC625,
0xA7F18118,0xA633EB2F,0xA4755576,0xA5B73F41,0xA0F829C4,0xA13A43F3,0xA37CFDAA,0xA2BE979D,
0xB5C473D0,0xB40619E7,0xB640A7BE,0xB782CD89,0xB2CDDB0C,0xB30FB13B,0xB1490F62,0xB08B6555,
0xBBD72268,0xBA15485F,0xB853F606,0xB9919C31,0xBCDE8AB4,0xBD1CE083,0xBF5A5EDA,0xBE9834ED },
{ 0x00000000,0xB8BC6765,0xAA09C88B,0x12B5AFEE,0x8F629757,0x37DEF032,0x256B5FDC,0x9DD738B9,
0xC5B428EF,0x7D084F8A,0x6FBDE064,0xD7018701,0x4AD6BFB8,0xF26AD8DD,0xE0DF7733,0x58631056,
0x5019579F,0xE8A530FA,0xFA109F14,0x42ACF871,0xDF7BC0C8,0x67C7A7AD,0x75720843,0xCDCE6F26,
0x95AD7F70,0x2D111815,0x3FA4B7FB,0x8718D09E,0x1ACFE827,0xA2738F42,0xB0C620AC,0x087A47C9,
0xA032AF3E,0x188EC85B,0x0A3B67B5,0xB28700D0,0x2F503869,0x97EC5F0C,0x8559F0E2,0x3DE59787,
0x658687D1,0xDD3AE0B4,0xCF8F4F5A,0x7733283F,0xEAE41086,0x525877E3,0x40EDD80D,0xF851BF68,
0xF02BF8A1,0x48979FC4,0x5A22302A,0xE29E574F,0x7F496FF6,0xC7F50893,0xD540A77D,0x6DFCC018,
0x359FD04E,0x8D23B72B,0x9F9618C5,0x272A7FA0,0xBAFD4719,0x0241207C,0x10F48F92,0xA848E8F7,
0x9B14583D,0x23A83F58,0x311D90B6,0x89A1F7D3,0x1476CF6A,0xACCAA80F,0xBE7F07E1,0x06C36084,
0x5EA070D2,0xE61C17B7,0xF4A9B859,0x4C15DF3C,0xD1C2E785,0x697E80E0,0x7BCB2F0E,0xC377486B,
0xCB0D0FA2,0x73B168C7,0x6104C729,0xD9B8A04C,0x446F98F5,0xFCD3FF90,0xEE66507E,0x56DA371B,
0x0EB9274D,0xB6054028,0xA4B0EFC6,0x1C0C88A3,0x81DBB01A,0x3967D77F,0x2BD27891,0x936E1FF4,
0x3B26F703,0x839A9066,0x912F3F88,0x299358ED,0xB4446054,0x0CF80731,0x1E4DA8DF,0xA6F1CFBA,
0xFE92DFEC,0x462EB889,0x549B1767,0xEC277002,0x71F048BB,0xC94C2FDE,0xDBF98030,0x6345E755,
0x6B3FA09C,0xD383C7F9,0xC1366817,0x798A0F72,0xE45D37CB,0x5CE150AE,0x4E54FF40,0xF6E89825,
0xAE8B8873,0x1637EF16,0x048240F8,0xBC3E279D,0x21E91F24,0x99557841,0x8BE0D7AF,0x335CB0CA,
0xED59B63B,0x55E5D15E,0x47507EB0,0xFFEC19D5,0x623B216C,0xDA874609,0xC832E9E7,0x708E8E82,
0x28ED9ED4,0x9051F9B1,0x82E4565F,0x3A58313A,0xA78F0983,0x1F336EE6,0x0D86C108,0xB53AA66D,
0xBD40E1A4,0x05FC86C1,0x1749292F,0xAFF54E4A,0x322276F3,0x8A9E1196,0x982BBE78,0x2097D91D,
0x78F4C94B,0xC048AE2E,0xD2FD01C0,0x6A4166A5,0xF7965E1C,0x4F2A3979,0x5D9F9697,0xE523F1F2,
0x4D6B1905,0xF5D77E60,0xE762D18E,0x5FDEB6EB,0xC2098E52,0x7AB5E937,0x680046D9,0xD0BC21BC,
0x88DF31EA,0x3063568F,0x22D6F961,0x9A6A9E04,0x07BDA6BD,0xBF01C1D8,0xADB46E36,0x15080953,
0x1D724E9A,0xA5CE29FF,0xB77B8611,0x0FC7E174,0x9210D9CD,0x2AACBEA8,0x38191146,0x80A57623,
0xD8C66675,0x607A0110,0x72CFAEFE,0xCA73C99B,0x57A4F122,0xEF189647,0xFDAD39A9,0x45115ECC,
0x764DEE06,0xCEF18963,0xDC44268D,0x64F841E8,0xF92F7951,0x41931E34,0x5326B1DA,0xEB9AD6BF,
0xB3F9C6E9,0x0B45A18C,0x19F00E62,0xA14C6907,0x3C9B51BE,0x842736DB,0x96929935,0x2E2EFE50,
0x2654B999,0x9EE8DEFC,0x8C5D7112,0x34E11677,0xA9362ECE,0x118A49AB,0x033FE645,0xBB838120,
0xE3E09176,0x5B5CF613,0x49E959FD,0xF1553E98,0x6C820621,0xD43E6144,0xC68BCEAA,0x7E37A9CF,
0xD67F4138,0x6EC3265D,0x7C7689B3,0xC4CAEED6,0x591DD66F,0xE1A1B10A,0xF3141EE4,0x4BA87981,
0x13CB69D7,0xAB770EB2,0xB9C2A15C,0x017EC639,0x9CA9FE80,0x241599E5,0x36A0360B,0x8E1C516E,
0x866616A7,0x3EDA71C2,0x2C6FDE2C,0x94D3B949,0x090481F0,0xB1B8E695,0xA30D497B,0x1BB12E1E,
0x43D23E48,0xFB6E592D,0xE9DBF6C3,0x516791A6,0xCCB0A91F,0x740CCE7A,0x66B96194,0xDE0506F1 },
{ 0x00000000,0x3D6029B0,0x7AC05360,0x47A07AD0,0xF580A6C0,0xC8E08F70,0x8F40F5A0,0xB220DC10,
0x30704BC1,0x0D106271,0x4AB018A1,0x77D03111,0xC5F0ED01,0xF890C4B1,0xBF30BE61,0x825097D1,
0x60E09782,0x5D80BE32,0x1A20C4E2,0x2740ED52,0x95603142,0xA80018F2,0xEFA06222,0xD2C04B92,
0x5090DC43,0x6DF0F5F3,0x2A508F23,0x1730A693,0xA5107A83,0x98705333,0xDFD029E3,0xE2B00053,
0xC1C12F04,0xFCA106B4,0xBB017C64,0x866155D4,0x344189C4,0x0921A074,0x4E81DAA4,0x73E1F314,
0xF1B164C5,0xCCD14D75,0x8B7137A5,0xB6111E15,0x0431C205,0x3951EBB5,0x7EF19165,0x4391B8D5,
0xA121B886,0x9C419136,0xDBE1EBE6,0xE681C256,0x54A11E46,0x69C137F6,0x2E614D26,0x13016496,
0x9151F347,0xAC31DAF7,0xEB91A027,0xD6F18997,0x64D15587,0x59B17C37,0x1E1106E7,0x23712F57,
0x58F35849,0x659371F9,0x22330B29,0x1F532299,0xAD73FE89,0x9013D739,0xD7B3ADE9,0xEAD38459,
0x68831388,0x55E33A38,0x124340E8,0x2F236958,0x9D03B548,0xA0639CF8,0xE7C3E628,0xDAA3CF98,
0x3813CFCB,0x0573E67B,0x42D39CAB,0x7FB3B51B,0xCD93690B,0xF0F340BB,0xB7533A6B,0x8A3313DB,
0x0863840A,0x3503ADBA,0x72A3D76A,0x4FC3FEDA,0xFDE322CA,0xC0830B7A,0x872371AA,0xBA43581A,
0x9932774D,0xA4525EFD,0xE3F2242D,0xDE920D9D,0x6CB2D18D,0x51D2F83D,0x167282ED,0x2B12AB5D,
0xA9423C8C,0x9422153C,0xD3826FEC,0xEEE2465C,0x5CC29A4C,0x61A2B3FC,0x2602C92C,0x1B62E09C,
0xF9D2E0CF,0xC4B2C97F,0x8312B3AF,0xBE729A1F,0x0C52460F,0x31326FBF,0x7692156F,0x4BF23CDF,
0xC9A2AB0E,0xF4C282BE,0xB362F86E,0x8E02D1DE,0x3C220DCE,0x0142247E,0x46E25EAE,0x7B82771E,
0xB1E6B092,0x8C869922,0xCB26E3F2,0xF646CA42,0x44661652,0x79063FE2,0x3EA64532,0x03C66C82,
0x8196FB53,0xBCF6D2E3,0xFB56A833,0xC6368183,0x74165D93,0x49767423,0x0ED60EF3,0x33B62743,
0xD1062710,0xEC660EA0,0xABC67470,0x96A65DC0,0x248681D0,0x19E6A860,0x5E46D2B0,0x6326FB00,
0xE1766CD1,0xDC164561,0x9BB63FB1,0xA6D61601,0x14F6CA11,0x2996E3A1,0x6E369971,0x5356B0C1,
0x70279F96,0x4D47B626,0x0AE7CCF6,0x3787E546,0x85A73956,0xB8C710E6,0xFF676A36,0xC2074386,
0x4057D457,0x7D37FDE7,0x3A978737,0x07F7AE87,0xB5D77297,0x88B75B27,0xCF1721F7,0xF2770847,
0x10C70814,0x2DA721A4,0x6A075B74,0x576772C4,0xE547AED4,0xD8278764,0x9F87FDB4,0xA2E7D404,
0x20B743D5,0x1DD76A65,0x5A7710B5,0x67173905,0xD537E515,0xE857CCA5,0xAFF7B675,0x92979FC5,
0xE915E8DB,0xD475C16B,0x93D5BBBB,0xAEB5920B,0x1C954E1B,0x21F567AB,0x66551D7B,0x5B3534CB,
0xD965A31A,0xE4058AAA,0xA3A5F07A,0x9EC5D9CA,0x2CE505DA,0x11852C6A,0x562556BA,0x6B457F0A,
0x89F57F59,0xB49556E9,0xF3352C39,0xCE550589,0x7C75D999,0x4115F029,0x06B58AF9,0x3BD5A349,
0xB9853498,0x84E51D28,0xC34567F8,0xFE254E48,0x4C059258,0x7165BBE8,0x36C5C138,0x0BA5E888,
0x28D4C7DF,0x15B4EE6F,0x521494BF,0x6F74BD0F,0xDD54611F,0xE03448AF,0xA794327F,0x9AF41BCF,
0x18A48C1E,0x25C4A5AE,0x6264DF7E,0x5F04F6CE,0xED242ADE,0xD044036E,0x97E479BE,0xAA84500E,
0x4834505D,0x755479ED,0x32F4033D,0x0F942A8D,0xBDB4F69D,0x80D4DF2D,0xC774A5FD,0xFA148C4D,
0x78441B9C,0x4524322C,0x028448FC,0x3FE4614C,0x8DC4BD5C,0xB0A494EC,0xF704EE3C,0xCA64C78C },
{ 0x00000000,0xCB5CD3A5,0x4DC8A10B,0x869472AE,0x9B914216,0x50CD91B3,0xD659E31D,0x1D0530B8,
0xEC53826D,0x270F51C8,0xA19B2366,0x6AC7F0C3,0x77C2C07B,0xBC9E13DE,0x3A0A6170,0xF156B2D5,
0x03D6029B,0xC88AD13E,0x4E1EA390,0x85427035,0x9847408D,0x531B9328,0xD58FE186,0x1ED33223,
0xEF8580F6,0x24D95353,0xA24D21FD,0x6911F258,0x7414C2E0,0xBF481145,0x39DC63EB,0xF280B04E,
0x07AC0536,0xCCF0D693,0x4A64A43D,0x81387798,0x9C3D4720,0x57619485,0xD1F5E62B,0x1AA9358E,
0xEBFF875B,0x20A354FE,0xA6372650,0x6D6BF5F5,0x706EC54D,0xBB3216E8,0x3DA66446,0xF6FAB7E3,
0x047A07AD,0xCF26D408,0x49B2A6A6,0x82EE7503,0x9FEB45BB,0x54B7961E,0xD223E4B0,0x197F3715,
0xE82985C0,0x23755665,0xA5E124CB,0x6EBDF76E,0x73B8C7D6,0xB8E41473,0x3E7066DD,0xF52CB578,
0x0F580A6C,0xC404D9C9,0x4290AB67,0x89CC78C2,0x94C9487A,0x5F959BDF,0xD901E971,0x125D3AD4,
0xE30B8801,0x28575BA4,0xAEC3290A,0x659FFAAF,0x789ACA17,0xB3C619B2,0x35526B1C,0xFE0EB8B9,
0x0C8E08F7,0xC7D2DB52,0x4146A9FC,0x8A1A7A59,0x971F4AE1,0x5C439944,0xDAD7EBEA,0x118B384F,
0xE0DD8A9A,0x2B81593F,0xAD152B91,0x6649F834,0x7B4CC88C,0xB0101B29,0x36846987,0xFDD8BA22,
0x08F40F5A,0xC3A8DCFF,0x453CAE51,0x8E607DF4,0x93654D4C,0x58399EE9,0xDEADEC47,0x15F13FE2,
0xE4A78D37,0x2FFB5E92,0xA96F2C3C,0x6233FF99,0x7F36CF21,0xB46A1C84,0x32FE6E2A,0xF9A2BD8F,
0x0B220DC1,0xC07EDE64,0x46EAACCA,0x8DB67F6F,0x90B34FD7,0x5BEF9C72,0xDD7BEEDC,0x16273D79,
0xE7718FAC,0x2C2D5C09,0xAAB92EA7,0x61E5FD02,0x7CE0CDBA,0xB7BC1E1F,0x31286CB1,0xFA74BF14,
0x1EB014D8,0xD5ECC77D,0x5378B5D3,0x98246676,0x852156CE,0x4E7D856B,0xC8E9F7C5,0x03B52460,
0xF2E396B5,0x39BF4510,0xBF2B37BE,0x7477E41B,0x6972D4A3,0xA22E0706,0x24BA75A8,0xEFE6A60D,
0x1D661643,0xD63AC5E6,0x50AEB748,0x9BF264ED,0x86F75455,0x4DAB87F0,0xCB3FF55E,0x006326FB,
0xF135942E,0x3A69478B,0xBCFD3525,0x77A1E680,0x6AA4D638,0xA1F8059D,0x276C7733,0xEC30A496,
0x191C11EE,0xD240C24B,0x54D4B0E5,0x9F886340,0x828D53F8,0x49D1805D,0xCF45F2F3,0x04192156,
0xF54F9383,0x3E134026,0xB8873288,0x73DBE12D,0x6EDED195,0xA5820230,0x2316709E,0xE84AA33B,
0x1ACA1375,0xD196C0D0,0x5702B27E,0x9C5E61DB,0x815B5163,0x4A0782C6,0xCC93F068,0x07CF23CD,
0xF6999118,0x3DC542BD,0xBB513013,0x700DE3B6,0x6D08D30E,0xA65400AB,0x20C07205,0xEB9CA1A0,
0x11E81EB4,0xDAB4CD11,0x5C20BFBF,0x977C6C1A,0x8A795CA2,0x41258F07,0xC7B1FDA9,0x0CED2E0C,
0xFDBB9CD9,0x36E74F7C,0xB0733DD2,0x7B2FEE77,0x662ADECF,0xAD760D6A,0x2BE27FC4,0xE0BEAC61,
0x123E1C2F,0xD962CF8A,0x5FF6BD24,0x94AA6E81,0x89AF5E39,0x42F38D9C,0xC467FF32,0x0F3B2C97,
0xFE6D9E42,0x35314DE7,0xB3A53F49,0x78F9ECEC,0x65FCDC54,0xAEA00FF1,0x28347D5F,0xE368AEFA,
0x16441B82,0xDD18C827,0x5B8CBA89,0x90D0692C,0x8DD55994,0x46898A31,0xC01DF89F,0x0B412B3A,
0xFA1799EF,0x314B4A4A,0xB7DF38E4,0x7C83EB41,0x6186DBF9,0xAADA085C,0x2C4E7AF2,0xE712A957,
0x15921919,0xDECECABC,0x585AB812,0x93066BB7,0x8E035B0F,0x455F88AA,0xC3CBFA04,0x089729A1,
0xF9C19B74,0x329D48D1,0xB4093A7F,0x7F55E9DA,0x6250D962,0xA90C0AC7,0x2F987869,0xE4C4ABCC },
{ 0x00000000,0xA6770BB4,0x979F1129,0x31E81A9D,0xF44F2413,0x52382FA7,0x63D0353A,0xC5A73E8E,
0x33EF4E67,0x959845D3,0xA4705F4E,0x020754FA,0xC7A06A74,0x61D761C0,0x503F7B5D,0xF64870E9,
0x67DE9CCE,0xC1A9977A,0xF0418DE7,0x56368653,0x9391B8DD,0x35E6B369,0x040EA9F4,0xA279A240,
0x5431D2A9,0xF246D91D,0xC3AEC380,0x65D9C834,0xA07EF6BA,0x0609FD0E,0x37E1E793,0x9196EC27,
0xCFBD399C,0x69CA3228,0x582228B5,0xFE552301,0x3BF21D8F,0x9D85163B,0xAC6D0CA6,0x0A1A0712,
0xFC5277FB,0x5A257C4F,0x6BCD66D2,0xCDBA6D66,0x081D53E8,0xAE6A585C,0x9F8242C1,0x39F54975,
0xA863A552,0x0E14AEE6,0x3FFCB47B,0x998BBFCF,0x5C2C8141,0xFA5B8AF5,0xCBB39068,0x6DC49BDC,
0x9B8CEB35,0x3DFBE081,0x0C13FA1C,0xAA64F1A8,0x6FC3CF26,0xC9B4C492,0xF85CDE0F,0x5E2BD5BB,
0x440B7579,0xE27C7ECD,0xD3946450,0x75E36FE4,0xB044516A,0x16335ADE,0x27DB4043,0x81AC4BF7,
0x77E43B1E,0xD19330AA,0xE07B2A37,0x460C2183,0x83AB1F0D,0x25DC14B9,0x14340E24,0xB2430590,
0x23D5E9B7,0x85A2E203,0xB44AF89E,0x123DF32A,0xD79ACDA4,0x71EDC610,0x4005DC8D,0xE672D739,
0x103AA7D0,0xB64DAC64,0x87A5B6F9,0x21D2BD4D,0xE47583C3,0x42028877,0x73EA92EA,0xD59D995E,
0x8BB64CE5,0x2DC14751,0x1C295DCC,0xBA5E5678,0x7FF968F6,0xD98E6342,0xE86679DF,0x4E11726B,
0xB8590282,0x1E2E0936,0x2FC613AB,0x89B1181F,0x4C162691,0xEA612D25,0xDB8937B8,0x7DFE3C0C,
0xEC68D02B,0x4A1FDB9F,0x7BF7C102,0xDD80CAB6,0x1827F438,0xBE50FF8C,0x8FB8E511,0x29CFEEA5,
0xDF879E4C,0x79F095F8,0x48188F65,0xEE6F84D1,0x2BC8BA5F,0x8DBFB1EB,0xBC57AB76,0x1A20A0C2,
0x8816EAF2,0x2E61E146,0x1F89FBDB,0xB9FEF06F,0x7C59CEE1,0xDA2EC555,0xEBC6DFC8,0x4DB1D47C,
0xBBF9A495,0x1D8EAF21,0x2C66B5BC,0x8A11BE08,0x4FB68086,0xE9C18B32,0xD82991AF,0x7E5E9A1B,
0xEFC8763C,0x49BF7D88,0x78576715,0xDE206CA1,0x1B87522F,0xBDF0599B,0x8C184306,0x2A6F48B2,
0xDC27385B,0x7A5033EF,0x4BB82972,0xEDCF22C6,0x28681C48,0x8E1F17FC,0xBFF70D61,0x198006D5,
0x47ABD36E,0xE1DCD8DA,0xD034C247,0x7643C9F3,0xB3E4F77D,0x1593FCC9,0x247BE654,0x820CEDE0,
0x74449D09,0xD23396BD,0xE3DB8C20,0x45AC8794,0x800BB91A,0x267CB2AE,0x1794A833,0xB1E3A387,
0x20754FA0,0x86024414,0xB7EA5E89,0x119D553D,0xD43A6BB3,0x724D6007,0x43A57A9A,0xE5D2712E,
0x139A01C7,0xB5ED0A73,0x840510EE,0x22721B5A,0xE7D525D4,0x41A22E60,0x704A34FD,0xD63D3F49,
0xCC1D9F8B,0x6A6A943F,0x5B828EA2,0xFDF58516,0x3852BB98,0x9E25B02C,0xAFCDAAB1,0x09BAA105,
0xFFF2D1EC,0x5985DA58,0x686DC0C5,0xCE1ACB71,0x0BBDF5FF,0xADCAFE4B,0x9C22E4D6,0x3A55EF62,
0xABC30345,0x0DB408F1,0x3C5C126C,0x9A2B19D8,0x5F8C2756,0xF9FB2CE2,0xC813367F,0x6E643DCB,
0x982C4D22,0x3E5B4696,0x0FB35C0B,0xA9C457BF,0x6C636931,0xCA146285,0xFBFC7818,0x5D8B73AC,
0x03A0A617,0xA5D7ADA3,0x943FB73E,0x3248BC8A,0xF7EF8204,0x519889B0,0x6070932D,0xC6079899,
0x304FE870,0x9638E3C4,0xA7D0F959,0x01A7F2ED,0xC400CC63,0x6277C7D7,0x539FDD4A,0xF5E8D6FE,
0x647E3AD9,0xC209316D,0xF3E12BF0,0x55962044,0x90311ECA,0x3646157E,0x07AE0FE3,0xA1D90457,
0x579174BE,0xF1E67F0A,0xC00E6597,0x66796E23,0xA3DE50AD,0x05A95B19,0x34414184,0x92364A30 },
{ 0x00000000,0xCCAA009E,0x4225077D,0x8E8F07E3,0x844A0EFA,0x48E00E64,0xC66F0987,0x0AC50919,
0xD3E51BB5,0x1F4F1B2B,0x91C01CC8,0x5D6A1C56,0x57AF154F,0x9B0515D1,0x158A1232,0xD92012AC,
0x7CBB312B,0xB01131B5,0x3E9E3656,0xF23436C8,0xF8F13FD1,0x345B3F4F,0xBAD438AC,0x767E3832,
0xAF5E2A9E,0x63F42A00,0xED7B2DE3,0x21D12D7D,0x2B142464,0xE7BE24FA,0x69312319,0xA59B2387,
0xF9766256,0x35DC62C8,0xBB53652B,0x77F965B5,0x7D3C6CAC,0xB1966C32,0x3F196BD1,0xF3B36B4F,
0x2A9379E3,0xE639797D,0x68B67E9E,0xA41C7E00,0xAED97719,0x62737787,0xECFC7064,0x205670FA,
0x85CD537D,0x496753E3,0xC7E85400,0x0B42549E,0x01875D87,0xCD2D5D19,0x43A25AFA,0x8F085A64,
0x562848C8,0x9A824856,0x140D4FB5,0xD8A74F2B,0xD2624632,0x1EC846AC,0x9047414F,0x5CED41D1,
0x299DC2ED,0xE537C273,0x6BB8C590,0xA712C50E,0xADD7CC17,0x617DCC89,0xEFF2CB6A,0x2358CBF4,
0xFA78D958,0x36D2D9C6,0xB85DDE25,0x74F7DEBB,0x7E32D7A2,0xB298D73C,0x3C17D0DF,0xF0BDD041,
0x5526F3C6,0x998CF358,0x1703F4BB,0xDBA9F425,0xD16CFD3C,0x1DC6FDA2,0x9349FA41,0x5FE3FADF,
0x86C3E873,0x4A69E8ED,0xC4E6EF0E,0x084CEF90,0x0289E689,0xCE23E617,0x40ACE1F4,0x8C06E16A,
0xD0EBA0BB,0x1C41A025,0x92CEA7C6,0x5E64A758,0x54A1AE41,0x980BAEDF,0x1684A93C,0xDA2EA9A2,
0x030EBB0E,0xCFA4BB90,0x412BBC73,0x8D81BCED,0x8744B5F4,0x4BEEB56A,0xC561B289,0x09CBB217,
0xAC509190,0x60FA910E,0xEE7596ED,0x22DF9673,0x281A9F6A,0xE4B09FF4,0x6A3F9817,0xA6959889,
0x7FB58A25,0xB31F8ABB,0x3D908D58,0xF13A8DC6,0xFBFF84DF,0x37558441,0xB9DA83A2,0x7570833C,
0x533B85DA,0x9F918544,0x111E82A7,0xDDB48239,0xD7718B20,0x1BDB8BBE,0x95548C5D,0x59FE8CC3,
0x80DE9E6F,0x4C749EF1,0xC2FB9912,0x0E51998C,0x04949095,0xC83E900B,0x46B197E8,0x8A1B9776,
0x2F80B4F1,0xE32AB46F,0x6DA5B38C,0xA10FB312,0xABCABA0B,0x6760BA95,0xE9EFBD76,0x2545BDE8,
0xFC65AF44,0x30CFAFDA,0xBE40A839,0x72EAA8A7,0x782FA1BE,0xB485A120,0x3A0AA6C3,0xF6A0A65D,
0xAA4DE78C,0x66E7E712,0xE868E0F1,0x24C2E06F,0x2E07E976,0xE2ADE9E8,0x6C22EE0B,0xA088EE95,
0x79A8FC39,0xB502FCA7,0x3B8DFB44,0xF727FBDA,0xFDE2F2C3,0x3148F25D,0xBFC7F5BE,0x736DF520,
0xD6F6D6A7,0x1A5CD639,0x94D3D1DA,0x5879D144,0x52BCD85D,0x9E16D8C3,0x1099DF20,0xDC33DFBE,
0x0513CD12,0xC9B9CD8C,0x4736CA6F,0x8B9CCAF1,0x8159C3E8,0x4DF3C376,0xC37CC495,0x0FD6C40B,
0x7AA64737,0xB60C47A9,0x3883404A,0xF42940D4,0xFEEC49CD,0x32464953,0xBCC94EB0,0x70634E2E,
0xA9435C82,0x65E95C1C,0xEB665BFF,0x27CC5B61,0x2D095278,0xE1A352E6,0x6F2C5505,0xA386559B,
0x061D761C,0xCAB77682,0x44387161,0x889271FF,0x825778E6,0x4EFD7878,0xC0727F9B,0x0CD87F05,
0xD5F86DA9,0x19526D37,0x97DD6AD4,0x5B776A4A,0x51B26353,0x9D1863CD,0x1397642E,0xDF3D64B0,
0x83D02561,0x4F7A25FF,0xC1F5221C,0x0D5F2282,0x079A2B9B,0xCB302B05,0x45BF2CE6,0x89152C78,
0x50353ED4,0x9C9F3E4A,0x121039A9,0xDEBA3937,0xD47F302E,0x18D530B0,0x965A3753,0x5AF037CD,
0xFF6B144A,0x33C114D4,0xBD4E1337,0x71E413A9,0x7B211AB0,0xB78B1A2E,0x39041DCD,0xF5AE1D53,
0x2C8E0FFF,0xE0240F61,0x6EAB0882,0xA201081C,0xA8C40105,0x646E019B,0xEAE10678,0x264B06E6 }
};
inline uint32_t swap(uint32_t x)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap32(x);
#endif
#ifdef MSC_VER
return _byteswap_ulong(x);
#endif
return (x >> 24) |
((x >> 8) & 0x0000FF00) |
((x << 8) & 0x00FF0000) |
(x << 24);
}
}
/// add arbitrary number of bytes
void CRC32::add(const void* data, size_t numBytes)
{
uint32_t* current = (uint32_t*) data;
uint32_t crc = ~m_hash;
// process eight bytes at once
while (numBytes >= 8)
{
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
uint32_t one = *current++ ^ swap(crc);
uint32_t two = *current++;
crc = crc32Lookup[7][ one>>24 ] ^
crc32Lookup[6][(one>>16) & 0xFF] ^
crc32Lookup[5][(one>> 8) & 0xFF] ^
crc32Lookup[4][ one & 0xFF] ^
crc32Lookup[3][ two>>24 ] ^
crc32Lookup[2][(two>>16) & 0xFF] ^
crc32Lookup[1][(two>> 8) & 0xFF] ^
crc32Lookup[0][ two & 0xFF];
#else
uint32_t one = *current++ ^ crc;
uint32_t two = *current++;
crc = crc32Lookup[7][ one & 0xFF] ^
crc32Lookup[6][(one>> 8) & 0xFF] ^
crc32Lookup[5][(one>>16) & 0xFF] ^
crc32Lookup[4][ one>>24 ] ^
crc32Lookup[3][ two & 0xFF] ^
crc32Lookup[2][(two>> 8) & 0xFF] ^
crc32Lookup[1][(two>>16) & 0xFF] ^
crc32Lookup[0][ two>>24 ];
#endif
numBytes -= 8;
}
unsigned char* currentChar = (unsigned char*) current;
// remaining 1 to 7 bytes (standard CRC table-based algorithm)
while (numBytes--)
crc = (crc >> 8) ^ crc32Lookup[0][(crc & 0xFF) ^ *currentChar++];
m_hash = ~crc;
}
/// return latest hash as 8 hex characters
std::string CRC32::getHash()
{
// convert hash to string
static const char dec2hex[16+1] = "0123456789abcdef";
char hashBuffer[8+1];
hashBuffer[0] = dec2hex[ m_hash >> 28 ];
hashBuffer[1] = dec2hex[(m_hash >> 24) & 15];
hashBuffer[2] = dec2hex[(m_hash >> 20) & 15];
hashBuffer[3] = dec2hex[(m_hash >> 16) & 15];
hashBuffer[4] = dec2hex[(m_hash >> 12) & 15];
hashBuffer[5] = dec2hex[(m_hash >> 8) & 15];
hashBuffer[6] = dec2hex[(m_hash >> 4) & 15];
hashBuffer[7] = dec2hex[ m_hash & 15];
// zero-terminated string
hashBuffer[8] = 0;
// convert to std::string
return hashBuffer;
}
/// return latest hash as bytes
void CRC32::getHash(unsigned char buffer[CRC32::HashBytes])
{
buffer[0] = (m_hash >> 24) & 0xFF;
buffer[1] = (m_hash >> 16) & 0xFF;
buffer[2] = (m_hash >> 8) & 0xFF;
buffer[3] = m_hash & 0xFF;
}
/// compute CRC32 of a memory block
std::string CRC32::operator()(const void* data, size_t numBytes)
{
reset();
add(data, numBytes);
return getHash();
}
/// compute CRC32 of a string, excluding final zero
std::string CRC32::operator()(const std::string& text)
{
reset();
add(text.c_str(), text.size());
return getHash();
}

69
external/Common/crc32.h vendored Normal file
View File

@ -0,0 +1,69 @@
// //////////////////////////////////////////////////////////
// crc32.h
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#pragma once
//#include "hash.h"
#include <string>
// define fixed size integer types
#ifdef _MSC_VER
// Windows
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
#else
// GCC
#include <stdint.h>
#endif
/// compute CRC32 hash, based on Intel's Slicing-by-8 algorithm
/** Usage:
CRC32 crc32;
std::string myHash = crc32("Hello World"); // std::string
std::string myHash2 = crc32("How are you", 11); // arbitrary data, 11 bytes
// or in a streaming fashion:
CRC32 crc32;
while (more data available)
crc32.add(pointer to fresh data, number of new bytes);
std::string myHash3 = crc32.getHash();
Note:
You can find code for the faster Slicing-by-16 algorithm on my website, too:
http://create.stephan-brumme.com/crc32/
Its unrolled version is about twice as fast but its look-up table doubled in size as well.
*/
class CRC32 //: public Hash
{
public:
/// hash is 4 bytes long
enum { HashBytes = 4 };
/// same as reset()
CRC32();
/// compute CRC32 of a memory block
std::string operator()(const void* data, size_t numBytes);
/// compute CRC32 of a string, excluding final zero
std::string operator()(const std::string& text);
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as 8 hex characters
std::string getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart
void reset();
private:
/// hash
uint32_t m_hash;
};

109
external/Common/digest.cpp vendored Normal file
View File

@ -0,0 +1,109 @@
// //////////////////////////////////////////////////////////
// digest.cpp
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
// g++ -O3 digest.cpp crc32.cpp md5.cpp sha1.cpp sha256.cpp keccak.cpp sha3.cpp -o digest
#include "crc32.h"
#include "md5.h"
#include "sha1.h"
#include "sha256.h"
#include "keccak.h"
#include "sha3.h"
#include <iostream>
#include <fstream>
int main(int argc, char** argv)
{
// syntax check
if (argc < 2 || argc > 3)
{
std::cout << "./digest filename [--crc|--md5|--sha1|--sha256|--keccak|--sha3]" << std::endl;
return 1;
}
// parameters
std::string filename = argv[1];
std::string algorithm = argc == 3 ? argv[2] : "";
bool computeCrc32 = algorithm.empty() || algorithm == "--crc";
bool computeMd5 = algorithm.empty() || algorithm == "--md5";
bool computeSha1 = algorithm.empty() || algorithm == "--sha1";
bool computeSha2 = algorithm.empty() || algorithm == "--sha2" || algorithm == "--sha256";
bool computeKeccak = algorithm.empty() || algorithm == "--keccak";
bool computeSha3 = algorithm.empty() || algorithm == "--sha3";
CRC32 digestCrc32;
MD5 digestMd5;
SHA1 digestSha1;
SHA256 digestSha2;
Keccak digestKeccak(Keccak::Keccak256);
SHA3 digestSha3 (SHA3 ::Bits256);
// each cycle processes about 1 MByte (divisible by 144 => improves Keccak/SHA3 performance)
const size_t BufferSize = 144*7*1024;
char* buffer = new char[BufferSize];
// select input source: either file or standard-in
std::ifstream file;
std::istream* input = NULL;
// accept std::cin, syntax will be: "./digest - --sha3 < data"
if (filename == "-")
{
input = &std::cin;
}
else
{
// open file
file.open(filename.c_str(), std::ios::in | std::ios::binary);
if (!file)
{
std::cerr << "Can't open '" << filename << "'" << std::endl;
return 2;
}
input = &file;
}
// process file
while (*input)
{
input->read(buffer, BufferSize);
std::size_t numBytesRead = size_t(input->gcount());
if (computeCrc32)
digestCrc32 .add(buffer, numBytesRead);
if (computeMd5)
digestMd5 .add(buffer, numBytesRead);
if (computeSha1)
digestSha1 .add(buffer, numBytesRead);
if (computeSha2)
digestSha2 .add(buffer, numBytesRead);
if (computeKeccak)
digestKeccak.add(buffer, numBytesRead);
if (computeSha3)
digestSha3 .add(buffer, numBytesRead);
}
// clean up
file.close();
delete[] buffer;
// show results
if (computeCrc32)
std::cout << "CRC32: " << digestCrc32 .getHash() << std::endl;
if (computeMd5)
std::cout << "MD5: " << digestMd5 .getHash() << std::endl;
if (computeSha1)
std::cout << "SHA1: " << digestSha1 .getHash() << std::endl;
if (computeSha2)
std::cout << "SHA2/256: " << digestSha2 .getHash() << std::endl;
if (computeKeccak)
std::cout << "Keccak/256: " << digestKeccak.getHash() << std::endl;
if (computeSha3)
std::cout << "SHA3/256: " << digestSha3 .getHash() << std::endl;
return 0;
}

14
external/Common/endian.h vendored Normal file
View File

@ -0,0 +1,14 @@
#ifndef _ENDIAN_H_
#define _ENDIAN_H_
#if defined(__MINGW32__) || defined(__MINGW64__)
// Workaround for MinGW and it's lack of <endian.h> file
#define __BYTE_ORDER __BYTE_ORDER__
#define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
#define __BIG_ENDIAN __ORDER_BIG_ENDIAN__
#elif !defined(_MSC_VER)
// Just include the system file
#include <endian.h>
#endif
#endif // _ENDIAN_H_

28
external/Common/hash.h vendored Normal file
View File

@ -0,0 +1,28 @@
// //////////////////////////////////////////////////////////
// hash.h
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#pragma once
#include <string>
/// abstract base class
class Hash
{
public:
/// compute hash of a memory block
virtual std::string operator()(const void* data, size_t numBytes) = 0;
/// compute hash of a string, excluding final zero
virtual std::string operator()(const std::string& text) = 0;
/// add arbitrary number of bytes
virtual void add(const void* data, size_t numBytes) = 0;
/// return latest hash as hex characters
virtual std::string getHash() = 0;
/// restart
virtual void reset() = 0;
};

7
external/Common/hash_license.txt vendored Normal file
View File

@ -0,0 +1,7 @@
All source code published on http://create.stephan-brumme.com and its sub-pages is licensed similar to the zlib license:
This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.

83
external/Common/hmac.h vendored Normal file
View File

@ -0,0 +1,83 @@
// //////////////////////////////////////////////////////////
// hmac.h
// Copyright (c) 2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#pragma once
// based on http://tools.ietf.org/html/rfc2104
// see also http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
/** Usage:
std::string msg = "The quick brown fox jumps over the lazy dog";
std::string key = "key";
std::string md5hmac = hmac< MD5 >(msg, key);
std::string sha1hmac = hmac< SHA1 >(msg, key);
std::string sha2hmac = hmac<SHA256>(msg, key);
Note:
To keep my code simple, HMAC computation currently needs the whole message at once.
This is in contrast to the hashes MD5, SHA1, etc. where an add() method is available
for incremental computation.
You can use any hash for HMAC as long as it provides:
- constant HashMethod::BlockSize (typically 64)
- constant HashMethod::HashBytes (length of hash in bytes, e.g. 20 for SHA1)
- HashMethod::add(buffer, bufferSize)
- HashMethod::getHash(unsigned char buffer[HashMethod::BlockSize])
*/
#include <string>
#include <cstring> // memcpy
/// compute HMAC hash of data and key using MD5, SHA1 or SHA256
template <typename HashMethod>
std::string hmac(const void* data, size_t numDataBytes, const void* key, size_t numKeyBytes)
{
// initialize key with zeros
unsigned char usedKey[HashMethod::BlockSize] = {0};
// adjust length of key: must contain exactly blockSize bytes
if (numKeyBytes <= HashMethod::BlockSize)
{
// copy key
memcpy(usedKey, key, numKeyBytes);
}
else
{
// shorten key: usedKey = hashed(key)
HashMethod keyHasher;
keyHasher.add(key, numKeyBytes);
keyHasher.getHash(usedKey);
}
// create initial XOR padding
for (size_t i = 0; i < HashMethod::BlockSize; i++)
usedKey[i] ^= 0x36;
// inside = hash((usedKey ^ 0x36) + data)
unsigned char inside[HashMethod::HashBytes];
HashMethod insideHasher;
insideHasher.add(usedKey, HashMethod::BlockSize);
insideHasher.add(data, numDataBytes);
insideHasher.getHash(inside);
// undo usedKey's previous 0x36 XORing and apply a XOR by 0x5C
for (size_t i = 0; i < HashMethod::BlockSize; i++)
usedKey[i] ^= 0x5C ^ 0x36;
// hash((usedKey ^ 0x5C) + hash((usedKey ^ 0x36) + data))
HashMethod finalHasher;
finalHasher.add(usedKey, HashMethod::BlockSize);
finalHasher.add(inside, HashMethod::HashBytes);
return finalHasher.getHash();
}
/// convenience function for std::string
template <typename HashMethod>
std::string hmac(const std::string& data, const std::string& key)
{
return hmac<HashMethod>(data.c_str(), data.size(), key.c_str(), key.size());
}

289
external/Common/keccak.cpp vendored Normal file
View File

@ -0,0 +1,289 @@
// //////////////////////////////////////////////////////////
// keccak.cpp
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#include "keccak.h"
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
#ifndef _MSC_VER
#include <endian.h>
#endif
/// same as reset()
Keccak::Keccak(Bits bits)
: m_blockSize(200 - 2 * (bits / 8)),
m_bits(bits)
{
reset();
}
/// restart
void Keccak::reset()
{
for (size_t i = 0; i < StateSize; i++)
m_hash[i] = 0;
m_numBytes = 0;
m_bufferSize = 0;
}
/// constants and local helper functions
namespace
{
const unsigned int KeccakRounds = 24;
const uint64_t XorMasks[KeccakRounds] =
{
0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
};
/// rotate left and wrap around to the right
inline uint64_t rotateLeft(uint64_t x, uint8_t numBits)
{
return (x << numBits) | (x >> (64 - numBits));
}
/// convert litte vs big endian
inline uint64_t swap(uint64_t x)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap64(x);
#endif
#ifdef _MSC_VER
return _byteswap_uint64(x);
#endif
return (x >> 56) |
((x >> 40) & 0x000000000000FF00ULL) |
((x >> 24) & 0x0000000000FF0000ULL) |
((x >> 8) & 0x00000000FF000000ULL) |
((x << 8) & 0x000000FF00000000ULL) |
((x << 24) & 0x0000FF0000000000ULL) |
((x << 40) & 0x00FF000000000000ULL) |
(x << 56);
}
/// return x % 5 for 0 <= x <= 9
unsigned int mod5(unsigned int x)
{
if (x < 5)
return x;
return x - 5;
}
}
/// process a full block
void Keccak::processBlock(const void* data)
{
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
#define LITTLEENDIAN(x) swap(x)
#else
#define LITTLEENDIAN(x) (x)
#endif
const uint64_t* data64 = (const uint64_t*) data;
// mix data into state
for (unsigned int i = 0; i < m_blockSize / 8; i++)
m_hash[i] ^= LITTLEENDIAN(data64[i]);
// re-compute state
for (unsigned int round = 0; round < KeccakRounds; round++)
{
// Theta
uint64_t coefficients[5];
for (unsigned int i = 0; i < 5; i++)
coefficients[i] = m_hash[i] ^ m_hash[i + 5] ^ m_hash[i + 10] ^ m_hash[i + 15] ^ m_hash[i + 20];
for (unsigned int i = 0; i < 5; i++)
{
uint64_t one = coefficients[mod5(i + 4)] ^ rotateLeft(coefficients[mod5(i + 1)], 1);
m_hash[i ] ^= one;
m_hash[i + 5] ^= one;
m_hash[i + 10] ^= one;
m_hash[i + 15] ^= one;
m_hash[i + 20] ^= one;
}
// temporary
uint64_t one;
// Rho Pi
uint64_t last = m_hash[1];
one = m_hash[10]; m_hash[10] = rotateLeft(last, 1); last = one;
one = m_hash[ 7]; m_hash[ 7] = rotateLeft(last, 3); last = one;
one = m_hash[11]; m_hash[11] = rotateLeft(last, 6); last = one;
one = m_hash[17]; m_hash[17] = rotateLeft(last, 10); last = one;
one = m_hash[18]; m_hash[18] = rotateLeft(last, 15); last = one;
one = m_hash[ 3]; m_hash[ 3] = rotateLeft(last, 21); last = one;
one = m_hash[ 5]; m_hash[ 5] = rotateLeft(last, 28); last = one;
one = m_hash[16]; m_hash[16] = rotateLeft(last, 36); last = one;
one = m_hash[ 8]; m_hash[ 8] = rotateLeft(last, 45); last = one;
one = m_hash[21]; m_hash[21] = rotateLeft(last, 55); last = one;
one = m_hash[24]; m_hash[24] = rotateLeft(last, 2); last = one;
one = m_hash[ 4]; m_hash[ 4] = rotateLeft(last, 14); last = one;
one = m_hash[15]; m_hash[15] = rotateLeft(last, 27); last = one;
one = m_hash[23]; m_hash[23] = rotateLeft(last, 41); last = one;
one = m_hash[19]; m_hash[19] = rotateLeft(last, 56); last = one;
one = m_hash[13]; m_hash[13] = rotateLeft(last, 8); last = one;
one = m_hash[12]; m_hash[12] = rotateLeft(last, 25); last = one;
one = m_hash[ 2]; m_hash[ 2] = rotateLeft(last, 43); last = one;
one = m_hash[20]; m_hash[20] = rotateLeft(last, 62); last = one;
one = m_hash[14]; m_hash[14] = rotateLeft(last, 18); last = one;
one = m_hash[22]; m_hash[22] = rotateLeft(last, 39); last = one;
one = m_hash[ 9]; m_hash[ 9] = rotateLeft(last, 61); last = one;
one = m_hash[ 6]; m_hash[ 6] = rotateLeft(last, 20); last = one;
m_hash[ 1] = rotateLeft(last, 44);
// Chi
for (unsigned int j = 0; j < 25; j += 5)
{
// temporaries
uint64_t one = m_hash[j];
uint64_t two = m_hash[j + 1];
m_hash[j] ^= m_hash[j + 2] & ~two;
m_hash[j + 1] ^= m_hash[j + 3] & ~m_hash[j + 2];
m_hash[j + 2] ^= m_hash[j + 4] & ~m_hash[j + 3];
m_hash[j + 3] ^= one & ~m_hash[j + 4];
m_hash[j + 4] ^= two & ~one;
}
// Iota
m_hash[0] ^= XorMasks[round];
}
}
/// add arbitrary number of bytes
void Keccak::add(const void* data, size_t numBytes)
{
const uint8_t* current = (const uint8_t*) data;
if (m_bufferSize > 0)
{
while (numBytes > 0 && m_bufferSize < m_blockSize)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
// full buffer
if (m_bufferSize == m_blockSize)
{
processBlock((void*)m_buffer);
m_numBytes += m_blockSize;
m_bufferSize = 0;
}
// no more data ?
if (numBytes == 0)
return;
// process full blocks
while (numBytes >= m_blockSize)
{
processBlock(current);
current += m_blockSize;
m_numBytes += m_blockSize;
numBytes -= m_blockSize;
}
// keep remaining bytes in buffer
while (numBytes > 0)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
/// process everything left in the internal buffer
void Keccak::processBuffer()
{
unsigned int blockSize = 200 - 2 * (m_bits / 8);
// add padding
size_t offset = m_bufferSize;
// add a "1" byte
m_buffer[offset++] = 1;
// fill with zeros
while (offset < blockSize)
m_buffer[offset++] = 0;
// and add a single set bit
m_buffer[blockSize - 1] |= 0x80;
processBlock(m_buffer);
}
/// return latest hash as 16 hex characters
std::string Keccak::getHash()
{
// process remaining bytes
processBuffer();
// convert hash to string
static const char dec2hex[16 + 1] = "0123456789abcdef";
// number of significant elements in hash (uint64_t)
unsigned int hashLength = m_bits / 64;
std::string result;
for (unsigned int i = 0; i < hashLength; i++)
for (unsigned int j = 0; j < 8; j++) // 64 bits => 8 bytes
{
// convert a byte to hex
unsigned char oneByte = (unsigned char) (m_hash[i] >> (8 * j));
result += dec2hex[oneByte >> 4];
result += dec2hex[oneByte & 15];
}
// Keccak224's last entry in m_hash provides only 32 bits instead of 64 bits
unsigned int remainder = m_bits - hashLength * 64;
unsigned int processed = 0;
while (processed < remainder)
{
// convert a byte to hex
unsigned char oneByte = (unsigned char) (m_hash[hashLength] >> processed);
result += dec2hex[oneByte >> 4];
result += dec2hex[oneByte & 15];
processed += 8;
}
return result;
}
/// compute Keccak hash of a memory block
std::string Keccak::operator()(const void* data, size_t numBytes)
{
reset();
add(data, numBytes);
return getHash();
}
/// compute Keccak hash of a string, excluding final zero
std::string Keccak::operator()(const std::string& text)
{
reset();
add(text.c_str(), text.size());
return getHash();
}

81
external/Common/keccak.h vendored Normal file
View File

@ -0,0 +1,81 @@
// //////////////////////////////////////////////////////////
// keccak.h
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#pragma once
//#include "hash.h"
#include <string>
// define fixed size integer types
#ifdef _MSC_VER
// Windows
typedef unsigned __int8 uint8_t;
typedef unsigned __int64 uint64_t;
#else
// GCC
#include <stdint.h>
#endif
/// compute Keccak hash (designated SHA3)
/** Usage:
Keccak keccak;
std::string myHash = keccak("Hello World"); // std::string
std::string myHash2 = keccak("How are you", 11); // arbitrary data, 11 bytes
// or in a streaming fashion:
Keccak keccak;
while (more data available)
keccak.add(pointer to fresh data, number of new bytes);
std::string myHash3 = keccak.getHash();
*/
class Keccak //: public Hash
{
public:
/// algorithm variants
enum Bits { Keccak224 = 224, Keccak256 = 256, Keccak384 = 384, Keccak512 = 512 };
/// same as reset()
explicit Keccak(Bits bits = Keccak256);
/// compute hash of a memory block
std::string operator()(const void* data, size_t numBytes);
/// compute hash of a string, excluding final zero
std::string operator()(const std::string& text);
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as hex characters
std::string getHash();
/// restart
void reset();
private:
/// process a full block
void processBlock(const void* data);
/// process everything left in the internal buffer
void processBuffer();
/// 1600 bits, stored as 25x64 bit, BlockSize is no more than 1152 bits (Keccak224)
enum { StateSize = 1600 / (8 * 8),
MaxBlockSize = 200 - 2 * (224 / 8) };
/// hash
uint64_t m_hash[StateSize];
/// size of processed data in bytes
uint64_t m_numBytes;
/// block size (less or equal to MaxBlockSize)
size_t m_blockSize;
/// valid bytes in m_buffer
size_t m_bufferSize;
/// bytes not processed yet
uint8_t m_buffer[MaxBlockSize];
/// variant
Bits m_bits;
};

380
external/Common/md5.cpp vendored Normal file
View File

@ -0,0 +1,380 @@
// //////////////////////////////////////////////////////////
// md5.cpp
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#include "md5.h"
#ifndef _MSC_VER
#include <endian.h>
#endif
/// same as reset()
MD5::MD5()
{
reset();
}
/// restart
void MD5::reset()
{
m_numBytes = 0;
m_bufferSize = 0;
// according to RFC 1321
m_hash[0] = 0x67452301;
m_hash[1] = 0xefcdab89;
m_hash[2] = 0x98badcfe;
m_hash[3] = 0x10325476;
}
namespace
{
// mix functions for processBlock()
inline uint32_t f1(uint32_t b, uint32_t c, uint32_t d)
{
return d ^ (b & (c ^ d)); // original: f = (b & c) | ((~b) & d);
}
inline uint32_t f2(uint32_t b, uint32_t c, uint32_t d)
{
return c ^ (d & (b ^ c)); // original: f = (b & d) | (c & (~d));
}
inline uint32_t f3(uint32_t b, uint32_t c, uint32_t d)
{
return b ^ c ^ d;
}
inline uint32_t f4(uint32_t b, uint32_t c, uint32_t d)
{
return c ^ (b | ~d);
}
inline uint32_t rotate(uint32_t a, uint32_t c)
{
return (a << c) | (a >> (32 - c));
}
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
inline uint32_t swap(uint32_t x)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap32(x);
#endif
#ifdef MSC_VER
return _byteswap_ulong(x);
#endif
return (x >> 24) |
((x >> 8) & 0x0000FF00) |
((x << 8) & 0x00FF0000) |
(x << 24);
}
#endif
}
/// process 64 bytes
void MD5::processBlock(const void* data)
{
// get last hash
uint32_t a = m_hash[0];
uint32_t b = m_hash[1];
uint32_t c = m_hash[2];
uint32_t d = m_hash[3];
// data represented as 16x 32-bit words
const uint32_t* words = (uint32_t*) data;
// computations are little endian, swap data if necessary
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
#define LITTLEENDIAN(x) swap(x)
#else
#define LITTLEENDIAN(x) (x)
#endif
// first round
uint32_t word0 = LITTLEENDIAN(words[ 0]);
a = rotate(a + f1(b,c,d) + word0 + 0xd76aa478, 7) + b;
uint32_t word1 = LITTLEENDIAN(words[ 1]);
d = rotate(d + f1(a,b,c) + word1 + 0xe8c7b756, 12) + a;
uint32_t word2 = LITTLEENDIAN(words[ 2]);
c = rotate(c + f1(d,a,b) + word2 + 0x242070db, 17) + d;
uint32_t word3 = LITTLEENDIAN(words[ 3]);
b = rotate(b + f1(c,d,a) + word3 + 0xc1bdceee, 22) + c;
uint32_t word4 = LITTLEENDIAN(words[ 4]);
a = rotate(a + f1(b,c,d) + word4 + 0xf57c0faf, 7) + b;
uint32_t word5 = LITTLEENDIAN(words[ 5]);
d = rotate(d + f1(a,b,c) + word5 + 0x4787c62a, 12) + a;
uint32_t word6 = LITTLEENDIAN(words[ 6]);
c = rotate(c + f1(d,a,b) + word6 + 0xa8304613, 17) + d;
uint32_t word7 = LITTLEENDIAN(words[ 7]);
b = rotate(b + f1(c,d,a) + word7 + 0xfd469501, 22) + c;
uint32_t word8 = LITTLEENDIAN(words[ 8]);
a = rotate(a + f1(b,c,d) + word8 + 0x698098d8, 7) + b;
uint32_t word9 = LITTLEENDIAN(words[ 9]);
d = rotate(d + f1(a,b,c) + word9 + 0x8b44f7af, 12) + a;
uint32_t word10 = LITTLEENDIAN(words[10]);
c = rotate(c + f1(d,a,b) + word10 + 0xffff5bb1, 17) + d;
uint32_t word11 = LITTLEENDIAN(words[11]);
b = rotate(b + f1(c,d,a) + word11 + 0x895cd7be, 22) + c;
uint32_t word12 = LITTLEENDIAN(words[12]);
a = rotate(a + f1(b,c,d) + word12 + 0x6b901122, 7) + b;
uint32_t word13 = LITTLEENDIAN(words[13]);
d = rotate(d + f1(a,b,c) + word13 + 0xfd987193, 12) + a;
uint32_t word14 = LITTLEENDIAN(words[14]);
c = rotate(c + f1(d,a,b) + word14 + 0xa679438e, 17) + d;
uint32_t word15 = LITTLEENDIAN(words[15]);
b = rotate(b + f1(c,d,a) + word15 + 0x49b40821, 22) + c;
// second round
a = rotate(a + f2(b,c,d) + word1 + 0xf61e2562, 5) + b;
d = rotate(d + f2(a,b,c) + word6 + 0xc040b340, 9) + a;
c = rotate(c + f2(d,a,b) + word11 + 0x265e5a51, 14) + d;
b = rotate(b + f2(c,d,a) + word0 + 0xe9b6c7aa, 20) + c;
a = rotate(a + f2(b,c,d) + word5 + 0xd62f105d, 5) + b;
d = rotate(d + f2(a,b,c) + word10 + 0x02441453, 9) + a;
c = rotate(c + f2(d,a,b) + word15 + 0xd8a1e681, 14) + d;
b = rotate(b + f2(c,d,a) + word4 + 0xe7d3fbc8, 20) + c;
a = rotate(a + f2(b,c,d) + word9 + 0x21e1cde6, 5) + b;
d = rotate(d + f2(a,b,c) + word14 + 0xc33707d6, 9) + a;
c = rotate(c + f2(d,a,b) + word3 + 0xf4d50d87, 14) + d;
b = rotate(b + f2(c,d,a) + word8 + 0x455a14ed, 20) + c;
a = rotate(a + f2(b,c,d) + word13 + 0xa9e3e905, 5) + b;
d = rotate(d + f2(a,b,c) + word2 + 0xfcefa3f8, 9) + a;
c = rotate(c + f2(d,a,b) + word7 + 0x676f02d9, 14) + d;
b = rotate(b + f2(c,d,a) + word12 + 0x8d2a4c8a, 20) + c;
// third round
a = rotate(a + f3(b,c,d) + word5 + 0xfffa3942, 4) + b;
d = rotate(d + f3(a,b,c) + word8 + 0x8771f681, 11) + a;
c = rotate(c + f3(d,a,b) + word11 + 0x6d9d6122, 16) + d;
b = rotate(b + f3(c,d,a) + word14 + 0xfde5380c, 23) + c;
a = rotate(a + f3(b,c,d) + word1 + 0xa4beea44, 4) + b;
d = rotate(d + f3(a,b,c) + word4 + 0x4bdecfa9, 11) + a;
c = rotate(c + f3(d,a,b) + word7 + 0xf6bb4b60, 16) + d;
b = rotate(b + f3(c,d,a) + word10 + 0xbebfbc70, 23) + c;
a = rotate(a + f3(b,c,d) + word13 + 0x289b7ec6, 4) + b;
d = rotate(d + f3(a,b,c) + word0 + 0xeaa127fa, 11) + a;
c = rotate(c + f3(d,a,b) + word3 + 0xd4ef3085, 16) + d;
b = rotate(b + f3(c,d,a) + word6 + 0x04881d05, 23) + c;
a = rotate(a + f3(b,c,d) + word9 + 0xd9d4d039, 4) + b;
d = rotate(d + f3(a,b,c) + word12 + 0xe6db99e5, 11) + a;
c = rotate(c + f3(d,a,b) + word15 + 0x1fa27cf8, 16) + d;
b = rotate(b + f3(c,d,a) + word2 + 0xc4ac5665, 23) + c;
// fourth round
a = rotate(a + f4(b,c,d) + word0 + 0xf4292244, 6) + b;
d = rotate(d + f4(a,b,c) + word7 + 0x432aff97, 10) + a;
c = rotate(c + f4(d,a,b) + word14 + 0xab9423a7, 15) + d;
b = rotate(b + f4(c,d,a) + word5 + 0xfc93a039, 21) + c;
a = rotate(a + f4(b,c,d) + word12 + 0x655b59c3, 6) + b;
d = rotate(d + f4(a,b,c) + word3 + 0x8f0ccc92, 10) + a;
c = rotate(c + f4(d,a,b) + word10 + 0xffeff47d, 15) + d;
b = rotate(b + f4(c,d,a) + word1 + 0x85845dd1, 21) + c;
a = rotate(a + f4(b,c,d) + word8 + 0x6fa87e4f, 6) + b;
d = rotate(d + f4(a,b,c) + word15 + 0xfe2ce6e0, 10) + a;
c = rotate(c + f4(d,a,b) + word6 + 0xa3014314, 15) + d;
b = rotate(b + f4(c,d,a) + word13 + 0x4e0811a1, 21) + c;
a = rotate(a + f4(b,c,d) + word4 + 0xf7537e82, 6) + b;
d = rotate(d + f4(a,b,c) + word11 + 0xbd3af235, 10) + a;
c = rotate(c + f4(d,a,b) + word2 + 0x2ad7d2bb, 15) + d;
b = rotate(b + f4(c,d,a) + word9 + 0xeb86d391, 21) + c;
// update hash
m_hash[0] += a;
m_hash[1] += b;
m_hash[2] += c;
m_hash[3] += d;
}
/// add arbitrary number of bytes
void MD5::add(const void* data, size_t numBytes)
{
const uint8_t* current = (const uint8_t*) data;
if (m_bufferSize > 0)
{
while (numBytes > 0 && m_bufferSize < BlockSize)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
// full buffer
if (m_bufferSize == BlockSize)
{
processBlock(m_buffer);
m_numBytes += BlockSize;
m_bufferSize = 0;
}
// no more data ?
if (numBytes == 0)
return;
// process full blocks
while (numBytes >= BlockSize)
{
processBlock(current);
current += BlockSize;
m_numBytes += BlockSize;
numBytes -= BlockSize;
}
// keep remaining bytes in buffer
while (numBytes > 0)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
/// process final block, less than 64 bytes
void MD5::processBuffer()
{
// the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
// - append "1" bit to message
// - append "0" bits until message length in bit mod 512 is 448
// - append length as 64 bit integer
// number of bits
size_t paddedLength = m_bufferSize * 8;
// plus one bit set to 1 (always appended)
paddedLength++;
// number of bits must be (numBits % 512) = 448
size_t lower11Bits = paddedLength & 511;
if (lower11Bits <= 448)
paddedLength += 448 - lower11Bits;
else
paddedLength += 512 + 448 - lower11Bits;
// convert from bits to bytes
paddedLength /= 8;
// only needed if additional data flows over into a second block
unsigned char extra[BlockSize];
// append a "1" bit, 128 => binary 10000000
if (m_bufferSize < BlockSize)
m_buffer[m_bufferSize] = 128;
else
extra[0] = 128;
size_t i;
for (i = m_bufferSize + 1; i < BlockSize; i++)
m_buffer[i] = 0;
for (; i < paddedLength; i++)
extra[i - BlockSize] = 0;
// add message length in bits as 64 bit number
uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
// find right position
unsigned char* addLength;
if (paddedLength < BlockSize)
addLength = m_buffer + paddedLength;
else
addLength = extra + paddedLength - BlockSize;
// must be little endian
*addLength++ = msgBits & 0xFF; msgBits >>= 8;
*addLength++ = msgBits & 0xFF; msgBits >>= 8;
*addLength++ = msgBits & 0xFF; msgBits >>= 8;
*addLength++ = msgBits & 0xFF; msgBits >>= 8;
*addLength++ = msgBits & 0xFF; msgBits >>= 8;
*addLength++ = msgBits & 0xFF; msgBits >>= 8;
*addLength++ = msgBits & 0xFF; msgBits >>= 8;
*addLength++ = msgBits & 0xFF;
// process blocks
processBlock(m_buffer);
// flowed over into a second block ?
if (paddedLength > BlockSize)
processBlock(extra);
}
/// return latest hash as 32 hex characters
std::string MD5::getHash()
{
// compute hash (as raw bytes)
unsigned char rawHash[HashBytes];
getHash(rawHash);
// convert to hex string
std::string result;
result.reserve(2 * HashBytes);
for (int i = 0; i < HashBytes; i++)
{
static const char dec2hex[16+1] = "0123456789abcdef";
result += dec2hex[(rawHash[i] >> 4) & 15];
result += dec2hex[ rawHash[i] & 15];
}
return result;
}
/// return latest hash as bytes
void MD5::getHash(unsigned char buffer[MD5::HashBytes])
{
// save old hash if buffer is partially filled
uint32_t oldHash[HashValues];
for (int i = 0; i < HashValues; i++)
oldHash[i] = m_hash[i];
// process remaining bytes
processBuffer();
unsigned char* current = buffer;
for (int i = 0; i < HashValues; i++)
{
*current++ = m_hash[i] & 0xFF;
*current++ = (m_hash[i] >> 8) & 0xFF;
*current++ = (m_hash[i] >> 16) & 0xFF;
*current++ = (m_hash[i] >> 24) & 0xFF;
// restore old hash
m_hash[i] = oldHash[i];
}
}
/// compute MD5 of a memory block
std::string MD5::operator()(const void* data, size_t numBytes)
{
reset();
add(data, numBytes);
return getHash();
}
/// compute MD5 of a string, excluding final zero
std::string MD5::operator()(const std::string& text)
{
reset();
add(text.c_str(), text.size());
return getHash();
}

78
external/Common/md5.h vendored Normal file
View File

@ -0,0 +1,78 @@
// //////////////////////////////////////////////////////////
// md5.h
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#pragma once
//#include "hash.h"
#include <string>
// define fixed size integer types
#ifdef _MSC_VER
// Windows
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#else
// GCC
#include <stdint.h>
#endif
/// compute MD5 hash
/** Usage:
MD5 md5;
std::string myHash = md5("Hello World"); // std::string
std::string myHash2 = md5("How are you", 11); // arbitrary data, 11 bytes
// or in a streaming fashion:
MD5 md5;
while (more data available)
md5.add(pointer to fresh data, number of new bytes);
std::string myHash3 = md5.getHash();
*/
class MD5 //: public Hash
{
public:
/// split into 64 byte blocks (=> 512 bits), hash is 16 bytes long
enum { BlockSize = 512 / 8, HashBytes = 16 };
/// same as reset()
MD5();
/// compute MD5 of a memory block
std::string operator()(const void* data, size_t numBytes);
/// compute MD5 of a string, excluding final zero
std::string operator()(const std::string& text);
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as 32 hex characters
std::string getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart
void reset();
private:
/// process 64 bytes
void processBlock(const void* data);
/// process everything left in the internal buffer
void processBuffer();
/// size of processed data in bytes
uint64_t m_numBytes;
/// valid bytes in m_buffer
size_t m_bufferSize;
/// bytes not processed yet
uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 };
/// hash, stored as integers
uint32_t m_hash[HashValues];
};

326
external/Common/sha1.cpp vendored Normal file
View File

@ -0,0 +1,326 @@
// //////////////////////////////////////////////////////////
// sha1.cpp
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#include "sha1.h"
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
#ifndef _MSC_VER
#include <endian.h>
#endif
/// same as reset()
SHA1::SHA1()
{
reset();
}
/// restart
void SHA1::reset()
{
m_numBytes = 0;
m_bufferSize = 0;
// according to RFC 1321
m_hash[0] = 0x67452301;
m_hash[1] = 0xefcdab89;
m_hash[2] = 0x98badcfe;
m_hash[3] = 0x10325476;
m_hash[4] = 0xc3d2e1f0;
}
namespace
{
// mix functions for processBlock()
inline uint32_t f1(uint32_t b, uint32_t c, uint32_t d)
{
return d ^ (b & (c ^ d)); // original: f = (b & c) | ((~b) & d);
}
inline uint32_t f2(uint32_t b, uint32_t c, uint32_t d)
{
return b ^ c ^ d;
}
inline uint32_t f3(uint32_t b, uint32_t c, uint32_t d)
{
return (b & c) | (b & d) | (c & d);
}
inline uint32_t rotate(uint32_t a, uint32_t c)
{
return (a << c) | (a >> (32 - c));
}
inline uint32_t swap(uint32_t x)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap32(x);
#endif
#ifdef MSC_VER
return _byteswap_ulong(x);
#endif
return (x >> 24) |
((x >> 8) & 0x0000FF00) |
((x << 8) & 0x00FF0000) |
(x << 24);
}
}
/// process 64 bytes
void SHA1::processBlock(const void* data)
{
// get last hash
uint32_t a = m_hash[0];
uint32_t b = m_hash[1];
uint32_t c = m_hash[2];
uint32_t d = m_hash[3];
uint32_t e = m_hash[4];
// data represented as 16x 32-bit words
const uint32_t* input = (uint32_t*) data;
// convert to big endian
uint32_t words[80];
for (int i = 0; i < 16; i++)
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
words[i] = input[i];
#else
words[i] = swap(input[i]);
#endif
// extend to 80 words
for (int i = 16; i < 80; i++)
words[i] = rotate(words[i-3] ^ words[i-8] ^ words[i-14] ^ words[i-16], 1);
// first round
for (int i = 0; i < 4; i++)
{
int offset = 5*i;
e += rotate(a,5) + f1(b,c,d) + words[offset ] + 0x5a827999; b = rotate(b,30);
d += rotate(e,5) + f1(a,b,c) + words[offset+1] + 0x5a827999; a = rotate(a,30);
c += rotate(d,5) + f1(e,a,b) + words[offset+2] + 0x5a827999; e = rotate(e,30);
b += rotate(c,5) + f1(d,e,a) + words[offset+3] + 0x5a827999; d = rotate(d,30);
a += rotate(b,5) + f1(c,d,e) + words[offset+4] + 0x5a827999; c = rotate(c,30);
}
// second round
for (int i = 4; i < 8; i++)
{
int offset = 5*i;
e += rotate(a,5) + f2(b,c,d) + words[offset ] + 0x6ed9eba1; b = rotate(b,30);
d += rotate(e,5) + f2(a,b,c) + words[offset+1] + 0x6ed9eba1; a = rotate(a,30);
c += rotate(d,5) + f2(e,a,b) + words[offset+2] + 0x6ed9eba1; e = rotate(e,30);
b += rotate(c,5) + f2(d,e,a) + words[offset+3] + 0x6ed9eba1; d = rotate(d,30);
a += rotate(b,5) + f2(c,d,e) + words[offset+4] + 0x6ed9eba1; c = rotate(c,30);
}
// third round
for (int i = 8; i < 12; i++)
{
int offset = 5*i;
e += rotate(a,5) + f3(b,c,d) + words[offset ] + 0x8f1bbcdc; b = rotate(b,30);
d += rotate(e,5) + f3(a,b,c) + words[offset+1] + 0x8f1bbcdc; a = rotate(a,30);
c += rotate(d,5) + f3(e,a,b) + words[offset+2] + 0x8f1bbcdc; e = rotate(e,30);
b += rotate(c,5) + f3(d,e,a) + words[offset+3] + 0x8f1bbcdc; d = rotate(d,30);
a += rotate(b,5) + f3(c,d,e) + words[offset+4] + 0x8f1bbcdc; c = rotate(c,30);
}
// fourth round
for (int i = 12; i < 16; i++)
{
int offset = 5*i;
e += rotate(a,5) + f2(b,c,d) + words[offset ] + 0xca62c1d6; b = rotate(b,30);
d += rotate(e,5) + f2(a,b,c) + words[offset+1] + 0xca62c1d6; a = rotate(a,30);
c += rotate(d,5) + f2(e,a,b) + words[offset+2] + 0xca62c1d6; e = rotate(e,30);
b += rotate(c,5) + f2(d,e,a) + words[offset+3] + 0xca62c1d6; d = rotate(d,30);
a += rotate(b,5) + f2(c,d,e) + words[offset+4] + 0xca62c1d6; c = rotate(c,30);
}
// update hash
m_hash[0] += a;
m_hash[1] += b;
m_hash[2] += c;
m_hash[3] += d;
m_hash[4] += e;
}
/// add arbitrary number of bytes
void SHA1::add(const void* data, size_t numBytes)
{
const uint8_t* current = (const uint8_t*) data;
if (m_bufferSize > 0)
{
while (numBytes > 0 && m_bufferSize < BlockSize)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
// full buffer
if (m_bufferSize == BlockSize)
{
processBlock((void*)m_buffer);
m_numBytes += BlockSize;
m_bufferSize = 0;
}
// no more data ?
if (numBytes == 0)
return;
// process full blocks
while (numBytes >= BlockSize)
{
processBlock(current);
current += BlockSize;
m_numBytes += BlockSize;
numBytes -= BlockSize;
}
// keep remaining bytes in buffer
while (numBytes > 0)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
/// process final block, less than 64 bytes
void SHA1::processBuffer()
{
// the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
// - append "1" bit to message
// - append "0" bits until message length in bit mod 512 is 448
// - append length as 64 bit integer
// number of bits
size_t paddedLength = m_bufferSize * 8;
// plus one bit set to 1 (always appended)
paddedLength++;
// number of bits must be (numBits % 512) = 448
size_t lower11Bits = paddedLength & 511;
if (lower11Bits <= 448)
paddedLength += 448 - lower11Bits;
else
paddedLength += 512 + 448 - lower11Bits;
// convert from bits to bytes
paddedLength /= 8;
// only needed if additional data flows over into a second block
unsigned char extra[BlockSize];
// append a "1" bit, 128 => binary 10000000
if (m_bufferSize < BlockSize)
m_buffer[m_bufferSize] = 128;
else
extra[0] = 128;
size_t i;
for (i = m_bufferSize + 1; i < BlockSize; i++)
m_buffer[i] = 0;
for (; i < paddedLength; i++)
extra[i - BlockSize] = 0;
// add message length in bits as 64 bit number
uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
// find right position
unsigned char* addLength;
if (paddedLength < BlockSize)
addLength = m_buffer + paddedLength;
else
addLength = extra + paddedLength - BlockSize;
// must be big endian
*addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
*addLength = (unsigned char)( msgBits & 0xFF);
// process blocks
processBlock(m_buffer);
// flowed over into a second block ?
if (paddedLength > BlockSize)
processBlock(extra);
}
/// return latest hash as 40 hex characters
std::string SHA1::getHash()
{
// compute hash (as raw bytes)
unsigned char rawHash[HashBytes];
getHash(rawHash);
// convert to hex string
std::string result;
result.reserve(2 * HashBytes);
for (int i = 0; i < HashBytes; i++)
{
static const char dec2hex[16+1] = "0123456789abcdef";
result += dec2hex[(rawHash[i] >> 4) & 15];
result += dec2hex[ rawHash[i] & 15];
}
return result;
}
/// return latest hash as bytes
void SHA1::getHash(unsigned char buffer[SHA1::HashBytes])
{
// save old hash if buffer is partially filled
uint32_t oldHash[HashValues];
for (int i = 0; i < HashValues; i++)
oldHash[i] = m_hash[i];
// process remaining bytes
processBuffer();
unsigned char* current = buffer;
for (int i = 0; i < HashValues; i++)
{
*current++ = (m_hash[i] >> 24) & 0xFF;
*current++ = (m_hash[i] >> 16) & 0xFF;
*current++ = (m_hash[i] >> 8) & 0xFF;
*current++ = m_hash[i] & 0xFF;
// restore old hash
m_hash[i] = oldHash[i];
}
}
/// compute SHA1 of a memory block
std::string SHA1::operator()(const void* data, size_t numBytes)
{
reset();
add(data, numBytes);
return getHash();
}
/// compute SHA1 of a string, excluding final zero
std::string SHA1::operator()(const std::string& text)
{
reset();
add(text.c_str(), text.size());
return getHash();
}

78
external/Common/sha1.h vendored Normal file
View File

@ -0,0 +1,78 @@
// //////////////////////////////////////////////////////////
// sha1.h
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#pragma once
//#include "hash.h"
#include <string>
// define fixed size integer types
#ifdef _MSC_VER
// Windows
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#else
// GCC
#include <stdint.h>
#endif
/// compute SHA1 hash
/** Usage:
SHA1 sha1;
std::string myHash = sha1("Hello World"); // std::string
std::string myHash2 = sha1("How are you", 11); // arbitrary data, 11 bytes
// or in a streaming fashion:
SHA1 sha1;
while (more data available)
sha1.add(pointer to fresh data, number of new bytes);
std::string myHash3 = sha1.getHash();
*/
class SHA1 //: public Hash
{
public:
/// split into 64 byte blocks (=> 512 bits), hash is 20 bytes long
enum { BlockSize = 512 / 8, HashBytes = 20 };
/// same as reset()
SHA1();
/// compute SHA1 of a memory block
std::string operator()(const void* data, size_t numBytes);
/// compute SHA1 of a string, excluding final zero
std::string operator()(const std::string& text);
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as 40 hex characters
std::string getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart
void reset();
private:
/// process 64 bytes
void processBlock(const void* data);
/// process everything left in the internal buffer
void processBuffer();
/// size of processed data in bytes
uint64_t m_numBytes;
/// valid bytes in m_buffer
size_t m_bufferSize;
/// bytes not processed yet
uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 };
/// hash, stored as integers
uint32_t m_hash[HashValues];
};

411
external/Common/sha256.cpp vendored Normal file
View File

@ -0,0 +1,411 @@
// //////////////////////////////////////////////////////////
// sha256.cpp
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#include "sha256.h"
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
#ifndef _MSC_VER
#include <endian.h>
#endif
/// same as reset()
SHA256::SHA256()
{
reset();
}
/// restart
void SHA256::reset()
{
m_numBytes = 0;
m_bufferSize = 0;
// according to RFC 1321
m_hash[0] = 0x6a09e667;
m_hash[1] = 0xbb67ae85;
m_hash[2] = 0x3c6ef372;
m_hash[3] = 0xa54ff53a;
m_hash[4] = 0x510e527f;
m_hash[5] = 0x9b05688c;
m_hash[6] = 0x1f83d9ab;
m_hash[7] = 0x5be0cd19;
}
namespace
{
inline uint32_t rotate(uint32_t a, uint32_t c)
{
return (a >> c) | (a << (32 - c));
}
inline uint32_t swap(uint32_t x)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap32(x);
#endif
#ifdef MSC_VER
return _byteswap_ulong(x);
#endif
return (x >> 24) |
((x >> 8) & 0x0000FF00) |
((x << 8) & 0x00FF0000) |
(x << 24);
}
// mix functions for processBlock()
inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g)
{
uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25);
uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g)))
return term1 + term2;
}
inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c)
{
uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22);
uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c);
return term1 + term2;
}
}
/// process 64 bytes
void SHA256::processBlock(const void* data)
{
// get last hash
uint32_t a = m_hash[0];
uint32_t b = m_hash[1];
uint32_t c = m_hash[2];
uint32_t d = m_hash[3];
uint32_t e = m_hash[4];
uint32_t f = m_hash[5];
uint32_t g = m_hash[6];
uint32_t h = m_hash[7];
// data represented as 16x 32-bit words
const uint32_t* input = (uint32_t*) data;
// convert to big endian
uint32_t words[64];
int i;
for (i = 0; i < 16; i++)
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
words[i] = input[i];
#else
words[i] = swap(input[i]);
#endif
uint32_t x,y; // temporaries
// first round
x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y;
x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y;
x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y;
x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y;
x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y;
x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y;
x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y;
x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y;
// secound round
x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y;
x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y;
x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y;
x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y;
x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y;
x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y;
x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y;
x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y;
// extend to 24 words
for (; i < 24; i++)
words[i] = words[i-16] +
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
words[i-7] +
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// third round
x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y;
x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y;
x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y;
x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y;
x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y;
x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y;
x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y;
x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y;
// extend to 32 words
for (; i < 32; i++)
words[i] = words[i-16] +
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
words[i-7] +
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// fourth round
x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y;
x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y;
x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y;
x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y;
x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y;
x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y;
x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y;
x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y;
// extend to 40 words
for (; i < 40; i++)
words[i] = words[i-16] +
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
words[i-7] +
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// fifth round
x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y;
x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y;
x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y;
x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y;
x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y;
x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y;
x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y;
x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y;
// extend to 48 words
for (; i < 48; i++)
words[i] = words[i-16] +
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
words[i-7] +
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// sixth round
x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y;
x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y;
x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y;
x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y;
x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y;
x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y;
x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y;
x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y;
// extend to 56 words
for (; i < 56; i++)
words[i] = words[i-16] +
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
words[i-7] +
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// seventh round
x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y;
x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y;
x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y;
x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y;
x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y;
x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y;
x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y;
x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y;
// extend to 64 words
for (; i < 64; i++)
words[i] = words[i-16] +
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
words[i-7] +
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// eigth round
x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y;
x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y;
x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y;
x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y;
x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y;
x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y;
x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y;
x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y;
// update hash
m_hash[0] += a;
m_hash[1] += b;
m_hash[2] += c;
m_hash[3] += d;
m_hash[4] += e;
m_hash[5] += f;
m_hash[6] += g;
m_hash[7] += h;
}
/// add arbitrary number of bytes
void SHA256::add(const void* data, size_t numBytes)
{
const uint8_t* current = (const uint8_t*) data;
if (m_bufferSize > 0)
{
while (numBytes > 0 && m_bufferSize < BlockSize)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
// full buffer
if (m_bufferSize == BlockSize)
{
processBlock(m_buffer);
m_numBytes += BlockSize;
m_bufferSize = 0;
}
// no more data ?
if (numBytes == 0)
return;
// process full blocks
while (numBytes >= BlockSize)
{
processBlock(current);
current += BlockSize;
m_numBytes += BlockSize;
numBytes -= BlockSize;
}
// keep remaining bytes in buffer
while (numBytes > 0)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
/// process final block, less than 64 bytes
void SHA256::processBuffer()
{
// the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
// - append "1" bit to message
// - append "0" bits until message length in bit mod 512 is 448
// - append length as 64 bit integer
// number of bits
size_t paddedLength = m_bufferSize * 8;
// plus one bit set to 1 (always appended)
paddedLength++;
// number of bits must be (numBits % 512) = 448
size_t lower11Bits = paddedLength & 511;
if (lower11Bits <= 448)
paddedLength += 448 - lower11Bits;
else
paddedLength += 512 + 448 - lower11Bits;
// convert from bits to bytes
paddedLength /= 8;
// only needed if additional data flows over into a second block
unsigned char extra[BlockSize];
// append a "1" bit, 128 => binary 10000000
if (m_bufferSize < BlockSize)
m_buffer[m_bufferSize] = 128;
else
extra[0] = 128;
size_t i;
for (i = m_bufferSize + 1; i < BlockSize; i++)
m_buffer[i] = 0;
for (; i < paddedLength; i++)
extra[i - BlockSize] = 0;
// add message length in bits as 64 bit number
uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
// find right position
unsigned char* addLength;
if (paddedLength < BlockSize)
addLength = m_buffer + paddedLength;
else
addLength = extra + paddedLength - BlockSize;
// must be big endian
*addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
*addLength = (unsigned char)( msgBits & 0xFF);
// process blocks
processBlock(m_buffer);
// flowed over into a second block ?
if (paddedLength > BlockSize)
processBlock(extra);
}
/// return latest hash as 64 hex characters
std::string SHA256::getHash()
{
// compute hash (as raw bytes)
unsigned char rawHash[HashBytes];
getHash(rawHash);
// convert to hex string
std::string result;
result.reserve(2 * HashBytes);
for (int i = 0; i < HashBytes; i++)
{
static const char dec2hex[16+1] = "0123456789abcdef";
result += dec2hex[(rawHash[i] >> 4) & 15];
result += dec2hex[ rawHash[i] & 15];
}
return result;
}
/// return latest hash as bytes
void SHA256::getHash(unsigned char buffer[SHA256::HashBytes])
{
// save old hash if buffer is partially filled
uint32_t oldHash[HashValues];
for (int i = 0; i < HashValues; i++)
oldHash[i] = m_hash[i];
// process remaining bytes
processBuffer();
unsigned char* current = buffer;
for (int i = 0; i < HashValues; i++)
{
*current++ = (m_hash[i] >> 24) & 0xFF;
*current++ = (m_hash[i] >> 16) & 0xFF;
*current++ = (m_hash[i] >> 8) & 0xFF;
*current++ = m_hash[i] & 0xFF;
// restore old hash
m_hash[i] = oldHash[i];
}
}
/// compute SHA256 of a memory block
std::string SHA256::operator()(const void* data, size_t numBytes)
{
reset();
add(data, numBytes);
return getHash();
}
/// compute SHA256 of a string, excluding final zero
std::string SHA256::operator()(const std::string& text)
{
reset();
add(text.c_str(), text.size());
return getHash();
}

78
external/Common/sha256.h vendored Normal file
View File

@ -0,0 +1,78 @@
// //////////////////////////////////////////////////////////
// sha256.h
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#pragma once
//#include "hash.h"
#include <string>
// define fixed size integer types
#ifdef _MSC_VER
// Windows
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#else
// GCC
#include <stdint.h>
#endif
/// compute SHA256 hash
/** Usage:
SHA256 sha256;
std::string myHash = sha256("Hello World"); // std::string
std::string myHash2 = sha256("How are you", 11); // arbitrary data, 11 bytes
// or in a streaming fashion:
SHA256 sha256;
while (more data available)
sha256.add(pointer to fresh data, number of new bytes);
std::string myHash3 = sha256.getHash();
*/
class SHA256 //: public Hash
{
public:
/// split into 64 byte blocks (=> 512 bits), hash is 32 bytes long
enum { BlockSize = 512 / 8, HashBytes = 32 };
/// same as reset()
SHA256();
/// compute SHA256 of a memory block
std::string operator()(const void* data, size_t numBytes);
/// compute SHA256 of a string, excluding final zero
std::string operator()(const std::string& text);
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as 64 hex characters
std::string getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart
void reset();
private:
/// process 64 bytes
void processBlock(const void* data);
/// process everything left in the internal buffer
void processBuffer();
/// size of processed data in bytes
uint64_t m_numBytes;
/// valid bytes in m_buffer
size_t m_bufferSize;
/// bytes not processed yet
uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 };
/// hash, stored as integers
uint32_t m_hash[HashValues];
};

289
external/Common/sha3.cpp vendored Normal file
View File

@ -0,0 +1,289 @@
// //////////////////////////////////////////////////////////
// sha3.cpp
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#include "sha3.h"
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
#ifndef _MSC_VER
#include <endian.h>
#endif
/// same as reset()
SHA3::SHA3(Bits bits)
: m_blockSize(200 - 2 * (bits / 8)),
m_bits(bits)
{
reset();
}
/// restart
void SHA3::reset()
{
for (size_t i = 0; i < StateSize; i++)
m_hash[i] = 0;
m_numBytes = 0;
m_bufferSize = 0;
}
/// constants and local helper functions
namespace
{
const unsigned int Rounds = 24;
const uint64_t XorMasks[Rounds] =
{
0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
};
/// rotate left and wrap around to the right
inline uint64_t rotateLeft(uint64_t x, uint8_t numBits)
{
return (x << numBits) | (x >> (64 - numBits));
}
/// convert litte vs big endian
inline uint64_t swap(uint64_t x)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap64(x);
#endif
#ifdef _MSC_VER
return _byteswap_uint64(x);
#endif
return (x >> 56) |
((x >> 40) & 0x000000000000FF00ULL) |
((x >> 24) & 0x0000000000FF0000ULL) |
((x >> 8) & 0x00000000FF000000ULL) |
((x << 8) & 0x000000FF00000000ULL) |
((x << 24) & 0x0000FF0000000000ULL) |
((x << 40) & 0x00FF000000000000ULL) |
(x << 56);
}
/// return x % 5 for 0 <= x <= 9
unsigned int mod5(unsigned int x)
{
if (x < 5)
return x;
return x - 5;
}
}
/// process a full block
void SHA3::processBlock(const void* data)
{
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
#define LITTLEENDIAN(x) swap(x)
#else
#define LITTLEENDIAN(x) (x)
#endif
const uint64_t* data64 = (const uint64_t*) data;
// mix data into state
for (unsigned int i = 0; i < m_blockSize / 8; i++)
m_hash[i] ^= LITTLEENDIAN(data64[i]);
// re-compute state
for (unsigned int round = 0; round < Rounds; round++)
{
// Theta
uint64_t coefficients[5];
for (unsigned int i = 0; i < 5; i++)
coefficients[i] = m_hash[i] ^ m_hash[i + 5] ^ m_hash[i + 10] ^ m_hash[i + 15] ^ m_hash[i + 20];
for (unsigned int i = 0; i < 5; i++)
{
uint64_t one = coefficients[mod5(i + 4)] ^ rotateLeft(coefficients[mod5(i + 1)], 1);
m_hash[i ] ^= one;
m_hash[i + 5] ^= one;
m_hash[i + 10] ^= one;
m_hash[i + 15] ^= one;
m_hash[i + 20] ^= one;
}
// temporary
uint64_t one;
// Rho Pi
uint64_t last = m_hash[1];
one = m_hash[10]; m_hash[10] = rotateLeft(last, 1); last = one;
one = m_hash[ 7]; m_hash[ 7] = rotateLeft(last, 3); last = one;
one = m_hash[11]; m_hash[11] = rotateLeft(last, 6); last = one;
one = m_hash[17]; m_hash[17] = rotateLeft(last, 10); last = one;
one = m_hash[18]; m_hash[18] = rotateLeft(last, 15); last = one;
one = m_hash[ 3]; m_hash[ 3] = rotateLeft(last, 21); last = one;
one = m_hash[ 5]; m_hash[ 5] = rotateLeft(last, 28); last = one;
one = m_hash[16]; m_hash[16] = rotateLeft(last, 36); last = one;
one = m_hash[ 8]; m_hash[ 8] = rotateLeft(last, 45); last = one;
one = m_hash[21]; m_hash[21] = rotateLeft(last, 55); last = one;
one = m_hash[24]; m_hash[24] = rotateLeft(last, 2); last = one;
one = m_hash[ 4]; m_hash[ 4] = rotateLeft(last, 14); last = one;
one = m_hash[15]; m_hash[15] = rotateLeft(last, 27); last = one;
one = m_hash[23]; m_hash[23] = rotateLeft(last, 41); last = one;
one = m_hash[19]; m_hash[19] = rotateLeft(last, 56); last = one;
one = m_hash[13]; m_hash[13] = rotateLeft(last, 8); last = one;
one = m_hash[12]; m_hash[12] = rotateLeft(last, 25); last = one;
one = m_hash[ 2]; m_hash[ 2] = rotateLeft(last, 43); last = one;
one = m_hash[20]; m_hash[20] = rotateLeft(last, 62); last = one;
one = m_hash[14]; m_hash[14] = rotateLeft(last, 18); last = one;
one = m_hash[22]; m_hash[22] = rotateLeft(last, 39); last = one;
one = m_hash[ 9]; m_hash[ 9] = rotateLeft(last, 61); last = one;
one = m_hash[ 6]; m_hash[ 6] = rotateLeft(last, 20); last = one;
m_hash[ 1] = rotateLeft(last, 44);
// Chi
for (unsigned int j = 0; j < 25; j += 5)
{
// temporaries
uint64_t one = m_hash[j];
uint64_t two = m_hash[j + 1];
m_hash[j] ^= m_hash[j + 2] & ~two;
m_hash[j + 1] ^= m_hash[j + 3] & ~m_hash[j + 2];
m_hash[j + 2] ^= m_hash[j + 4] & ~m_hash[j + 3];
m_hash[j + 3] ^= one & ~m_hash[j + 4];
m_hash[j + 4] ^= two & ~one;
}
// Iota
m_hash[0] ^= XorMasks[round];
}
}
/// add arbitrary number of bytes
void SHA3::add(const void* data, size_t numBytes)
{
const uint8_t* current = (const uint8_t*) data;
// copy data to buffer
if (m_bufferSize > 0)
{
while (numBytes > 0 && m_bufferSize < m_blockSize)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
// full buffer
if (m_bufferSize == m_blockSize)
{
processBlock((void*)m_buffer);
m_numBytes += m_blockSize;
m_bufferSize = 0;
}
// no more data ?
if (numBytes == 0)
return;
// process full blocks
while (numBytes >= m_blockSize)
{
processBlock(current);
current += m_blockSize;
m_numBytes += m_blockSize;
numBytes -= m_blockSize;
}
// keep remaining bytes in buffer
while (numBytes > 0)
{
m_buffer[m_bufferSize++] = *current++;
numBytes--;
}
}
/// process everything left in the internal buffer
void SHA3::processBuffer()
{
// add padding
size_t offset = m_bufferSize;
// add a "1" byte
m_buffer[offset++] = 0x06;
// fill with zeros
while (offset < m_blockSize)
m_buffer[offset++] = 0;
// and add a single set bit
m_buffer[offset - 1] |= 0x80;
processBlock(m_buffer);
}
/// return latest hash as 16 hex characters
std::string SHA3::getHash()
{
// process remaining bytes
processBuffer();
// convert hash to string
static const char dec2hex[16 + 1] = "0123456789abcdef";
// number of significant elements in hash (uint64_t)
unsigned int hashLength = m_bits / 64;
std::string result;
result.reserve(m_bits / 4);
for (unsigned int i = 0; i < hashLength; i++)
for (unsigned int j = 0; j < 8; j++) // 64 bits => 8 bytes
{
// convert a byte to hex
unsigned char oneByte = (unsigned char) (m_hash[i] >> (8 * j));
result += dec2hex[oneByte >> 4];
result += dec2hex[oneByte & 15];
}
// SHA3-224's last entry in m_hash provides only 32 bits instead of 64 bits
unsigned int remainder = m_bits - hashLength * 64;
unsigned int processed = 0;
while (processed < remainder)
{
// convert a byte to hex
unsigned char oneByte = (unsigned char) (m_hash[hashLength] >> processed);
result += dec2hex[oneByte >> 4];
result += dec2hex[oneByte & 15];
processed += 8;
}
return result;
}
/// compute SHA3 of a memory block
std::string SHA3::operator()(const void* data, size_t numBytes)
{
reset();
add(data, numBytes);
return getHash();
}
/// compute SHA3 of a string, excluding final zero
std::string SHA3::operator()(const std::string& text)
{
reset();
add(text.c_str(), text.size());
return getHash();
}

81
external/Common/sha3.h vendored Normal file
View File

@ -0,0 +1,81 @@
// //////////////////////////////////////////////////////////
// sha3.h
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
#pragma once
//#include "hash.h"
#include <string>
// define fixed size integer types
#ifdef _MSC_VER
// Windows
typedef unsigned __int8 uint8_t;
typedef unsigned __int64 uint64_t;
#else
// GCC
#include <stdint.h>
#endif
/// compute SHA3 hash
/** Usage:
SHA3 sha3;
std::string myHash = sha3("Hello World"); // std::string
std::string myHash2 = sha3("How are you", 11); // arbitrary data, 11 bytes
// or in a streaming fashion:
SHA3 sha3;
while (more data available)
sha3.add(pointer to fresh data, number of new bytes);
std::string myHash3 = sha3.getHash();
*/
class SHA3 //: public Hash
{
public:
/// algorithm variants
enum Bits { Bits224 = 224, Bits256 = 256, Bits384 = 384, Bits512 = 512 };
/// same as reset()
explicit SHA3(Bits bits = Bits256);
/// compute hash of a memory block
std::string operator()(const void* data, size_t numBytes);
/// compute hash of a string, excluding final zero
std::string operator()(const std::string& text);
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as hex characters
std::string getHash();
/// restart
void reset();
private:
/// process a full block
void processBlock(const void* data);
/// process everything left in the internal buffer
void processBuffer();
/// 1600 bits, stored as 25x64 bit, BlockSize is no more than 1152 bits (Keccak224)
enum { StateSize = 1600 / (8 * 8),
MaxBlockSize = 200 - 2 * (224 / 8) };
/// hash
uint64_t m_hash[StateSize];
/// size of processed data in bytes
uint64_t m_numBytes;
/// block size (less or equal to MaxBlockSize)
size_t m_blockSize;
/// valid bytes in m_buffer
size_t m_bufferSize;
/// bytes not processed yet
uint8_t m_buffer[MaxBlockSize];
/// variant
Bits m_bits;
};