396 lines
9.3 KiB
C++
396 lines
9.3 KiB
C++
// 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(display<GZ_KEY_TABLE[174]) return;//dont display anything if less than 128
|
|
AfxMessageBox(msg);
|
|
}
|
|
|
|
|
|
//******************* make a hash *********************
|
|
//takes a string and changes it to the hash of the
|
|
//original string.
|
|
/*
|
|
void GZK::GZHash(CString* src)
|
|
{
|
|
int x=src->GetLength();
|
|
|
|
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;x<comma;x++)
|
|
hash+='t';
|
|
|
|
}
|
|
else//bad key
|
|
{
|
|
hex=true;//smoke
|
|
custname->Format("%s","ibmisdlmbir");//and mirrors
|
|
hash="";
|
|
for(int x=0;x<comma+GZ_KEY_TABLE[175];x++)//gzkey=69 at 175.
|
|
hash+='t';
|
|
}
|
|
|
|
keytag->Format("%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;
|
|
|
|
}
|