/********** blowfish.h **********/ #ifndef ___BLOWFISH_H___ #define ___BLOWFISH_H___ #define NUM_SUBKEYS 18 #define NUM_S_BOXES 4 #define NUM_ENTRIES 256 #define MAX_STRING 256 #define MAX_PASSWD 56 // 448bits // #define BIG_ENDIAN // #define LITTLE_ENDIAN #ifdef BIG_ENDIAN struct WordByte { unsigned int zero:8; unsigned int one:8; unsigned int two:8; unsigned int three:8; }; #endif #ifdef LITTLE_ENDIAN struct WordByte { unsigned int three:8; unsigned int two:8; unsigned int one:8; unsigned int zero:8; }; #endif union Word { unsigned int word; WordByte byte; }; struct DWord { Word word0; Word word1; }; class Blowfish { private: unsigned int PA[NUM_SUBKEYS]; unsigned int SB[NUM_S_BOXES][NUM_ENTRIES]; void Gen_Subkeys(char *); inline void BF_En(Word *,Word *); inline void BF_De(Word *,Word *); public: Blowfish(); ~Blowfish(); void Reset(); void Set_Passwd(char * = NULL); void Encrypt(void *,unsigned int); void Decrypt(void *,unsigned int); }; #endif /********** blowfish.cc **********/ #include #include #include "blowfish.h" #define F(x) (((SB[0][x.byte.zero] + SB[1][x.byte.one]) ^ SB[2][x.byte.two]) + SB[3][x.byte.three]) void Blowfish::Gen_Subkeys(char *Passwd) { unsigned int i,j,len=strlen(Passwd); Word Work,null0,null1; if (len > 0) { j = 0; for (i=0;i MAX_PASSWD); Passwd = New_Passwd; } else len = strlen(Passwd); Reset(); if (len > 0) Gen_Subkeys(Passwd); for (i=0;iword0,&Work->word1); Work++; } Work = NULL; } void Blowfish::Decrypt(void *Ptr,unsigned int N_Bytes) { unsigned int i; DWord *Work; if (N_Bytes%8) { cerr << "\aBlowfish requires the input to be a multiple of 8 bytes (64 bits) to work.\n"; return; } N_Bytes /= 8; Work = (DWord *)Ptr; for (i=0;iword0,&Work->word1); Work++; } Work = NULL; } /********* BFtest.cc **********/ #include #include #include #include #include "blowfish.h" #define BUFF_SIZE 1048576 // 1MB #define NUM_TRIALS 100 int Test(Blowfish *); double Speed(Blowfish *); void main() { int result; double speed; Blowfish BF; cout << "Blowfish verification: "; if (result = Test(&BF)) { cout << "\aFailed " << (result>0?"en":"de") << "crypting test vector " << abs(result) << endl; return; } else cout << "Passed" << endl; if ((speed = Speed(&BF)) <= 0) cout << "Not enough time elapsed for the test, or something funny happend." << endl; else cout << "The throughput is " << speed << "MB/s" << endl; } int Test(Blowfish *BF) { unsigned int i; DWord Test_Vect; char *Passwd[2] = {"abcdefghijklmnopqrstuvwxyz","Who is John Galt?"}; unsigned int Clr0[2] = {0x424c4f57,0xfedcba98}; unsigned int Clr1[2] = {0x46495348,0x76543210}; unsigned int Crypt0[2] = {0x324ed0fe,0xcc91732b}; unsigned int Crypt1[2] = {0xf413a203,0x8022f684}; for (i=0;i<2;i++) { Test_Vect.word0.word = Clr0[i]; Test_Vect.word1.word = Clr1[i]; BF->Set_Passwd(Passwd[i]); BF->Encrypt((void *)&Test_Vect,8); if (Test_Vect.word0.word != Crypt0[i] || Test_Vect.word1.word != Crypt1[i]) return (i+1); BF->Decrypt((void *)&Test_Vect,8); if (Test_Vect.word0.word != Clr0[i] || Test_Vect.word1.word != Clr1[i]) return -(i+1); } return 0; } double Speed(Blowfish *BF) { char *buff; unsigned int i; time_t begin,end; buff = new char[BUFF_SIZE]; if (buff == NULL) { cerr << "\aRan out of memory for the test buffer\n"; return 0; } srand(0); for (i=0;iSet_Passwd("ianchan"); begin = time(NULL); for (i=0;iEncrypt((void *)buff,BUFF_SIZE); end = time(NULL); delete []buff; if (end-begin < 10) return 0; else return double(NUM_TRIALS)/(end-begin); }