// This code is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Blowfish algorythms: Bruce Schneier and Jim Conger // Bruce Schneier, 1996, Applied Cryptography, 2nd ed., John Wiley & Sons // Blowfish Eggdrop algorythms: Robey Pointer //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include #include "oldblowfish1.h" #include "oldblowfish2.h" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // blowfish.cpp C++ class implementation of the BLOWFISH encryption algorithm // _THE BLOWFISH ENCRYPTION ALGORITHM_ // by Bruce Schneier // Revised code--3/20/94 // Converted to C++ class 5/96, Jim Conger //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #define S(x,i) (SBoxes[i][x.w.byte##i]) #define bf_F(x) (((S(x,0) + S(x,1)) ^ S(x,2)) + S(x,3)) #define ROUND(a,b,n) (a.dword ^= bf_F(b) ^ PArray[n]) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- oldCBlowFish::oldCBlowFish () { PArray = new DWORD [18] ; SBoxes = new DWORD [4][256] ; } oldCBlowFish::~oldCBlowFish () { delete PArray ; delete [] SBoxes ; } // the low level (private) encryption function void oldCBlowFish::Blowfish_encipher (DWORD *xl, DWORD *xr) { union aword Xl, Xr ; Xl.dword = *xl ; Xr.dword = *xr ; Xl.dword ^= PArray [0]; ROUND (Xr, Xl, 1) ; ROUND (Xl, Xr, 2) ; ROUND (Xr, Xl, 3) ; ROUND (Xl, Xr, 4) ; ROUND (Xr, Xl, 5) ; ROUND (Xl, Xr, 6) ; ROUND (Xr, Xl, 7) ; ROUND (Xl, Xr, 8) ; ROUND (Xr, Xl, 9) ; ROUND (Xl, Xr, 10) ; ROUND (Xr, Xl, 11) ; ROUND (Xl, Xr, 12) ; ROUND (Xr, Xl, 13) ; ROUND (Xl, Xr, 14) ; ROUND (Xr, Xl, 15) ; ROUND (Xl, Xr, 16) ; Xr.dword ^= PArray [17] ; *xr = Xl.dword ; *xl = Xr.dword ; } // the low level (private) decryption function void oldCBlowFish::Blowfish_decipher (DWORD *xl, DWORD *xr) { union aword Xl ; union aword Xr ; Xl.dword = *xl ; Xr.dword = *xr ; Xl.dword ^= PArray [17] ; ROUND (Xr, Xl, 16) ; ROUND (Xl, Xr, 15) ; ROUND (Xr, Xl, 14) ; ROUND (Xl, Xr, 13) ; ROUND (Xr, Xl, 12) ; ROUND (Xl, Xr, 11) ; ROUND (Xr, Xl, 10) ; ROUND (Xl, Xr, 9) ; ROUND (Xr, Xl, 8) ; ROUND (Xl, Xr, 7) ; ROUND (Xr, Xl, 6) ; ROUND (Xl, Xr, 5) ; ROUND (Xr, Xl, 4) ; ROUND (Xl, Xr, 3) ; ROUND (Xr, Xl, 2) ; ROUND (Xl, Xr, 1) ; Xr.dword ^= PArray[0]; *xl = Xr.dword; *xr = Xl.dword; } // constructs the enctryption sieve void oldCBlowFish::Initialize (BYTE key[], int keybytes) { int i, j ; DWORD data, datal, datar ; union aword temp ; // ATTN: new fix for keys > 56, should make it more compatible with FISH // but fish uses 80 ??? if (keybytes>MAXKEYBYTES_COMPATMODE) keybytes=MAXKEYBYTES_COMPATMODE; // first fill arrays from data tables for (i = 0 ; i < 18 ; i++) PArray [i] = bf_P [i] ; for (i = 0 ; i < 4 ; i++) { for (j = 0 ; j < 256 ; j++) SBoxes [i][j] = bf_S [i][j] ; } j = 0 ; for (i = 0 ; i < NPASS + 2 ; ++i) { temp.dword = 0 ; temp.w.byte0 = key[j]; temp.w.byte1 = key[(j+1) % keybytes] ; temp.w.byte2 = key[(j+2) % keybytes] ; temp.w.byte3 = key[(j+3) % keybytes] ; data = temp.dword ; PArray [i] ^= data ; j = (j + 4) % keybytes ; } datal = 0 ; datar = 0 ; for (i = 0 ; i < NPASS + 2 ; i += 2) { Blowfish_encipher (&datal, &datar) ; PArray [i] = datal ; PArray [i + 1] = datar ; } for (i = 0 ; i < 4 ; ++i) { for (j = 0 ; j < 256 ; j += 2) { Blowfish_encipher (&datal, &datar) ; SBoxes [i][j] = datal ; SBoxes [i][j + 1] = datar ; } } } // get output length, which must be even MOD 8 DWORD oldCBlowFish::GetOutputLength (DWORD lInputLong) { DWORD lVal ; lVal = lInputLong % 8 ; // find out if uneven number of bytes at the end if (lVal != 0) return lInputLong + 8 - lVal ; else return lInputLong ; } // Encode pIntput into pOutput. Input length in lSize. Returned value // is length of output which will be even MOD 8 bytes. Input buffer and // output buffer can be the same, but be sure buffer length is even MOD 8. DWORD oldCBlowFish::Encode (BYTE * pInput, BYTE * pOutput, DWORD lSize) { DWORD lCount, lOutSize, lGoodBytes ; BYTE *pi, *po ; int i, j ; int SameDest = (pInput == pOutput ? 1 : 0) ; lOutSize = GetOutputLength (lSize) ; for (lCount = 0 ; lCount < lOutSize ; lCount += 8) { if (SameDest) // if encoded data is being written into input buffer { if (lCount < lSize - 7) // if not dealing with uneven bytes at end { Blowfish_encipher ((DWORD *) pInput, (DWORD *) (pInput + 4)) ; } else // pad end of data with null bytes to complete encryption { po = pInput + lSize ; // point at byte past the end of actual data j = (int) (lOutSize - lSize) ; // number of bytes to set to null for (i = 0 ; i < j ; i++) *po++ = 0 ; Blowfish_encipher ((DWORD *) pInput, (DWORD *) (pInput + 4)) ; } pInput += 8 ; } else // output buffer not equal to input buffer, so must copy { // input to output buffer prior to encrypting if (lCount < lSize - 7) // if not dealing with uneven bytes at end { pi = pInput ; po = pOutput ; for (i = 0 ; i < 8 ; i++) // copy bytes to output *po++ = *pi++ ; Blowfish_encipher ((DWORD *) pOutput, // now encrypt them (DWORD *) (pOutput + 4)) ; } else // pad end of data with null bytes to complete encryption { lGoodBytes = lSize - lCount ; // number of remaining data bytes po = pOutput ; for (i = 0 ; i < (int) lGoodBytes ; i++) *po++ = *pInput++ ; for (j = i ; j < 8 ; j++) *po++ = 0 ; Blowfish_encipher ((DWORD *) pOutput, (DWORD *) (pOutput + 4)) ; } pInput += 8 ; pOutput += 8 ; } } return lOutSize ; } // Decode pIntput into pOutput. Input length in lSize. Input buffer and // output buffer can be the same, but be sure buffer length is even MOD 8. void oldCBlowFish::Decode (BYTE * pInput, BYTE * pOutput, DWORD lSize) { DWORD lCount ; BYTE *pi, *po ; int i ; int SameDest = (pInput == pOutput ? 1 : 0) ; for (lCount = 0 ; lCount < lSize ; lCount += 8) { if (SameDest) // if encoded data is being written into input buffer { Blowfish_decipher ((DWORD *) pInput, (DWORD *) (pInput + 4)) ; pInput += 8 ; } else // output buffer not equal to input buffer { // so copy input to output before decoding pi = pInput ; po = pOutput ; for (i = 0 ; i < 8 ; i++) *po++ = *pi++ ; Blowfish_decipher ((DWORD *) pOutput, (DWORD *) (pOutput + 4)) ; pInput += 8 ; pOutput += 8 ; } } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // The following code is adapted from the eggdrop bot source: // by Robey Pointer // DR - as i understand this, what we have here is a function where you pass // it a string(passphrase), and it convolutes it into an encrypted version // (witout using a separate key). and you use this one-way encrypted // string later, when you ask person for their passphrase. when they give // you there passphrase, you call this again, and compare the two outputs. // if the outputs are the same, then the inputs presumably were, and so // passphrase is judged to match. In this way you can store one-way encrypted // passphrases in plain files. // #define SALT1 0xdeadd061 #define SALT2 0x23f6b095 // Convert 64-bit encrypted passphrase to text for userfile char *base64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; int base64dec(char c) { // updated 1/20/03 for speed improvement static char base64unmap[255]; static bool didinit=false; int i; if (!didinit) { // initialize base64unmap for (i=0;i<255;++i) base64unmap[i]=0; for (i=0;i<64;++i) base64unmap[base64[i]]=i; didinit=true; } return base64unmap[c]; } void blowfish_encrypt_pass(char *text, char *str) { DWORD left,right; int n; char *p; oldCBlowFish caca; caca.Initialize((unsigned char*)text,strlen(text)); left = SALT1; right = SALT2; caca.Blowfish_encipher(&left, &right); p = str; *p++ = '+'; // + means encrypted pass n = 32; while (n > 0) { *p++ = base64[right & 0x3f]; right = (right >> 6); n -= 6; } n = 32; while (n > 0) { *p++ = base64[left & 0x3f]; left = (left >> 6); n -= 6; } *p = 0; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // ORIGINAL COMPATIBLE (ECB) METHODS char *encrypt_string_oldecb(char *key, char *str) { DWORD left, right; unsigned char *p; char *s, *dest, *d; int i; // Pad fake string with 8 bytes to make sure there's enough s = new char[strlen(str) + 9]; strcpy(s, str); if ((!key) || (!key[0])) return s; p = (unsigned char*)s; dest = new char[(strlen(str) + 9) * 2]; while (*p) p++; for (i = 0; i < 8; i++) *p++ = 0; oldCBlowFish caca; caca.Initialize((unsigned char*)key,strlen(key)); p = (unsigned char*)s; d = dest; while (*p) { left = ((*p++) << 24); left += ((*p++) << 16); left += ((*p++) << 8); left += (*p++); right = ((*p++) << 24); right += ((*p++) << 16); right += ((*p++) << 8); right += (*p++); caca.Blowfish_encipher(&left, &right); for (i = 0; i < 6; i++) { *d++ = base64[right & 0x3f]; right = (right >> 6); } for (i = 0; i < 6; i++) { *d++ = base64[left & 0x3f]; left = (left >> 6); } } *d = 0; delete s; return dest; } // Returned string must be freed when done with it! char *decrypt_string_oldecb(char *key, char *str) { DWORD left, right; char *p, *s, *dest, *d; int i; // Pad encoded string with 0 bits in case it's bogus s = new char[strlen(str) + 12]; strcpy(s, str); if ((!key) || (!key[0])) return s; p = s; dest = new char[strlen(str) + 12]; while (*p) p++; for (i = 0; i < 12; i++) *p++ = 0; oldCBlowFish caca; caca.Initialize((unsigned char*)key,strlen(key)); p = s; d = dest; while (*p) { right = 0L; left = 0L; for (i = 0; i < 6; i++) right |= (base64dec(*p++)) << (i * 6); for (i = 0; i < 6; i++) left |= (base64dec(*p++)) << (i * 6); caca.Blowfish_decipher(&left, &right); for (i = 0; i < 4; i++) *d++ = (char) ((left & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8)); for (i = 0; i < 4; i++) *d++ = (char) ((right & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8)); } *d = 0; delete s; return dest; } //---------------------------------------------------------------------------