// GZK.cpp: implementation of the GZK class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "GZK.h" #include "c:\data\projects\crypto31\config.h" #include "c:\data\projects\crypto31\twofish.h" #include "c:\data\projects\crypto31\base64.h" #include "c:\data\projects\crypto31\cbc.h" #include "c:\data\projects\crypto31\hex.h" USING_NAMESPACE(CryptoPP) #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// //this is an index into the key table. The key used will be the 16 bytes //that can be found starting at the following index location in the key table #define PRODUCT_UNIQUE_KEY_VALUE 235 BYTE GZ_KEY_TABLE[]={ 187,71,225,207,126,247,40,49,245,248,41,95,30,172,209,92, 251,217,54,171,87,33,139,104,51,154,59,77,234,128,157,33, 44,189,42,240,43,191,100,190,134,158,53,70,74,133,43,163, 118,13,181,228,137,246,201,106,241,18,187,16,205,83,181,40, 39,237,51,11,56,132,87,36,153,151,179,142,28,11,170,241, 80,113,176,121,56,163,149,150,191,169,237,145,7,115,245,131, 103,232,19,249,190,241,6,48,51,149,89,189,53,208,34,51, 235,201,39,149,103,137,140,183,74,69,106,40,22,200,111,173, 2,67,130,43,176,142,218,184,132,219,215,80,80,4,1,44, 172,81,50,146,21,148,53,99,83,4,157,61,204,199,12,15, 160,145,26,226,16,228,127,208,43,36,78,250,39,2,128,69, 136,40,109,159,177,113,134,181,136,224,154,150,211,117,185,220, 30,176,248,143,42,52,180,194,156,244,105,3,252,172,242,143, 180,41,215,27,18,221,148,143,242,181,213,173,49,121,82,38, 216,73,206,46,240,240,72,176,223,6,167,249,14,157,185,114, 179,55,141,89,57,184,12,14,195,94,141,117,13,74,183,108, 238,214,187,168,186,235,84,148,21,195,81,78,26,95,192,120, 110,208,98,248,1,117,159,251,7,111,202,108,29,59,125,80, 73,176,108,212,123,217,241,131,244,31,79,34,49,91,6,253, 239,214,174,240,125,210,17,14,158,68,125,193,208,3,128,61, 69,213,186,179,126,240,80,121,216,25,109,161,36,50,118,208, 239,226,107,27,225,246,171,36,167,66,52,141,160,244,128,179, 132,98,53,227,20,195,34,42,84,2,164,45,246,92,15,187, 222,68,188,201,239,131,227,228,38,135,41,96,17,235,202,81, 85,137,239,34,13,185,153,188,185,123,55,113,46,169,82,122, 78,177,69,188,106,23,31,73,182,159,127,123,101,255,86,83,0,0,0,0}; //Constructor, the key sets here GZK::GZK() { Key = new BYTE[16];//= GZ_KEY_TABLE; memcpy(Key,GZ_KEY_TABLE+PRODUCT_UNIQUE_KEY_VALUE,16); } GZK::~GZK() { //destructor: since the decryption is done on an object passed in there is no wiping necessary? delete Key; } void GZK::GZEncrypt(CString *src,bool hex) { char* instr; unsigned int c=src->GetLength(); instr=new char[c+1]; lstrcpy(instr,*src); char* outstr; char* retstr; TwofishEncryption* e; CBCPaddedEncryptor* enc; e=new TwofishEncryption(Key); enc=new CBCPaddedEncryptor(*e,Key); enc->Put((byte *)instr, c); enc->Close(); c = enc->MaxRetrieveable(); outstr = new char[c+1]; enc->Get((byte *)outstr, c); outstr[c] = 0; if(hex==false) { Base64Encoder e64; e64.Put((byte*)outstr,c); e64.Close(); c=e64.MaxRetrieveable(); retstr = new char[c+1]; e64.Get((byte *)retstr,c); retstr[c]=0; retstr[c-1]=0; //b64str[c-2]=0; //b64str[c-3]=0; src->Format("%s",retstr); } else { HexEncoder he; he.Put((byte*)outstr,c); he.Close(); c=he.MaxRetrieveable(); retstr = new char[c+1]; he.Get((byte *)retstr,c); retstr[c]=0; //retstr[c-1]=0; //b64str[c-2]=0; //b64str[c-3]=0; src->Format("%s",retstr); } delete instr; delete e; delete enc; delete outstr; delete retstr; } void GZK::GZDecrypt(CString *src, bool hex) { char* instr; unsigned int c=src->GetLength(); instr=new char[c+1]; lstrcpy(instr,*src); char* outstr; char* str; TwofishDecryption* d ; CBCPaddedDecryptor* dec; d=new TwofishDecryption(Key); dec=new CBCPaddedDecryptor(*d,Key); if(hex==false) { Base64Decoder d64; d64.Put((byte*)instr,c); d64.Close(); c=d64.MaxRetrieveable(); str = new char[c]; d64.Get((byte *)str,c); } else { HexDecoder hd; hd.Put((byte*)instr,c); hd.Close(); c=hd.MaxRetrieveable(); str = new char[c]; hd.Get((byte *)str,c); } dec->Put((byte *)str, c); dec->Close(); c =dec->MaxRetrieveable(); outstr = new char[c+1]; dec->Get((byte *)outstr, c); outstr[c] = 0; src->Format("%s",outstr); //wipe the memory contents before it goes out of scope memset(outstr,'\0',c); delete d; delete dec; delete str; delete outstr; delete instr; } //************* take an encrypted string and //************* display a decrypted version in a messagebox //display is a smokescreen, if less than 128 will not display message void GZK::gzMsgBox(char *cryptmsg,int display) { CString msg; msg.Format("%s",cryptmsg); GZDecrypt(&msg,false); msg.Replace("~","\r\n"); if(displayGetLength(); unsigned char *str = new unsigned char[x]; lstrcpy((char*)str, *src); unsigned long hash = 5381; int c; while (c = *str++) hash = ((hash << 5) + hash) + c; // hash * 33 + c src->Format("%u",hash); //_CrtDumpMemoryLeaks(); } */ //******************* make a djb2 hash ********************* //takes a string of at most 200 bytes!!! //and changes it to the hash of the original string. //http://www.cs.yorku.ca/~oz/hash.html void GZK::GZHash(CString* src) { ASSERT(src->GetLength()< 190);//we can always increase it later //note:hash is performed on user first/last name and company name //company is max 75, user first and last is max 100+11others so //200 is assumed to be a very safe fixed amount //this function should be modified as before, but if less than //a certain amount then pads to avoid overwriting other memory. unsigned char *str = new unsigned char[200]; unsigned char* placeholder=str; lstrcpy((char*)str, *src); unsigned long hash = 5381; int c; while (c = *str++) hash = ((hash << 5) + hash) + c; // hash * 33 + c src->Format("%u",hash); delete placeholder; //_CrtDumpMemoryLeaks(); } //takes a pointer to two cstring objects, one contains the encrypted key //the other the plaintext client name //returns: a string of random characters whose total count of characters equals the //feature code enabled. On failure returns a random string of characters of a count that //is not equal to a known feature code. //================== //decrypts the key and gets a string formatted like this: //Hash of clients name---->2345345345345,255<--feature code, one byte //separates the feature code //from the hash of the clients name, //hashes the clients name passed in, //compares the hash from key with the clients name hash //if hash ok then starts a loop from 1 to x where //x = the feature code byte value. Inserts a random //character into the keytag string each loop void GZK::ValidateKey(CString *keytag,CString* custname,bool hex) { CString hash,features,hash2; int comma; //decrypt the key GZDecrypt(keytag,hex); //split the key hash=keytag->SpanExcluding(","); comma=keytag->ReverseFind(','); features=keytag->Right(keytag->GetLength()-comma-1); comma=atoi(features.GetBuffer(999)); hash2.Format("%s",*custname); GZHash(&hash2); if(hash2==hash)//ok key { hex=false;//smoke custname->Format("%s","sadifjaskdfi");//and mirrors hash=""; for(int x=0;xFormat("%s","ibmisdlmbir");//and mirrors hash=""; for(int x=0;xFormat("%s",hash); } CString GZK::InLineDecrypt(char *str) { CString text=str; GZDecrypt(&text,false);//always b64 for inline return text; } //set a unique offset value to work with //this avoids using the built in key for uses //where you don't want exposure (known plain and cypher for example) void GZK::GZSetUniqueKey(int nOffset) { ASSERT(nOffset<400); memcpy(Key,GZ_KEY_TABLE+nOffset,16); } //encode a passed memory block into b64 text //need this for saving memory blocks to database //as text items (i.e. printer DEVMODE structure) CString GZK::EncodeB64(char *input, int size) { CString retString; unsigned int c=size; char* retstr; Base64Encoder e64; e64.Put((byte*)input,c); e64.Close(); c=e64.MaxRetrieveable(); retstr = new char[c+1]; e64.Get((byte *)retstr,c); retstr[c]=0; retstr[c-1]=0; retString.Format("%s",retstr); delete retstr; return retString; } void GZK::DecodeB64(CString* input, char* retblock) { char* instr; unsigned int c=input->GetLength(); instr=new char[c+1]; lstrcpy(instr,*input); Base64Decoder d64; d64.Put((byte*)instr,c); d64.Close(); c=d64.MaxRetrieveable(); d64.Get((byte *)retblock,c); delete instr; }