Upload MD5Crack project

This commit is contained in:
Ernesto Canales Pereña 2023-07-29 19:47:08 +02:00
commit 1ee68eccf7
23 changed files with 3734 additions and 0 deletions

359
CrackMD5.cc Normal file
View File

@ -0,0 +1,359 @@
#include "lib/md5.h"
#include "lib/sha256.h"
#include <iostream>
#include <thread>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <cstring>
#include <atomic>
#include <unistd.h>
#include <random>
#include <sys/stat.h>
#include "sys/sysinfo.h"
using namespace std;
using namespace chrono;
#define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
#define PBWIDTH 60
enum Error {
ERR_UNKNOWN_OPTION,
ERR_CANT_OPEN_FILE,
ERR_ARGS,
ERR_THREADS
};
void error(Error n, string file)
{
switch (n) {
case ERR_UNKNOWN_OPTION:
cout << "Error, unknown option" << endl;
break;
case ERR_CANT_OPEN_FILE:
cout << "Error, can't open file: "<< file << endl;
break;
case ERR_ARGS:
cout<< "Usage:\ncrack -f [file] -d [dict] -t [threads] --trace [worst performance] --check [sys info]" << endl;
break;
case ERR_THREADS:
cout<< "Error, wrong number of threads" << endl;
break;
}
}
enum Info{
CHECK_SYS
};
void info(Info i){
struct sysinfo memInfo;
sysinfo (&memInfo);
long long totalPhysMemBytes = memInfo.totalram;
long long totalPhysMemGBytes = (totalPhysMemBytes/(1024*1024*1024));
const auto processor_count = std::thread::hardware_concurrency();
switch (i) {
case CHECK_SYS:
cout << "Number of threads: " << processor_count << endl;
cout << "Total RAM: " << totalPhysMemGBytes << "GB ("<<totalPhysMemBytes<<" bytes)"<<endl;
break;
}
}
void loadingFunction(double percentage){
int val = (int) (percentage * 100);
int lpad = (int) (percentage * PBWIDTH);
int rpad = PBWIDTH - lpad;
printf("\r%3d%% [%.*s%*s]", val, lpad, PBSTR, rpad, "");
fflush(stdout);
}
long long countLines(string &nombre){
ifstream inFile(nombre);
long long c = count(istreambuf_iterator<char>(inFile),
istreambuf_iterator<char>(), '\n')+1;
return c;
}
void readFile(string *&words,string &nombre, long long &size){
ifstream fichero; string fila;
words = new string[size];
long long i = 0;
fichero.open(nombre.c_str(), ios::in);
if(fichero.is_open()){
while(!fichero.eof()){
getline(fichero, fila);
words[i] = fila;
i++;
}
fichero.close();
}
}
void readFileDict(char *&dict,string &nombre, long long &sizeWordsDICT){
cout<<"Loading dictionary in memory..."<<endl;
std::ifstream fichero(nombre, ios::in);
fichero.read(dict, sizeWordsDICT);
}
void crackPasswords(string *wordsMD5, char *&dict, string *&result, long long *&rangs, long long &sizeMD5, long long &sizeWordsDICT, int core, int &recovered, bool &trace)
{
MD5 hashMD5;
for(long long j=rangs[0];j<rangs[1];j++){
if(core==0 && trace){
loadingFunction(static_cast<double>(j)/static_cast<double>(rangs[1]));
}
string word = "";
while(dict[j] != '\n' && j<=sizeWordsDICT){
word = word + dict[j];
j++;
}
word.erase(std::remove(word.begin(), word.end(), '\r' ), word.end());
string wordHashMD5 = hashMD5(word);
for(int word2crack=0;word2crack<sizeMD5;word2crack++){
if(result[word2crack]!=""){
continue;
}
if(wordsMD5[word2crack]==wordHashMD5){
recovered++;
result[word2crack] = word;
}
}
}
}
void fillSplit(long long **&rangs, long long &sizeWordsDICT, int &numThreads){
long long split = sizeWordsDICT/numThreads;
long long resto = sizeWordsDICT%numThreads;
long long endSPlit = split+resto;
long long currentB=0;
long long currentF=split-1;
for(int rang=0; rang<numThreads; rang++){
rangs[rang] = new long long[2];
rangs[rang][0]=currentB;
rangs[rang][1]=currentF;
if(rang + 2 == numThreads){
currentB = currentF+1;
currentF += endSPlit;
}
else{
currentB = currentF+1;
currentF += split;
}
}
}
bool checkIfExist(string &nombre){
ifstream fichero;
fichero.open(nombre.c_str(), ios::in);
if(fichero.is_open()){
return true;
}
else{
return false;
}
}
string gen_random(const int len) {
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
std::string tmp_s;
tmp_s.reserve(len);
random_device rd;
mt19937 mt(rd());
uniform_real_distribution<double> dist(0, sizeof(alphanum)-1);
for (int i = 0; i < len; ++i) {
tmp_s += alphanum[(int)(dist(mt))];
}
return tmp_s;
}
void outputFileCrack(string *result, long long &sizeMD5){
ofstream fichero("plain.txt");
if(fichero.is_open()){
for(long long i =0;i<sizeMD5;i++){
fichero<<result[i]<<endl;
}
fichero.close();
}
}
void outputFileSHA256(string *result, long long &sizeMD5){
srand((unsigned)time(NULL) * getpid());
string salt = gen_random(12);
SHA256 sha256;
ofstream fichero("new_passwords.txt");
if(fichero.is_open()){
for(long long i =0;i<sizeMD5;i++){
if(result[i]==""){
fichero<<""<<endl;
}
else{
string salt = gen_random(12);
string resultString = result[i] + salt;
fichero<<sha256(resultString)<<":"<<salt<<endl;
}
}
fichero.close();
}
}
long long GetFileSize(string filename)
{
struct stat stat_buf;
int rc = stat(filename.c_str(), &stat_buf);
return rc == 0 ? stat_buf.st_size : -1;
}
int main(int argc,char *argv[])
{
// create a new hashing object
//SHA256 sha256;
//std::cout << sha256("Hello World") << std::endl;
//Parametros de entrada.
string nameFileMD5="";
string nameFileDict="";
bool trace=false;
int numThreads = 0;
//Args
int args = 0;
while(args < argc){
if(strcmp(argv[args], "--check") == 0){
info(CHECK_SYS);
return -1;
}
if(strcmp(argv[args], "--help") == 0){
if(args+1<argc){
error(ERR_ARGS,"");
return -1;
}
}
if(strcmp(argv[args], "-f") == 0){
if(args+1<argc){
nameFileMD5=argv[args+1];
}
}
if(strcmp(argv[args], "--trace") == 0){
trace=true;
}
if(strcmp(argv[args], "-d") == 0){
if(args+1<argc){
nameFileDict=argv[args+1];
}
}
if(strcmp(argv[args], "-t") == 0){
if(args+1<argc){
numThreads=stoi(argv[args+1]);
const auto processor_count = std::thread::hardware_concurrency();
if(numThreads == 0 || processor_count<numThreads){
error(ERR_THREADS,"");
return -1;
}
}
}
args++;
}
if(nameFileMD5=="" || nameFileDict=="" || numThreads<=0){
error(ERR_ARGS,"");
return -1;
}
if(!checkIfExist(nameFileMD5)){
error(ERR_CANT_OPEN_FILE, nameFileMD5);
return -1;
}
if(!checkIfExist(nameFileDict)){
error(ERR_CANT_OPEN_FILE, nameFileDict);
return -1;
}
//Files Size
long long sizeMD5 = countLines(nameFileMD5);
long long sizeWordsDICT = GetFileSize(nameFileDict);
//Struct and params
string *wordsMD5;
char* dict = (char*)malloc(sizeWordsDICT);
string *result; result=new string[sizeMD5];
std::vector<std::thread> ThreadVector;
long long **rangs;
rangs = new long long*[numThreads];
int recovered = 0;
//Read hashes to crack, read dict and caculate ranges
readFile(wordsMD5,nameFileMD5,sizeMD5);
readFileDict(dict,nameFileDict,sizeWordsDICT);
fillSplit(rangs,sizeWordsDICT,numThreads);
cout<<"Running process with "<<numThreads<<" threads..."<<endl;
auto begin=high_resolution_clock::now();
for(int thread=0; thread<numThreads; thread++){
int core = thread;
ThreadVector.emplace_back([&wordsMD5,&dict,&result,&rangs,core,&sizeWordsDICT,&sizeMD5,&recovered, &trace](){crackPasswords(ref(wordsMD5),ref(dict),ref(result),rangs[core], ref(sizeMD5), ref(sizeWordsDICT), core, ref(recovered), ref(trace));});
}
for(auto&t :ThreadVector){
t.join();
}
auto end=high_resolution_clock::now();
if(trace){
loadingFunction(1);
cout<<endl;
}
int time = duration_cast<milliseconds>(end-begin).count();
cout<<"Time to execution: "<<time<<" ms."<<endl;
cout<<"Recovered passwords: "<<recovered<<endl;
ThreadVector.clear();
delete [] dict;
delete [] wordsMD5;
for (int i=0; i<numThreads; i++){
delete[] rangs[i];
}
delete[] rangs;
cout<<"Writing in file the recovered passwords..."<<endl;
outputFileCrack(result,sizeMD5);
cout<<"Writing in file the hash passwords in SHA256 with salt..."<<endl;
outputFileSHA256(result,sizeMD5);
delete [] result;
return 0;
}

12
README.md Normal file
View File

@ -0,0 +1,12 @@
# ARP Spoofing Banana
## Usage
```
git clone http://git.wacanal.cloud/ernie/md5crack.git
cd md5crack
make
crack -f [file] -d [dict] -t [threads] --trace [worst performance] --check [sys info]
```

10
lib/LICENSE Normal file
View File

@ -0,0 +1,10 @@
zlib License
Copyright (c) 2014,2015 Stephan Brumme
This software is provided 'as-is', without any express or implied warranty. In no event will the authors 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:
1. 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.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

431
lib/crc32.cpp 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
lib/crc32.h 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
lib/digest.cpp 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);
// 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;
}
// 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];
// 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;
}

28
lib/hash.h 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;
};

83
lib/hmac.h 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());
}

298
lib/keccak.cpp Normal file
View File

@ -0,0 +1,298 @@
// //////////////////////////////////////////////////////////
// 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 < StateSize; 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()
{
// save hash state
uint64_t oldHash[StateSize];
for (unsigned int i = 0; i < StateSize; i++)
oldHash[i] = m_hash[i];
// 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;
}
// restore state
for (unsigned int i = 0; i < StateSize; i++)
m_hash[i] = oldHash[i];
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
lib/keccak.h 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
lib/md5.cpp 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
lib/md5.h 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];
};

51
lib/readme.md Normal file
View File

@ -0,0 +1,51 @@
# Portable C++ Hashing Library
This is a mirror of my library hosted at https://create.stephan-brumme.com/hash-library/
In a nutshell:
- computes CRC32, MD5, SHA1 and SHA256 (most common member of the SHA2 functions), Keccak and its SHA3 sibling
- optional HMAC (keyed-hash message authentication code)
- no external dependencies, small code size
- can work chunk-wise (for example when reading streams block-by-block)
- portable: supports Windows and Linux, tested on Little Endian and Big Endian CPUs
- roughly as fast as Linux core hashing functions
- open source, zlib license
You can find code examples, benchmarks and much more on my website https://create.stephan-brumme.com/hash-library/
# How to use
This example computes SHA256 hashes but the API is more or less identical for all hash algorithms:
``` cpp
// SHA2 test program
#include "sha256.h"
#include <iostream> // for std::cout only, not needed for hashing library
int main(int, char**)
{
// create a new hashing object
SHA256 sha256;
// hashing an std::string
std::cout << sha256("Hello World") << std::endl;
// => a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
// hashing a buffer of bytes
const char* buffer = "How are you";
std::cout << sha256(buffer, 11) << std::endl;
// => 9c7d5b046878838da72e40ceb3179580958df544b240869b80d0275cc07209cc
// or in a streaming fashion (re-use "How are you")
SHA256 sha256stream;
const char* url = "create.stephan-brumme.com"; // 25 bytes
int step = 5;
for (int i = 0; i < 25; i += step)
sha256stream.add(url + i, step); // add five bytes at a time
std::cout << sha256stream.getHash() << std::endl;
// => 82aa771f1183c52f973c798c9243a1c73833ea40961c73e55e12430ec77b69f6
return 0;
}
```

326
lib/sha1.cpp 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
lib/sha1.h 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];
};

428
lib/sha256.cpp Normal file
View File

@ -0,0 +1,428 @@
// //////////////////////////////////////////////////////////
// sha256.cpp
// Copyright (c) 2014,2015,2021 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
//#define SHA2_224_SEED_VECTOR
/// same as reset()
SHA256::SHA256()
{
reset();
}
/// restart
void SHA256::reset()
{
m_numBytes = 0;
m_bufferSize = 0;
// according to RFC 1321
// "These words were obtained by taking the first thirty-two bits of the
// fractional parts of the square roots of the first eight prime numbers"
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;
#ifdef SHA2_224_SEED_VECTOR
// if you want SHA2-224 instead then use these seeds
// and throw away the last 32 bits of getHash
m_hash[0] = 0xc1059ed8;
m_hash[1] = 0x367cd507;
m_hash[2] = 0x3070dd17;
m_hash[3] = 0xf70e5939;
m_hash[4] = 0xffc00b31;
m_hash[5] = 0x68581511;
m_hash[6] = 0x64f98fa7;
m_hash[7] = 0xbefa4fa4;
#endif
}
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
lib/sha256.h 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];
};

300
lib/sha3.cpp Normal file
View File

@ -0,0 +1,300 @@
// //////////////////////////////////////////////////////////
// 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
#include <iostream>
/// 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 < StateSize; 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()
{
// save hash state
uint64_t oldHash[StateSize];
for (unsigned int i = 0; i < StateSize; i++)
oldHash[i] = m_hash[i];
// 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;
}
// restore state
for (unsigned int i = 0; i < StateSize; i++)
m_hash[i] = oldHash[i];
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
lib/sha3.h 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;
};

View File

@ -0,0 +1,64 @@
// minimal test case for https://github.com/stbrumme/hash-library/issues/2
// g++ github-issue2.cpp ../sha*.cpp ../keccak.cpp ../md5.cpp -o github-issue2 && ./github-issue2
#include "../sha1.h"
#include "../sha256.h"
#include "../sha3.h"
#include "../keccak.h"
#include "../md5.h"
#include <iostream>
int main()
{
std::string text = "hello world";
std::cout << "SHA1:" << std::endl;
SHA1 sha1;
sha1.add(text.c_str(), text.size());
std::cout << sha1.getHash() << std::endl;
std::cout << sha1.getHash() << std::endl;
std::cout << sha1.getHash() << std::endl;
std::cout << std::endl;
std::cout << "SHA256:" << std::endl;
SHA256 sha256;
sha256.add(text.c_str(), text.size());
std::cout << sha256.getHash() << std::endl;
std::cout << sha256.getHash() << std::endl;
std::cout << sha256.getHash() << std::endl;
std::cout << std::endl;
std::cout << "SHA3:" << std::endl;
SHA3 sha3;
sha3.add(text.c_str(), text.size());
std::cout << sha3.getHash() << std::endl;
std::cout << sha3.getHash() << std::endl;
std::cout << sha3.getHash() << std::endl;
std::cout << std::endl;
std::cout << "Keccak:" << std::endl;
Keccak keccak;
keccak.add(text.c_str(), text.size());
std::cout << keccak.getHash() << std::endl;
std::cout << keccak.getHash() << std::endl;
std::cout << keccak.getHash() << std::endl;
std::cout << std::endl;
std::cout << "MD5:" << std::endl;
MD5 md5;
md5.add(text.c_str(), text.size());
std::cout << md5.getHash() << std::endl;
std::cout << md5.getHash() << std::endl;
std::cout << md5.getHash() << std::endl;
return 0;
}

View File

@ -0,0 +1,16 @@
// minimal test case for https://github.com/stbrumme/hash-library/issues/6
// g++ github-issue6.cpp ../sha3.cpp -o github-issue6 && ./github-issue6
#include "../sha3.h"
#include <iostream>
int main(int argc, char *argv[])
{
std::string text = "72a5f501151ca974002f34";
SHA3 hasher(SHA3::Bits512);
hasher.add(text.data(), text.size());
std::cout << hasher.getHash() << std::endl;
return 0;
}

361
lib/tests/tests.cpp Normal file
View File

@ -0,0 +1,361 @@
// //////////////////////////////////////////////////////////
// tests.cpp
// Copyright (c) 2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
// simple test suite for hash-library
// g++ tests.cpp ../crc32.cpp ../md5.cpp ../sha1.cpp ../sha256.cpp ../sha3.cpp -o tests && ./tests
#include "../crc32.h"
#include "../md5.h"
#include "../sha1.h"
#include "../sha256.h"
#include "../sha3.h"
#include "../keccak.h"
#include "../hmac.h"
#include <string>
#include <vector>
#include <iostream>
struct TestSet
{
const char* input;
const char* crc32b;
const char* md5;
const char* sha1;
const char* sha256;
const char* sha3_256;
};
const size_t NumTests = 100;
TestSet testset[NumTests] =
{ // generated by PHP script, SHA3 vectors from https://raw.githubusercontent.com/gvanas/KeccakCodePackage/master/TestVectors/ShortMsgKAT_SHA3-256.txt
/*
$lines = file("ShortMsgKAT_SHA3-256.txt");
for ($i = 1; $i <= 100; $i++)
{
$hex = trim(strtolower(substr($lines[8 * 4 * $i + 3], 6)));
$sha3 = trim(strtolower(substr($lines[8 * 4 * $i + 4], 5)));
$msg = hex2bin($hex);
echo "{ \"$hex\", \"".
hash("crc32b", $msg).'", "'.
hash("md5", $msg).'", "'.
hash("sha1", $msg).'", "'.
hash("sha256", $msg).'", "'.
"$sha3\" }, // $i\n";
}
*/
{ "cc", "40d06116", "a2e970f170961ce879190d64982c94ec", "a6f57425137e9aa54537f0b3f5364ce165aedb0a", "1dd8312636f6a0bf3d21fa2855e63072507453e93a5ced4301b364e91c9d87d6", "677035391cd3701293d385f037ba32796252bb7ce180b00b582dd9b20aaad7f0" }, // 1
{ "41fb", "82d4472f", "70d3e9af7232e67b6b6f3e71f7399438", "a6a5d330d9928b452ca7e34e946c52ea4f6eaa15", "0f8fa28112230a7a0b3cabcb64d37bd38f5023b1391e38f89a9b29f32b0aefbc", "39f31b6e653dfcd9caed2602fd87f61b6254f581312fb6eeec4d7148fa2e72aa" }, // 2
{ "1f877c", "c54a0ec4", "f7ac37ba79246d6a36b49c0993791110", "d17212f7dbfa31d10b68d480bc91cd3e1596be86", "ab0213910396c8d94cbf3b6c97de1fc97fc55cea4b6b6cc25ea4b71e7e7bc28c", "bc22345e4bd3f792a341cf18ac0789f1c9c966712a501b19d1b6632ccd408ec5" }, // 3
{ "c1ecfdfc", "5a545e7c", "af9116916ca42299e557e55cfa3e1591", "dc148b935ff1614ba17bdbad6e5392179e412f0d", "7df4925396138971f4a733680107ce202c5c5991dbc8737ad07eb4da85a06f85", "c5859be82560cc8789133f7c834a6ee628e351e504e601e8059a0667ff62c124" }, // 4
{ "21f134ac57", "d086fa95", "29057856dd5548ac8c1cca4b27489449", "404be2d420abc459707149bb79c8065aded00e7e", "a0ba0190c23bf1140cf5bf5a07e1140df55389792283bb6a8b5867a539ac7931", "55bd9224af4eed0d121149e37ff4d7dd5be24bd9fbe56e0171e87db7a6f4e06d" }, // 5
{ "c6f50bb74e29", "cdff1654", "d175ad6887766bf159f1bde8e514465a", "6685c62b13f7fc0703fd246c050a19cce98fcd97", "e2c0a1c005c4aa91ad89e509b603c5c0f474a18df291e5ca378725a9ad76fb09", "ae0cbc757d4ab088e172abfd8746289950f92d38a25295658dbf744b5635af04" }, // 6
{ "119713cc83eeef", "54465641", "27e281ab44bce27391bc7cee7b0f3437", "1fcd96a8c76f4d884c744bf840507acfe646ff76", "96e043b747fa1737d63d83b898987d3e70c816175a50333077ce4e7602255975", "e340c9a44373efcc212f3cb66a047ac34c87ff1c58c4a14b16a2bfc34698bb1d" }, // 7
{ "4a4f202484512526", "696ab8df", "90ea55f66c4b5239df52b05349455037", "928a171eacc5698811ef2992712458a9fa043955", "1b1c9bf7e050805714c81c03a05a6961e924bbaca37cb5b9998cb46bb2be4fa5", "ba4fb009d57a5ceb85fc64d54e5c55a55854b41cc47ad15294bc41f32165dfba" }, // 8
{ "1f66ab4185ed9b6375", "c0b622ae", "164a8c44008d14028fae0cf7b9d566aa", "8b81a9a58e987edb923fe6118ca6099cb71ad55a", "0eb3c0f5f345bd6cf98cf870886abc1817a0c5dde08d62f870a6b4a006979ee3", "b9886ef905c8bdd272eda8298865e0769869f1c964460d1aa9d7a0c687707ccd" }, // 9
{ "eed7422227613b6f53c9", "2029782c", "e57498c9318a515fcd8980dc319aa10a", "261830dfe450e4d58e5315cb0cb9d31c725cc406", "9758c2ee9d9782c6a3e60b394b16837689ab6f13c4157d45fc6ee7597a59448f", "fab8f88d3191e21a725b21c63a02cad3fa7c450ef8584b94cfa382f393422455" }, // 10
{ "eaeed5cdffd89dece455f1", "42fcfb29", "5e49b16a26a63aef2912956918f6a919", "c0507f76cea3e4d46edf256d49fe0ccf0ec2145a", "0a5f39f0e909a63bc93a76a21e94d62a0451d9f8123ecc5a59e5bd240b2850b0", "9363acd3f48bb91a8998aa0e8df75c971770a16a71e7d2334409734cd7d0a9ee" }, // 11
{ "5be43c90f22902e4fe8ed2d3", "4fbb1441", "e907bfc096655d56d3799b422f0ddd16", "f089f569228795551af51bbff935ac0e6b625c78", "c6057a042954e08be906ff710b042dbf6352f8b958b8ade708439063710bb5e2", "16932f6f65deaad5780e25ab410c66b0e4198eba9f4ed1a25ee24f7879faefe2" }, // 12
{ "a746273228122f381c3b46e4f1", "ad022e12", "ae0549cbb3704b5d2d1f18dbbc159de4", "2b269ce05fc8392c0333f8d1aec8ce32ed969e32", "7c48389c069dedf88be6534d34dfc20c109ce40788b96ddebc1e9209c0ca49de", "1c28100e0ef50671c7ea3e024fa3ba9da2ebddb4de264c3a2426c36ad3f91c61" }, // 13
{ "3c5871cd619c69a63b540eb5a625", "1ca57d8b", "c4d0ef66c3ddc1f3ee998de21e6834ec", "88b2b64f3ada91ed6cd29e80b8c67e2cd6ff555a", "82af41b707f8336fadc9fdbfc00b50d11a27b46e1e022ed4865896dca259377d", "8183be4875fab7ec5f99ed94f5f900cf1d6b953d8f71e1e7cc008687980e613a" }, // 14
{ "fa22874bcc068879e8ef11a69f0722", "0e69af1c", "3af22d0558d6cb039e164bb47bc48265", "46234cafafbce55281c87102559f47450976bb08", "f479cdfa3488c4d8e44c8e10167a54cbc1142a7a75bb5a0ee6aa647a93a65d0f", "3b1a6d21fe44691dac4eb7c593a6d8523cb606e63cf00e94d711a574248daca5" }, // 15
{ "52a608ab21ccdd8a4457a57ede782176", "1ccb278f", "72d4071b78731c61b61076067f3ef40b", "2d64a7c42ce0cb8dae2617effd031b5fe328eef6", "7ae441ed62ba0263f194386043ac4ba452bc593a5a9ad001da5c70ddc533abb1", "2c7e7cb356fdc68ec8927e499d2a6bae2b781817919c829ebbe8225baed46967" }, // 16
{ "82e192e4043ddcd12ecf52969d0f807eed", "4e448a12", "e880a1c8344c01c1aede282f4a0c6930", "f4c49546bb55bfadddb0e8f0c14add76039250ce", "b06558895e83f861bcdc2556f7e6377468341b352745caf2605df544275e9949", "c7b12eff692d842110cc39ac60616707acb3f9b0f1cb361b94577efc529ca26c" }, // 17
{ "75683dcb556140c522543bb6e9098b21a21e", "4b50b9e1", "9b92909591db3d4957047c6bb3c06880", "bb479acce571cec0775532af7c7b19c2a719456d", "7da11d5a5c7e39d51d7509bd8f5819f7110a3f7aecaf314cf7d6a5943e70ac66", "493ebaebc04776f4e067555afa09b58c850fdf1b0e22d4bf006ce41c091dc762" }, // 18
{ "06e4efe45035e61faaf4287b4d8d1f12ca97e5", "45cad288", "b1f1c44c82ba049a4f540e0206cdd045", "82c2585cbecc9ade3bd64895a84a85bb97952e43", "0b9e07de6287032320423371a8ee66e149ae208e248587443e122c9f8cc600fb", "1d01f3120ecfbdd28dce44317666cf864f52391b9eca3843db45667c2e0a98ad" }, // 19
{ "e26193989d06568fe688e75540aea06747d9f851", "1a5edc0e", "9e0e0f99c95fa883fc65e74bc94149e5", "bdfd2785148f71a6ac5790d3e65cb7638a3efdc6", "e88d019b09a378a39bd5bfa33215c358303c7f13004ce3a12650aa70d01b8ca0", "2c1e61e5d45203f27b86f1293a80bab34192daf42b8623b12005b2fb1c18acb1" }, // 20
{ "d8dc8fdefbdce9d44e4cbafe78447bae3b5436102a", "2803f7c6", "2c6e363d11a7a5d810dce54d3e28c409", "3ac65fbaceb1591da5b96bfa50c825e7e7c61a20", "fdfa03e288a4af6d325049bfc4b76e9c8178321d484ae88fb1025d26bef78679", "ad0e3f29767067e929d1cecd95582df8f2a9beb92eaa27eeb315f620365a9244" }, // 21
{ "57085fd7e14216ab102d8317b0cb338a786d5fc32d8f", "64ba010b", "92ca1e70af2d4926eaca1acb0a7204da", "88ba72d3f7331c8235bfac25f0af1fce30534676", "a05e71cd70727ee68b029f36bdd7838dc3c69bbdb956c21b68dfa439421af5f9", "2b4eb5de20e86074cabb55bfa63a5c8c6ae15679302061845b9cf233e17c906b" }, // 22
{ "a05404df5dbb57697e2c16fa29defac8ab3560d6126fa0", "53948692", "1ca08b8e52e2d6956504aeeb4175d98c", "1c3329ab472a203c11a74936c786177462822bd8", "7ea63cd84b9f0b9ce4daf224835d06e029a4601eeb5a37496799a3d84ed42f8d", "6ae04c6c6f3651f1f64c0ad69733990b41747c93f87acb813bb25bb1fc0eff07" }, // 23
{ "aecbb02759f7433d6fcb06963c74061cd83b5b3ffa6f13c6", "5e55297b", "f9715ac28f13a90a4dfb017aee4dd9b1", "76538ebb720710421b935ce23fbe37543e090cb6", "19045e899afc4a35967ca5c7970a5b0ddc99f70f69716dcf62c46825be0aa457", "40f9f55bc55da466bc3dc1f89835a64094572de73d64ed6646a1d3b667be70a9" }, // 24
{ "aafdc9243d3d4a096558a360cc27c8d862f0be73db5e88aa55", "f7f32407", "6d71d851e6fc1cc3a44be9c16e546cb9", "e294d8908f122b8d7ccfc1223058636eb276d405", "4c8487b6a2561455e1535c1462722c1042fe2f478ead5a6f65f39bad004cab59", "c64becf7b75fc885d5853924f2b7d37abcefd3da126bb817697e1a09152b1ebe" }, // 25
{ "7bc84867f6f9e9fdc3e1046cae3a52c77ed485860ee260e30b15", "edbb117c", "8a104d5ba0f66e66042486f7e106fe87", "a1a306755332086effbf26d6c20af9b50e415285", "8c41fa0b07f82b9cd0026de7e38059680f69f2d20f426596e88b4d800aa638b2", "57d46a6bc8fab33601538dad27f98c66443032cc3912434c28eb88d0af44c52c" }, // 26
{ "fac523575a99ec48279a7a459e98ff901918a475034327efb55843", "39f0e9db", "7de1128f904f39f92f1c51989c94aaf8", "a58b983e90870a964296a164bd02b62ffff7e12f", "a84dbb8acfe2c5ab82c2ed371040a3221f7cde534baf134e24534a3b5105da69", "7c956503d5b4dbb764ff8e66fa74ce0f9132da90ea3543f669c9dd08e413e33c" }, // 27
{ "0f8b2d8fcfd9d68cffc17ccfb117709b53d26462a3f346fb7c79b85e", "6b2ad7a1", "d41bdd74f0dbbcb034ff01402a163736", "ae41363098fe07213fec440bb03be81aab0fb7f0", "afecd3e65dcb52c4c8625471842d007575e4cb33942ac4e6377014cce668ba4f", "6de164a9626d5a4f54d854ac158994f35a8e362ecc753f55182790934a2e0d06" }, // 28
{ "a963c3e895ff5a0be4824400518d81412f875fa50521e26e85eac90c04", "51e5475b", "bff43c6ee76dffa8850237aa11ec11b9", "ca408361c45d44c71e90fb6b4c69955d08c58ecd", "7ac86f1239e32eedaeaa8ed184445c8b017e9124a5d283cf4393fd80ad3996f0", "b760312bd1b279fc672479d21c5ed349e5fe96f08940237b4515452721c49a16" }, // 29
{ "03a18688b10cc0edf83adf0a84808a9718383c4070c6c4f295098699ac2c", "0807648c", "268c59a326b83e17f42bd7500c916290", "a9b323ca196695d80ce6cfb26ca9a8b77e51b008", "5e9c68da67265b87ded2f3b2a93744f5b7ec832419916aadf0ea78b63ef97432", "94fc255de4ef19c0da4b09b2e2fac21f20048b46f17c30685abe40d5c743f375" }, // 30
{ "84fb51b517df6c5accb5d022f8f28da09b10232d42320ffc32dbecc3835b29", "dddccc2a", "6b393afb85a556ff1b38ceef3ba946c6", "cda4605fb1409be66738df89f20f3da5e6609056", "9929cf1e6fac383f3a2fa322af8d125753bcf9c28ededb9e63a45da0cf5c5984", "39a4a0ffc4603698ae0a4f3d24b1bc42ac7a2d7d923e7a5d602453e82d5323c5" }, // 31
{ "9f2fcc7c90de090d6b87cd7e9718c1ea6cb21118fc2d5de9f97e5db6ac1e9c10", "c90368f7", "b4b5b22fea8d7a60d07859b46b03b810", "5eb1836714dd13760ec23a8187c3c64086dcc3f8", "ace84f09d49226d391e3704ff36b0cb5a61c0a0727e6bc5a7188e5c273a740db", "2f1a5f7159e34ea19cddc70ebf9b81f1a66db40615d7ead3cc1f1b954d82a3af" }, // 32
{ "de8f1b3faa4b7040ed4563c3b8e598253178e87e4d0df75e4ff2f2dedd5a0be046", "e43f6c2b", "c09b81300dfe5d57cd53b29971ef55ca", "2299eef7f22c57e489c29155e632b10d6ad28761", "072d632c7b4d6cf25f3c18336d572d22759d5a78e5cf9ee5f3d844f2b6345cb3", "1c57fe0e38cd3a124eaa6cd87f70a079bccc073a341e8c0eb1976fb3a3f7b774" }, // 33
{ "62f154ec394d0bc757d045c798c8b87a00e0655d0481a7d2d9fb58d93aedc676b5a0", "2aa78ff5", "c1b47551dbd87287e3786d29f0ead5c2", "b53c51b62b98bb6a897bdf2e4de297ee6f80d64f", "2d503f6f3432d37088b1890299259db30d158665604ea63e82cc43548412bd35", "a905603b186ef4f2d5b2d1bcfda504c68ed5eb9b0c7b7ea2a001575f5aa69e68" }, // 34
{ "b2dcfe9ff19e2b23ce7da2a4207d3e5ec7c6112a8a22aec9675a886378e14e5bfbad4e", "d9c9c459", "39a82f09125434582385b8b09ef042d8", "303ea353679f64e0e7ea72f308908091b3f798b6", "c4a3feb41cd26f040c26f0b0ca12f8e3d55f0bb39771ee087c5086118e098146", "fffd39f7c451788eb0316f429ea0a7c0ac8091657aca28f1560ed5775e8c4c12" }, // 35
{ "47f5697ac8c31409c0868827347a613a3562041c633cf1f1f86865a576e02835ed2c2492", "5b1508f1", "cdb044f567cde9d20b264add4edf6a56", "499279bf8d5c7ac1f0ae11de2a7a774bd949ad17", "cb9e4c92d9cf019f4c3156ab791350ad8e42e502f7f2eb64e47466aebbffd283", "6f55becd168e0939ba2fa090257b1727fc66491a44493279a5beacb9e3435324" }, // 36
{ "512a6d292e67ecb2fe486bfe92660953a75484ff4c4f2eca2b0af0edcdd4339c6b2ee4e542", "9c7afee9", "a3f7368cbeb89e1ed9564c147bc62ccf", "1aff151f3d6e3c71a2cfb9cd0170a1f907aa2e28", "5f4b5f2cebc6e5c7d8939273d3c63597efb8e7414b7373dfa4060041252f07ef", "84649bffcd48527b9288e8da5f52fbab2604dc5a91c4b0b87d477dbd7b40b6ae" }, // 37
{ "973cf2b4dcf0bfa872b41194cb05bb4e16760a1840d8343301802576197ec19e2a1493d8f4fb", "2466a23c", "91a3389423f3aad784cfa032e8511fac", "a950d6ce4683c8e9c97db7ec3ca8770ae1d78410", "6bcd52fae737be4465e3688ce0620b668d1b3b926bf12265bdcf215e22bee702", "d4055b4e3e2aea1c67cc99fd409d574e53e1e296cf9eef73c472ab92a6cb6609" }, // 38
{ "80beebcd2e3f8a9451d4499961c9731ae667cdc24ea020ce3b9aa4bbc0a7f79e30a934467da4b0", "9869fe61", "4e9f41ef61570fb59c1905c127a1dbb6", "d46154473fd626ed75429dedcb6d18c14b84bf09", "61c7b8427e946955efc51dcbe85c33f770f35c9f87cca931a220435cd5cb52c4", "5694ca2f3b9962226a87163ab38325bcdc898a732dfeb2c36db4eb88616b8741" }, // 39
{ "7abaa12ec2a7347674e444140ae0fb659d08e1c66decd8d6eae925fa451d65f3c0308e29446b8ed3", "30ec2a35", "59b97d4bb9621edd21508e983d1e0162", "50aa4e5b0d5aa3fe38a7b6539060a393f132e754", "7e9d4111cc710b6b24290fcab6934ad08cd4b239c1a0cbdde71f685f0a1e6fd9", "8cf287ad03ab4a74086620cfa4cce74f48fa5cdb15ec02b1f721736a4f849e60" }, // 40
{ "c88dee9927679b8af422abcbacf283b904ff31e1cac58c7819809f65d5807d46723b20f67ba610c2b7", "5a9f457c", "dd004f029f857a4e9acfdc516191dd0e", "baf9d3c7d2b18f36ac2981c7f071e63bbbfd3493", "2668d27f283bce5f7919d490d721aea6bbd0348332a2cde536dd4bc1912c55ad", "c5d5af22a4df9acd0c056fa30d8e240b679a20d4d2630260f779ff815ca82d7d" }, // 41
{ "01e43fe350fcec450ec9b102053e6b5d56e09896e0ddd9074fe138e6038210270c834ce6eadc2bb86bf6", "44d76f15", "28b66ebe60836815e0050c6dae6cb383", "a0a7388255f447285f5419ff96aad6f1818d6de0", "c60b5602cb8a1a23ec67b6c57ab41152ea1360a532b146a8e3195b2c23b32b48", "0ac75279adff65660464550a283fecd4e0610d88f35574c3d7ac5d22262a2fe8" }, // 42
{ "337023370a48b62ee43546f17c4ef2bf8d7ecd1d49f90bab604b839c2e6e5bd21540d29ba27ab8e309a4b7", "aef8f701", "66191acef6407facd6776248be2b2814", "deac10320e720100261ec67889ae36a13688c4e2", "612af005d7f47d3d7cd0e8cdcca4571139fef602e82e64e7e027189e5b1b8700", "81917ae290dbba17289a8a67e5c2e8b12d3dde0efe9f990198a1763ff4f3dda7" }, // 43
{ "6892540f964c8c74bd2db02c0ad884510cb38afd4438af31fc912756f3efec6b32b58ebc38fc2a6b913596a8", "a1739060", "72f332cb3d1ee64f1956eea0f9f65b64", "42b6406d40071927e77a0d7749de78a7f426b290", "42633916521313c491f53a8aed2de5647bd21befb8423e31397e3ba76e7cc43a", "138e75e72fddd927e591315af8d3aba280efa36230a3309a97bcde5a78c31589" }, // 44
{ "f5961dfd2b1ffffda4ffbf30560c165bfedab8ce0be525845deb8dc61004b7db38467205f5dcfb34a2acfe96c0", "2ad774c3", "e729ab5e0ed1eda842771b4cab4f7e24", "3e1b964d0dd2c054862c038488b8ab0f1c38f13b", "bb15e052c6167318eb92530ee2a6a38bbbb03888b27ccf17402dd91336742e7c", "21bcdad3fef3e5b859cb0912a2991efa661bad812747292ef0f79a8fcc6b4e98" }, // 45
{ "ca061a2eb6ceed8881ce2057172d869d73a1951e63d57261384b80ceb5451e77b06cf0f5a0ea15ca907ee1c27eba", "b0ecc329", "6886c2fe3bd64c5d7e0a92dd9d3de9c1", "75f7e1712c432f990d5d47bb410bc0ed1f01d340", "1debaf5b88a075e43a0ec8765fa3830b3e08655162b28ce9a9357c4424869fa5", "8d6fd9c559b0b4948f91337916084c0082a16a0755b0a00811096e973e48b3c8" }, // 46
{ "1743a77251d69242750c4f1140532cd3c33f9b5ccdf7514e8584d4a5f9fbd730bcf84d0d4726364b9bf95ab251d9bb", "26ce2541", "48a07b1571b3de06d65a88e95ca57b50", "2c2bb28f64a17b4054376a503bb9c57f1e142bf4", "de11c81dd4609233c6a2d73a3ac06a20e312e6e1c0f5d351bc72b3d5c40961a0", "1dd23ae7aadd61e712bdd82bd60a70dd9d66c9fd79dbfd8669e3eaabf7901cdc" }, // 47
{ "d8faba1f5194c4db5f176fabfff856924ef627a37cd08cf55608bba8f1e324d7c7f157298eabc4dce7d89ce5162499f9", "8ebccf97", "3dea64ea9ed114752e867afd704a9762", "b8be5ea10dee2d8190d82dd47b94d6a8019baec8", "ecd5464831f5a8b034f07b3ef7b96d096751d76425d0771bbfaeed9894721ccf", "34f8607ec10c092c1ba0b6565ce6197062c4e1a35a8e8c723e48a2d2416c3790" }, // 48
{ "be9684be70340860373c9c482ba517e899fc81baaa12e5c6d7727975d1d41ba8bef788cdb5cf4606c9c1c7f61aed59f97d", "46a4b59a", "83c390e922be9d42cf14d8df71bf3541", "7a6281ec0b58c82a80b1ee18e8bbf22e6d84df60", "171300d37d33b2f8942ed26aa86c67346fc0c9710c6e59a83472c4dafc033aef", "19a8577fc90fae5d6a6b2e0c1ff155515502cfa1757029c09bebbfa263d9a363" }, // 49
{ "7e15d2b9ea74ca60f66c8dfab377d9198b7b16deb6a1ba0ea3c7ee2042f89d3786e779cf053c77785aa9e692f821f14a7f51", "f5661d98", "730487d5390fd8a72bcde0109529f614", "6e17b4575af829c6ee18e24fb6eae024a9baaf49", "7863f2acd39baee07b57e2e65a391dc828c05de45821e52e3b908b43a9ad9705", "9d9dbb4ce7d01d009e72a66051acc16805e49f598cbe430c5d4c22a881a64b3f" }, // 50
{ "9a219be43713bd578015e9fda66c0f2d83cac563b776ab9f38f3e4f7ef229cb443304fba401efb2bdbd7ece939102298651c86", "97779492", "2c2ac042030f8f1645df0e9575bd2d41", "29309a4a739f0e6ac4ef1fd38871c9a02a326d10", "ee0924a0f948eba8bc731c0489da61d6665829fc2e6ea1b5378964f5a77dd7dc", "13f0d951b64481135466cfccbe52418cc1d03fb16b5b696c35d724f6f55cbb6d" }, // 51
{ "c8f2b693bd0d75ef99caebdc22adf4088a95a3542f637203e283bbc3268780e787d68d28cc3897452f6a22aa8573ccebf245972a", "2d2ad237", "d72991ae45a2f1deaf888c4e9886d3fe", "88970ef3bb5191e6927a639dc105835e1b98aaba", "f7f7c47d804f0d9455426e236676d6e9ddd91bf99e40e23220ca911d99d88ada", "fb2fe7b00b75c42305cf31de14d98f904e8c46dc57bb6f94c282ca8c13dc45db" }, // 52
{ "ec0f99711016c6a2a07ad80d16427506ce6f441059fd269442baaa28c6ca037b22eeac49d5d894c0bf66219f2c08e9d0e8ab21de52", "69f4b6eb", "590fcad19889b907e3d6bbdf991edc93", "a63c6fd614d977f015fcc29936dfbffc9e8f2d33", "ee99da04f780abe64d2c1ee1170e7f678c50683a7b9303a84678c6ebdf9b9a7f", "d54cbf7d5c80ae11a0d0bad4e95ab18b5f07c970621f3936447a48eef818d06e" }, // 53
{ "0dc45181337ca32a8222fe7a3bf42fc9f89744259cff653504d6051fe84b1a7ffd20cb47d4696ce212a686bb9be9a8ab1c697b6d6a33", "27569834", "e087a2fb0e175b748d68833fbddad14e", "01c8e2d5274a8daf51bb207eee328c33b49592f1", "860c4d344cd31e574e20ae9a54ed146f690823930e43947e89adfeda3da669de", "ff050a45adeef4cfc7d964102ba877c80320a37794893e6865965ec2547cd4c9" }, // 54
{ "de286ba4206e8b005714f80fb1cdfaebde91d29f84603e4a3ebc04686f99a46c9e880b96c574825582e8812a26e5a857ffc6579f63742f", "43ab2765", "1c4f5048955f692961be8682e7226025", "e81bed804597822ac47ca7a507976972eece5c60", "99a9fa276e7471535a13e41abdb1dd5c1013ed1f4d57a4c7b9433455d3cdc705", "1bc1bcc70f638958db1006af37b02ebd8954ec59b3acbad12eacedbc5b21e908" }, // 55
{ "eebcc18057252cbf3f9c070f1a73213356d5d4bc19ac2a411ec8cdeee7a571e2e20eaf61fd0c33a0ffeb297ddb77a97f0a415347db66bcaf", "4d3ce864", "6d0557d282d4ddbfa3f0607030db59ac", "d493f943e6d7e52989990f1bb88c835e9a14ab59", "c8d39c9dabb62cb284be55658b05412b50ff3eda8ac98ae6bc616f466aeb2650", "f7bde239ad087aa7dabe42cc4d3c49380a026cd239a7faaf34a2233469a44a4d" }, // 56
{ "416b5cdc9fe951bd361bd7abfc120a5054758eba88fdd68fd84e39d3b09ac25497d36b43cbe7b85a6a3cebda8db4e5549c3ee51bb6fcb6ac1e", "a49c059d", "2a51205e846de5953d7e1c6900fc574c", "24a9ea1d842750fb805a8e1985d7cfaeca799fa0", "03f7b846ea8f9e26760eeaa30eae500646819842d6af87ca64275b865aaf43f7", "ef845aac2aaf0a793108204ff380e0a30f2558e7acde4531ab22f8ec79e26a69" }, // 57
{ "5c5faf66f32e0f8311c32e8da8284a4ed60891a5a7e50fb2956b3cbaa79fc66ca376460e100415401fc2b8518c64502f187ea14bfc9503759705", "63822070", "2d4d21e2117980b30ee1827876ae37f7", "45ec45c12ae8056e31df5578659ac18b077e0337", "463a6a7d0765f0a520f4dff288c4caa7c4c0ce3080e3703cd47122a7ee8b9434", "26db514e01e034c678b636d40ba367da2f37f67078bb576ff2b8559b3517484d" }, // 58
{ "7167e1e02be1a7ca69d788666f823ae4eef39271f3c26a5cf7cee05bca83161066dc2e217b330df821103799df6d74810eed363adc4ab99f36046a", "a2c861c5", "8d04f5ae0093555f98532d29e062138c", "ea91f748c7a9137eda2a82d7e8e9dbe54d574949", "c82776eca46928e0d5b3d1c43db40953cce11013cb3528fec5b882fc5b286fc8", "5dbd4b558463196211465c1fc32401fc2d8e41ebc5e6badd1d8f7c4f090f728f" }, // 59
{ "2fda311dbba27321c5329510fae6948f03210b76d43e7448d1689a063877b6d14c4f6d0eaa96c150051371f7dd8a4119f7da5c483cc3e6723c01fb7d", "0bf07be9", "0d84254eb21804f52cc6155c736bfe2b", "905fac724e298c9849ae82c0c0d3a494a8060085", "55d4462e8486ebc14e2f5ba7f573330faf3a0d56bdf7701ee2820aba265d7ac0", "355c79fd6e6fa88ed402b6979fde1ed805498abeb101f4231b5d64d1439d552d" }, // 60
{ "95d1474a5aab5d2422aca6e481187833a6212bd2d0f91451a67dd786dfc91dfed51b35f47e1deb8a8ab4b9cb67b70179cc26f553ae7b569969ce151b8d", "cb5e3049", "dca6b7cded7224dc17e8c7e506f4e011", "b17fb3167bc83a7375ff6ddcd5f0b552ad9ddc41", "4d78228bf419b23d867082d8d5c066a4aee56a9bb54224d3b5cbd2c04364d99c", "3d9c9bf09d88211c7e0056112d073ee85d00acaa4da7a668fa017b3273cd4d4b" }, // 61
{ "c71bd7941f41df044a2927a8ff55b4b467c33d089f0988aa253d294addbdb32530c0d4208b10d9959823f0c0f0734684006df79f7099870f6bf53211a88d", "4eabb06f", "fa630a5284e5180afa75d6ba9a0ff421", "5792719abbd47647358eb65529abd4136d501af5", "48d4ed4341aafba1f02bbf72eeaf2bf5991c04ea3c643d7665f0130fffdc9165", "67980d28e2e658e7a24a2593a28167a13d907d06f47729d47ca4fe1772f8b3df" }, // 62
{ "f57c64006d9ea761892e145c99df1b24640883da79d9ed5262859dcda8c3c32e05b03d984f1ab4a230242ab6b78d368dc5aaa1e6d3498d53371e84b0c1d4ba", "8ffc4b50", "90d5671bdc15f8f96c3745f6f6020a8e", "632ee5446b709013fba8123b67e49dc7bdcc4c4f", "ce122fb56c82bf0cf7953b837e2f00cb0546f5b5d91f7af3480f659ed6152390", "a8df6b76df41994f7593f1a81967e77ee180e31183d1c4a569db854e61e99b05" }, // 63
{ "e926ae8b0af6e53176dbffcc2a6b88c6bd765f939d3d178a9bde9ef3aa131c61e31c1e42cdfaf4b4dcde579a37e150efbef5555b4c1cb40439d835a724e2fae7", "ded134c1", "f8885d6cda92c999dc4bee554df7dd2c", "6c4664cb736cd563f74f52cea42e33d6d617f153", "f4a1a02e8e35822107cc08b5b21b661c058e2825f3c7cb2a3b6d40f3ae89211b", "27a6441ee939b46e2c378d7afeb0e891c47a28120e488eff0ab71af08788ceb3" }, // 64
{ "16e8b3d8f988e9bb04de9c96f2627811c973ce4a5296b4772ca3eefeb80a652bdf21f50df79f32db23f9f73d393b2d57d9a0297f7a2f2e79cfda39fa393df1ac00", "e891cf16", "09ceb3a6fa3e2d38467a6969d43f6587", "6ba94f05cfa29501ff47ae917e18763e063229da", "16b1449186ef6d27ddf9f8ddfe23c59e51a953833c7df2e8c6a7528403f3ba68", "c4bb067383002db44ca773918bb74104b604a583e12b06be56c270f8b43512f2" }, // 65
{ "fc424eeb27c18a11c01f39c555d8b78a805b88dba1dc2a42ed5e2c0ec737ff68b2456d80eb85e11714fa3f8eabfb906d3c17964cb4f5e76b29c1765db03d91be37fc", "82e3941f", "09f55194b57e25646de7c5e4a8635f5e", "1e2895343ba31a9e32730f8156c68369e3f4132c", "9d91ce1295f7acca7bdb2e2ff0794e5e2917509fe03bbcfb34bc8dd7e536b8fb", "ae773915ca642d80413330c9e0ee9bd06653c0023c5c0277100f3b1526eaa51d" }, // 66
{ "abe3472b54e72734bdba7d9158736464251c4f21b33fbbc92d7fac9a35c4e3322ff01d2380cbaa4ef8fb07d21a2128b7b9f5b6d9f34e13f39c7ffc2e72e47888599ba5", "e73f9991", "d561fc54a4d61467f7d72ea037bb9332", "ea1c325d0e91a757e2106792943361d47ce99bee", "f1737040e38e73ab3b4085ec8e1acf1e055a1ed8411e6cf867d0a5dca56a3364", "1cf9d6ce9cb658556b76cd7eba3e51393699ad500b1ab3f56172748db7f59667" }, // 67
{ "36f9f0a65f2ca498d739b944d6eff3da5ebba57e7d9c41598a2b0e4380f3cf4b479ec2348d015ffe6256273511154afcf3b4b4bf09d6c4744fdd0f62d75079d440706b05", "ae719e56", "313c5846da0836226ecbf50c324fb7c5", "0082b9a8ab38b32ac364e5f1a656cfe98ef9c931", "df0cd17c3fd3885653849bc8be8cad1f2171755e05176d448dc466fdb94ce780", "8d60e889e2b1020dad4b523301f5f6bbab6c781af276085af6765546fcfb95ac" }, // 68
{ "abc87763cae1ca98bd8c5b82caba54ac83286f87e9610128ae4de68ac95df5e329c360717bd349f26b872528492ca7c94c2c1e1ef56b74dbb65c2ac351981fdb31d06c77a4", "6c4cd72d", "53bfe40050067274fe7482d2a3b7986b", "328136f32226dc14f7e9dee5ba67863b669cb0d7", "6fe7f18c476330654ad42917435a5dd906c1c35f863cb2a8147a9fa10aa19c91", "dd4ff4b530552f48af9a7530a6464819ed1a5b733084f709e41daf1acb35ecfd" }, // 69
{ "94f7ca8e1a54234c6d53cc734bb3d3150c8ba8c5f880eab8d25fed13793a9701ebe320509286fd8e422e931d99c98da4df7e70ae447bab8cffd92382d8a77760a259fc4fbd72", "c957294b", "58a4f59c5a014d0d19f4b0807d3883db", "45905089a697d8542c78e1d206a0d87430fc0789", "54fe7d51e0cd082a42a4972acfdf8c59406c89ef95b79d659a84a0d07d121069", "7ac8d4bb53fc434dd8712daefeb474668f541418e6f617dba523d8392eb0766e" }, // 70
{ "13bd2811f6ed2b6f04ff3895aceed7bef8dcd45eb121791bc194a0f806206bffc3b9281c2b308b1a729ce008119dd3066e9378acdcc50a98a82e20738800b6cddbe5fe9694ad6d", "22bd0ff5", "bc3db75037ec1773fb11045a256001bd", "c29ad52ef807b4f73f3ec0b20999a996b3e462cd", "6feab1c9d115cc82efe3631535e964c3eeb5c3dad4c38d837717f8f10a3357b1", "f7b0e15a63232a2b800b23b311d357617ddfd1293e1ffe3f772692ade3427152" }, // 71
{ "1eed9cba179a009ec2ec5508773dd305477ca117e6d569e66b5f64c6bc64801ce25a8424ce4a26d575b8a6fb10ead3fd1992edddeec2ebe7150dc98f63adc3237ef57b91397aa8a7", "0ab24bd5", "9022f5cdff2c1f55ac3f5270f8d43484", "8b78f85b603c4b896cac77b41edee07c56d14058", "046155a4d0e52a53fc745278ded12590875fde9b66fa4e40a6638c1504f6d435", "b3d05af7e8c406a7c2709223791d3f5f4b3129329993220053a36293ac2b0e06" }, // 72
{ "ba5b67b5ec3a3ffae2c19dd8176a2ef75c0cd903725d45c9cb7009a900c0b0ca7a2967a95ae68269a6dbf8466c7b6844a1d608ac661f7eff00538e323db5f2c644b78b2d48de1a08aa", "8368ecf5", "92c203258dfb11755b1a6f3d15095f45", "e0a01e53a373265566a422f5209346605eca2252", "450effce3b3be76285be139ad8c15cdb36d847a70122e7754cc50da7b4f262e6", "6c47e2ea4ba29e17792defc4b707754c4664bde15168a5100bf881ec7c02b258" }, // 73
{ "0efa26ac5673167dcacab860932ed612f65ff49b80fa9ae65465e5542cb62075df1c5ae54fba4db807be25b070033efa223bdd5b1d3c94c6e1909c02b620d4b1b3a6c9fed24d70749604", "f5fc8790", "c125928b6cdf8b88f30efaacef4acba0", "732dbb9df2f07abc0ba482376a401acb1652fd1a", "88f8922134a0dfd8cf733e69a67f79695c157a12f004e0f41f47dbe25e929f11", "82a66bed668dcc14af12c14c976ce650049e9d1d9969b83d1dd3b6f1c07d252b" }, // 74
{ "bbfd933d1fd7bf594ac7f435277dc17d8d5a5b8e4d13d96d2f64e771abbd51a5a8aea741beccbddb177bcea05243ebd003cfdeae877cca4da94605b67691919d8b033f77d384ca01593c1b", "07c73070", "2ce5ec25b22239c42ad1e1fd4a38e7f8", "1196665356621ac4b74f7cb453a695ff51fe13a0", "6abd3225cde2afc0da502567790af919681ae1bee565192a06e5e34df7cdfe4e", "2f21d07d7b10683b9ac7a63e9fcc70cf9f887cb905f9bff5332551288b288524" }, // 75
{ "90078999fd3c35b8afbf4066cbde335891365f0fc75c1286cdd88fa51fab94f9b8def7c9ac582a5dbcd95817afb7d1b48f63704e19c2baa4df347f48d4a6d603013c23f1e9611d595ebac37c", "905d3872", "fa79da4e5b2df87ce3cc98ab763fd19c", "16b3a27baeeecb4c4c66c7f235fbd4f6c5839145", "0cbd201eca6a8fabf81c7377047a4a86f6dff090d665381fd884c6b5836b0902", "80202f01e7140db4fee490dcc50afafdf6a48ca33d362c7875b8e8db9c9d0655" }, // 76
{ "64105eca863515c20e7cfbaa0a0b8809046164f374d691cdbd6508aaabc1819f9ac84b52bafc1b0fe7cddbc554b608c01c8904c669d8db316a0953a4c68ece324ec5a49ffdb59a1bd6a292aa0e", "7e11cb91", "b9c451f86bc03e42fca7d2400609b188", "61d6f9fccf0a8c486dfa7df4417dc4d0c4e59149", "e30a878fdab9b75fc3d1f8ca1ea9c754817de4a471aa8e2abd6a7526e36274c5", "b2330a189047e3117479a2f20b3407a7d119e4ad431fe06ff1ff2a106f2ab3a2" }, // 77
{ "d4654be288b9f3b711c2d02015978a8cc57471d5680a092aa534f7372c71ceaab725a383c4fcf4d8deaa57fca3ce056f312961eccf9b86f14981ba5bed6ab5b4498e1f6c82c6cae6fc14845b3c8a", "dcdff841", "4551bc9250abb5607cca78ca71137a3f", "a95f70deef0c1733a02e6297a67aa61f0356e005", "9b163642ad529f4f0ac03b31cc22752599fd3cc3abdca1124cbce15eab11021e", "bb9b9bb685c241f8d63fdbf0dbaabcef7075add7ba405a2fffe7ad5b23e021c7" }, // 78
{ "12d9394888305ac96e65f2bf0e1b18c29c90fe9d714dd59f651f52b88b3008c588435548066ea2fc4c101118c91f32556224a540de6efddbca296ef1fb00341f5b01fecfc146bdb251b3bdad556cd2", "9ccb3cf0", "0dc5922d3935802af173a0825b8793cd", "6a59742f6d780f0161427835f743187e7c4de6c2", "e9d510eb338e4def24410eab6e26845a721aa9feba233d225f18f9a4d165c0f8", "f8316a367aa0316da3562f319d522e81f4a8bd2e2108d2532126f4a903704ba3" }, // 79
{ "871a0d7a5f36c3da1dfce57acd8ab8487c274fad336bc137ebd6ff4658b547c1dcfab65f037aa58f35ef16aff4abe77ba61f65826f7be681b5b6d5a1ea8085e2ae9cd5cf0991878a311b549a6d6af230", "c37eb643", "b14fd7247fb0600a4ee58d7d02c54573", "5ee0c3e4b737f3c6eb0537c6dba47e8e33334a39", "3bbc51465e6ad6c102c41cf61c0a510d191a522e7a8981eef519149d1bca5fe9", "89e3ebd02b229cd759612a5521d867ab2a1594bc0b1fe6a78b7954ccc84caf03" }, // 80
{ "e90b4ffef4d457bc7711ff4aa72231ca25af6b2e206f8bf859d8758b89a7cd36105db2538d06da83bad5f663ba11a5f6f61f236fd5f8d53c5e89f183a3cec615b50c7c681e773d109ff7491b5cc22296c5", "ba83a755", "a7b5bb4aa7b91d2853ec40c62ae71adb", "93e5e5a709b797bbb6e77a7ead3edec6d77d463d", "2ab2197e676517e8e900f69dbbfb6251e5dae049432d18adbdee892f42601e73", "2e7cc875305ea6bb9c2fc770b9d84fd93b96405df9b93307f6b5de26e135724c" }, // 81
{ "e728de62d75856500c4c77a428612cd804f30c3f10d36fb219c5ca0aa30726ab190e5f3f279e0733d77e7267c17be27d21650a9a4d1e32f649627638dbada9702c7ca303269ed14014b2f3cf8b894eac8554", "8bac7df0", "3bed3364dda24e4f121971960ace8cd6", "80ab947730a8b954b0e0108f9add9808ad9d4d4c", "a245a9c8b82fcf89b008b8f68393bdbf70a7750efa9f946a493025f5b929e398", "ecab75f28a728429cb433ec13310d1b850ccf522c38d2fa6dfa489963d6d6ca7" }, // 82
{ "6348f229e7b1df3b770c77544e5166e081850fa1c6c88169db74c76e42eb983facb276ad6a0d1fa7b50d3e3b6fcd799ec97470920a7abed47d288ff883e24ca21c7f8016b93bb9b9e078bdb9703d2b781b616e", "8666f487", "0b5846abc9ec2f73f95a046a98db99e5", "6d8d4d535d9478bfe55bc439bd72aa4ca059994f", "40319d72d16dd3b02e5049b28dd4de6bd6263796085069184ca868912d1a39ea", "021c9459d1451f3da4c07c029a8681945c87c5bebc6c30da1d95c5c49d8ab95c" }, // 83
{ "4b127fde5de733a1680c2790363627e63ac8a3f1b4707d982caea258655d9bf18f89afe54127482ba01e08845594b671306a025c9a5c5b6f93b0a39522dc877437be5c2436cbf300ce7ab6747934fcfc30aeaaf6", "b9b607f0", "8e7c9e38008a99bc26850bdcfa296fd7", "5a991f5a462d57c678f8b1a853d5e63510c0c01f", "9885b7b4d61caee20fcbe9a902496071f3113f34d144929891ee711b12f6d1db", "4642e21622f15b09b9413659680116bf2f96cac2384b8c79f1328d5dd36d7a01" }, // 84
{ "08461f006cff4cc64b752c957287e5a0faabc05c9bff89d23fd902d324c79903b48fcb8f8f4b01f3e4ddb483593d25f000386698f5ade7faade9615fdc50d32785ea51d49894e45baa3dc707e224688c6408b68b11", "07839217", "03e0732d64855293605a4ffea43e2151", "e734c52c2930b653dd5b01e04fde3ad7b9eaa51c", "64278b8ed65d1d1ee032d6289d74f7d5637d0538e7b05bcd099ca7cc8f6263e9", "8daa47c3572157266ad0276d5926aff2872f06b0cd7b974a80d7a6827d41d782" }, // 85
{ "68c8f8849b120e6e0c9969a5866af591a829b92f33cd9a4a3196957a148c49138e1e2f5c7619a6d5edebe995acd81ec8bb9c7b9cfca678d081ea9e25a75d39db04e18d475920ce828b94e72241f24db72546b352a0e4", "d74ac160", "bafd00316db76387bed7c84492d70158", "7e1b8fa40e87f9b12d40a1fcfd66b2ca708540d3", "3a4145a03567aae008db8fed2a58f616dcfa6d345ae38aa27b9e2ead32768a9e", "345365232ce9afc655dce4bac23f43c8acbdf9016d4bc2344be8d396a4919c34" }, // 86
{ "b8d56472954e31fb54e28fca743f84d8dc34891cb564c64b08f7b71636debd64ca1edbdba7fc5c3e40049ce982bba8c7e0703034e331384695e9de76b5104f2fbc4535ecbeebc33bc27f29f18f6f27e8023b0fbb6f563c", "60457106", "65ec6a553b431e4fa351cf2dfc6c1b53", "d887f88a626f98cad59e0a5b2484189bb1accc6b", "c50b8c10e4dbbcd0055d9a81a89f2ac18b709715377eb4048edbc4b497165f5a", "f52e102e57293878c28f29deb47792324fe455a62fa7441aabcc16a9cfc40ffa" }, // 87
{ "0d58ac665fa84342e60cefee31b1a4eacdb092f122dfc68309077aed1f3e528f578859ee9e4cefb4a728e946324927b675cd4f4ac84f64db3dacfe850c1dd18744c74ceccd9fe4dc214085108f404eab6d8f452b5442a47d", "966eb885", "8f37ffb065d2ca3e5e40930455518773", "3103211925d1886b7bfe73c42f24e000ddde8e01", "63deff17e210cd39682f253d819cfb454d6434bb72aa36d3074c808f051043d5", "2b89aa88b1b7f9f8ea461c4c5cae4829125f45f5697deadb8db2e964524c0d91" }, // 88
{ "1755e2d2e5d1c1b0156456b539753ff416651d44698e87002dcf61dcfa2b4e72f264d9ad591df1fdee7b41b2eb00283c5aebb3411323b672eaa145c5125185104f20f335804b02325b6dea65603f349f4d5d8b782dd3469ccd", "a4fb2fb2", "52d15ee0e65cc07d84370f420f3f4ccd", "1baeeea41fcf4bc3cc4178d77475f869369b8a36", "fb76aa04f9f2538c4262e8cd4ca5053ea2e2b082b97a484293fce02d97abe341", "3f3092365982c0b4278055beee9032ff9d1060e03c3b087e1a6197defc707e1a" }, // 89
{ "b180de1a611111ee7584ba2c4b020598cd574ac77e404e853d15a101c6f5a2e5c801d7d85dc95286a1804c870bb9f00fd4dcb03aa8328275158819dcad7253f3e3d237aeaa7979268a5db1c6ce08a9ec7c2579783c8afc1f91a7", "5412b36e", "ae8786808d7ce1a0d9a9226befb0bdca", "ab82cef5607ffa69e218ff71fc0d2d97bf713d03", "4582b15b38b27dca503ef8423b249a7703e987953139129c1468a3ba6b826740", "3c74aae2f340a24178cbab51004cba1aac3d91133c300715ea82c177269c0556" }, // 90
{ "cf3583cbdfd4cbc17063b1e7d90b02f0e6e2ee05f99d77e24e560392535e47e05077157f96813544a17046914f9efb64762a23cf7a49fe52a0a4c01c630cfe8727b81fb99a89ff7cc11dca5173057e0417b8fe7a9efba6d95c555f", "8724d307", "7dd591d07265406cc377020ac6c7e058", "6907d863d797deb8e46bc94ad05b6bef242a15d9", "7a41a251c2de39f9593b9808d89eb31958cec525b31d2e7a373dc29ee33ad9db", "0157c4ba44618ded11e9800afa07a0d5b6c711fc16a576c5edb71c4cc6894f82" }, // 91
{ "072fc02340ef99115bad72f92c01e4c093b9599f6cfc45cb380ee686cb5eb019e806ab9bd55e634ab10aa62a9510cc0672cd3eddb589c7df2b67fcd3329f61b1a4441eca87a33c8f55da4fbbad5cf2b2527b8e983bb31a2fadec7523", "b4e5de52", "218579c794ef71c9da317e227e90d058", "9ba690ac8b7a22662b244fc7f27c8723c3fc649e", "e146431158a7db63496e7fbb4741b820ce288a1758495ea8ef6061adbc36cfb9", "8d53dba107aaacb8422d6667f6778839f8965f8e4c8f4a851284cc91168a9030" }, // 92
{ "76eecf956a52649f877528146de33df249cd800e21830f65e90f0f25ca9d6540fde40603230eca6760f1139c7f268deba2060631eea92b1fff05f93fd5572fbe29579ecd48bc3a8d6c2eb4a6b26e38d6c5fbf2c08044aeea470a8f2f26", "f6ca3db4", "540f04cc19dea131532b643fb63cfae7", "e3b917152cab357dc3585fffc2d95e2337bd9b6f", "05f8979573501c8fb1778a9d38e9cad4ef481e5d6f6bdffb4fc642b5f3ce22c9", "5163f02233e332ad9be32c2346c9fcfe39afa5fbe9bc1cfeb92f4920155b20ec" }, // 93
{ "7adc0b6693e61c269f278e6944a5a2d8300981e40022f839ac644387bfac9086650085c2cdc585fea47b9d2e52d65a2b29a7dc370401ef5d60dd0d21f9e2b90fae919319b14b8c5565b0423cefb827d5f1203302a9d01523498a4db10374", "567891ac", "d859f008f48753ead4e62f52ca11377f", "233920ef506e9c59481d306d89cfccbb2fdbb2d5", "5ba07a5acf0fe4c89df8171896812ffea2b2de5185df097da8bde2635f512f4e", "faaf0e95217ca4b1568751ef2e4cd341d9ec33e16600bf09b92c6f1a6df84d2e" }, // 94
{ "e1fffa9826cce8b86bccefb8794e48c46cdf372013f782eced1e378269b7be2b7bf51374092261ae120e822be685f2e7a83664bcfbe38fe8633f24e633ffe1988e1bc5acf59a587079a57a910bda60060e85b5f5b6f776f0529639d9cce4bd", "c6835842", "05b12d9ac1c9854ebc86f00080321bc4", "f8429fe37ed6a336d46ab0e510d6772f0587d3bb", "65ac6f5061759518913cde199d49ec9e06c19e97c42eb99ab4f835eb8a4ab2e2", "b2c175d9d92aaa9ee72672f995b8dfd2daaf6555a0327a508218a9b447f00be8" }, // 95
{ "69f9abba65592ee01db4dce52dbab90b08fc04193602792ee4daa263033d59081587b09bbe49d0b49c9825d22840b2ff5d9c5155f975f8f2c2e7a90c75d2e4a8040fe39f63bbafb403d9e28cc3b86e04e394a9c9e8065bd3c85fa9f0c7891600", "4c61dddb", "f3642e61b5c0042af24a3571d7c9c239", "267a3f3a6fe13900f2bf1c9c360cdef18a6d9862", "4faef6b1ced3843526e9c93262647450dc7a68cda7e17f611e01bc6737d92c1e", "fb5388122306d37cee790cad1d3cddba8e9a93d5f9d78288b052482739c883fd" }, // 96
{ "38a10a352ca5aedfa8e19c64787d8e9c3a75dbf3b8674bfab29b5dbfc15a63d10fae66cd1a6e6d2452d557967eaad89a4c98449787b0b3164ca5b717a93f24eb0b506ceb70cbbcb8d72b2a72993f909aad92f044e0b5a2c9ac9cb16a0ca2f81f49", "eb65cf3e", "b7d46788d692d387300f5bfaa379ed18", "1594d253f40cabdafbe5eae70b7f6d4d142e9c1c", "9707054caf9ce8f2eb3e4304e3018beee27516bce6bf507d68adf7485b8c002f", "1c2f8d418ff6718b18dd4c756dcc8ed0f4755e8c22497a6cc19f8d7ae7fd2da7" }, // 97
{ "6d8c6e449bc13634f115749c248c17cd148b72157a2c37bf8969ea83b4d6ba8c0ee2711c28ee11495f43049596520ce436004b026b6c1f7292b9c436b055cbb72d530d860d1276a1502a5140e3c3f54a93663e4d20edec32d284e25564f624955b52", "6322e90d", "7d8e166acc1d95fc2f9098b02d431283", "25b53442fd71250f2c9a5c9df5655bfb8ead4b2e", "89e1ee5e7b902293bcb91098a2691cdc2ec0444bfce6c0078e7f2e27c06e9459", "7ea8116e6434c1caa049069dbbd9b6f0e9dc6cdfd6a889343d3b2652803078fc" }, // 98
{ "6efcbcaf451c129dbe00b9cef0c3749d3ee9d41c7bd500ade40cdc65dedbbbadb885a5b14b32a0c0d087825201e303288a733842fa7e599c0c514e078f05c821c7a4498b01c40032e9f1872a1c925fa17ce253e8935e4c3c71282242cb716b2089ccc1", "e7d1d1e5", "ac2ffed693bfcb55c8a717af6c4fa348", "ca4cf03895a389d8e926b9cca06c457db3672cf8", "3dc3e4bbc7e26c406c38c139a2c864bd7dbe71347bfc02f488c6874d90e1a741", "736d888751faac4d8e78b45b95abb15d40d98d8038c7225be0f523d5439ea5b6" }, // 99
{ "433c5303131624c0021d868a30825475e8d0bd3052a022180398f4ca4423b98214b6beaac21c8807a2c33f8c93bd42b092cc1b06cedf3224d5ed1ec29784444f22e08a55aa58542b524b02cd3d5d5f6907afe71c5d7462224a3f9d9e53e7e0846dcbb4ce", "5c444498", "9dc41264137166fe20aebb253ecce43e", "e9c3b6728e90f15a3703d1b9906e8f957ce0d4e5", "19acbb45e086963576fa1847f933f6ed78e777a4a27aca0609969362a72e3abf", "90e10b1ca8d352794d7dbd7bae410bef25f0ec7d080e053f48674237e33ea45f" } // 100
};
// return number of failed hashes
template <typename HashMethod, typename Container>
int check(const Container& input, const std::string& expectedResult)
{
HashMethod hasher;
std::string hash = hasher(&input[0], input.size());
if (hash == expectedResult)
return 0;
// error
std::cerr << "hash failed ! expected \"" << expectedResult << "\" but library computed \"" << hash << "\"" << std::endl;
return 1;
}
// same as above for SHA3/Keccak with variable hash size
template <typename HashMethod, int HashSize, typename Container>
int check(const Container& input, const std::string& expectedResult)
{
HashMethod hasher = HashMethod(typename HashMethod::Bits(HashSize));
hasher.add(&input[0], input.size());
std::string hash = hasher.getHash();
if (hash == expectedResult)
return 0;
// error
std::cerr << "hash/" << HashSize << " failed ! expected \"" << expectedResult << "\" but library computed \"" << hash << "\"" << std::endl;
return 1;
}
// same as above but convert input from hex to raw bytes first (can contain zeros)
template <typename HashMethod, typename InputContainer, typename KeyContainer>
int checkHmac(const InputContainer& input, const KeyContainer& key, const std::string& expectedResult)
{
std::string hash = hmac<HashMethod>(&input[0], input.size(), &key[0], key.size());
if (hash == expectedResult)
return 0;
// error
std::cerr << "hmac hash failed ! expected \"" << expectedResult << "\" but library computed \"" << hash << "\"" << std::endl;
return 1;
}
// convert from hex to binary
std::vector<unsigned char> hex2bin(const std::string& hex)
{
std::vector<unsigned char> result;
for (size_t i = 0; i < hex.size(); i++)
{
unsigned char high = hex[i] >= 'a' ? hex[i] - 'a' + 10 : hex[i] - '0';
i++;
unsigned char low = hex[i] >= 'a' ? hex[i] - 'a' + 10 : hex[i] - '0';
result.push_back(high * 16 + low);
}
return result;
}
// here we go !
int main()
{
int errors = 0;
// http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
// or more compact overview: http://www.di-mgt.com.au/sha_testvectors.html
std::string empty;
std::string abc = "abc";
std::string abc448bits = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
std::string abc896bits = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
std::string million(1000000, 'a');
std::cout << "test SHA1 ...\n";
errors += check<SHA1>(empty, "da39a3ee5e6b4b0d3255bfef95601890afd80709");
errors += check<SHA1>(abc, "a9993e364706816aba3e25717850c26c9cd0d89d");
errors += check<SHA1>(abc448bits, "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
errors += check<SHA1>(abc896bits, "a49b2446a02c645bf419f995b67091253a04a259");
errors += check<SHA1>(million, "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
std::cout << "test SHA2/256 ...\n";
errors += check<SHA256>(empty, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
errors += check<SHA256>(abc, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
errors += check<SHA256>(abc448bits, "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
errors += check<SHA256>(abc896bits, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1");
errors += check<SHA256>(million, "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
std::cout << "test SHA3/256 ...\n";
errors += check<SHA3>(empty, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a");
errors += check<SHA3>(abc, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532");
errors += check<SHA3>(abc448bits, "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376");
errors += check<SHA3>(abc896bits, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18");
errors += check<SHA3>(million, "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1");
// next test case produced an error until February 2015, reported by Gary Singer
// note: automatic test case 71 failed, too, same bug
std::cout << "test SHA3/512 ...\n";
SHA3 sha3_512(SHA3::Bits512);
std::vector<unsigned char> sha3bug = hex2bin("13bd2811f6ed2b6f04ff3895aceed7bef8dcd45eb121791bc194a0f806206bffc3b9281c2b308b1a729ce008119dd3066e9378acdcc50a98a82e20738800b6cddbe5fe9694ad6d");
if (sha3_512(sha3bug.data(), sha3bug.size())
!= "def4ab6cda8839729a03e000846604b17f03c5d5d7ec23c483670a13e11573c1e9347a63ec69a5abb21305f9382ecdaaabc6850f92840e86f88f4dabfcd93cc0")
{
std::cerr << "SHA3/512 bug present" << std::endl;
errors++;
}
// hex conversion failed for SHA3/224 (last eight hex digits [32 bits] were missing)
// reported by Alexander Moch in March 2015
std::cout << "test SHA3/224 ...\n";
SHA3 sha3_224(SHA3::Bits224);
if (check<SHA3, SHA3::Bits224>(empty, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"))
{
std::cerr << "SHA3/224 bug present" << std::endl;
errors++;
}
std::cout << "test Keccak/224 ...\n";
Keccak keccak224(Keccak::Keccak224);
if (keccak224("") != "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd")
{
std::cerr << "Keccak/224 bug present" << std::endl;
errors++;
}
// check all automatically generated testsets
std::cout << "generic testsets (CRC32,MD5,SHA1,SHA256,SHA3) ..." << std::endl;
for (size_t i = 0; i < NumTests; i++)
{
errors += check<CRC32 >(hex2bin(testset[i].input), testset[i].crc32b);
errors += check< MD5 >(hex2bin(testset[i].input), testset[i].md5);
errors += check< SHA1 >(hex2bin(testset[i].input), testset[i].sha1);
errors += check<SHA256>(hex2bin(testset[i].input), testset[i].sha256);
errors += check< SHA3 >(hex2bin(testset[i].input), testset[i].sha3_256);
}
// HMAC MD5 and SHA1 test vectors from RFC2202 http://www.ietf.org/rfc/rfc2202.txt
std::cout << "test HMAC(MD5) ...\n";
errors += checkHmac< MD5 >(std::string("Hi There"),
hex2bin("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
"9294727a3638bb1c13f48ef8158bfc9d");
errors += checkHmac< SHA1 >(std::string("Hi There"),
hex2bin("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
"b617318655057264e28bc0b6fb378c8ef146be00");
errors += checkHmac< MD5 >(std::string("what do ya want for nothing?"),
std::string("Jefe"),
"750c783e6ab0b503eaa86e310a5db738");
errors += checkHmac< SHA1 >(std::string("what do ya want for nothing?"),
std::string("Jefe"),
"effcdf6ae5eb2fa2d27416d5f184df9c259a7c79");
errors += checkHmac< MD5 >(hex2bin("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"56be34521d144c88dbb8c733f0e8b3f6");
errors += checkHmac< SHA1 >(hex2bin("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"125d7342b9ac11cd91a39af48aa17b4f63f175d3");
errors += checkHmac< MD5 >(hex2bin("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"),
hex2bin("0102030405060708090a0b0c0d0e0f10111213141516171819"),
"697eaf0aca3a3aea3a75164746ffaa79");
errors += checkHmac< SHA1 >(hex2bin("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"),
hex2bin("0102030405060708090a0b0c0d0e0f10111213141516171819"),
"4c9007f4026250c6bc8414f9bf50c86c2d7235da");
// test case 5 skipped
errors += checkHmac< MD5 >(std::string("Test Using Larger Than Block-Size Key - Hash Key First"),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd");
errors += checkHmac< SHA1 >(std::string("Test Using Larger Than Block-Size Key - Hash Key First"),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"aa4ae5e15272d00e95705637ce8a3b55ed402112");
errors += checkHmac< MD5 >(std::string("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"6f630fad67cda0ee1fb1f562db3aa53e");
errors += checkHmac< SHA1 >(std::string("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"e8e99d0f45237d786d6bbaa7965c7808bbff1a91");
// HMAC SHA256 test vectors from RFC4231 http://www.ietf.org/rfc/rfc4231.txt
std::cout << "test HMAC(SHA256) ...\n";
errors += checkHmac<SHA256>(std::string("Hi There"),
hex2bin("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
errors += checkHmac<SHA256>(std::string("what do ya want for nothing?"),
std::string("Jefe"),
"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
errors += checkHmac<SHA256>(hex2bin("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe");
errors += checkHmac<SHA256>(hex2bin("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"),
hex2bin("0102030405060708090a0b0c0d0e0f10111213141516171819"),
"82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b");
// test case 5 skipped
errors += checkHmac<SHA256>(std::string("Test Using Larger Than Block-Size Key - Hash Key First"),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54");
errors += checkHmac<SHA256>(std::string("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."),
hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2");
// summary
if (errors == 0)
std::cout << "all tests ok" << std::endl;
else
std::cerr << errors << " tests failed" << std::endl;
return errors;
}

13
makefile Executable file
View File

@ -0,0 +1,13 @@
CC=g++
##g++ -o crack CrackMD5.cc ./lib/md5.cpp ./lib/sha256.cpp -pthread
LIBDIR=lib
_LIB= sha256.cpp md5.cpp
LIB = $(patsubst %,$(LIBDIR)/%,$(_LIB))
THREAD=-pthread
MAIN=CrackMD5.cc
crackMD5:
$(CC) -o crack $(MAIN) $(LIB) $(THREAD)
clean:
rm crack new_passwords.txt plain.txt