www.pudn.com > abot.rar > blowfish.cpp, change:2007-05-15,size:10239b


// 
// Blowfish - Blowfish encryption for mIRC 
// Copyright (C) 2001 Gustavo Picon 
// 
// This program 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 
// Blowfish Eggdrop algorythms:  Robey Pointer 
 
#define WIN32_LEAN_AND_MEAN 
#include <windows.h> 
#pragma warning(disable:4244) 
 
#define MAXSTRINGLEN 900 
 
#include "blowfish.h" 
#include "blowfish.h2"	// holds the random digit tables 
 
#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]) 
 
CBlowFish::CBlowFish () 
{ 
 	PArray = new DWORD [18] ; 
 	SBoxes = new DWORD [4][256] ; 
} 
 
CBlowFish::~CBlowFish () 
{ 
	delete PArray ; 
	delete [] SBoxes ; 
} 
 
	// the low level (private) encryption function 
void CBlowFish::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 CBlowFish::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 CBlowFish::Initialize (BYTE key[], int keybytes) 
{ 
	int  		i, j ; 
	DWORD  		data, datal, datar ; 
	union aword temp ; 
 
	// 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 CBlowFish::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 CBlowFish::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 CBlowFish::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 
 
#define SALT1  0xdeadd061 
#define SALT2  0x23f6b095 
 
// Convert 64-bit encrypted password to text for userfile 
char *base64 = ".!0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
 
int base64dec(char c) 
{ 
	int i; 
	for (i = 0; i < 64; i++) 
		if (base64[i] == c) 
			return i; 
	return 0; 
} 
 
void blowfish_encrypt_pass(char *text, char *str) 
{ 
	DWORD left,right; 
	int n; 
	char *p; 
	CBlowFish caca; 
	caca.Initialize((unsigned char*)text,lstrlen(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; 
} 
// Returned string must be freed when done with it! 
char *encrypt_string(const char *key, const 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[lstrlen(str) + 9]; 
	lstrcpy(s, str); 
	if ((!key) || (!key[0])) 
		return s; 
	p = (unsigned char*)s; 
	dest = new char[(lstrlen(str) + 9) * 2]; 
	while (*p) 
		p++; 
	for (i = 0; i < 8; i++) 
		*p++ = 0; 
	CBlowFish caca; 
	caca.Initialize((unsigned char*)key,lstrlen(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! 
static char *decrypt_string(const char *key, const 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[lstrlen(str) + 12]; 
	lstrcpy(s, str); 
	if ((!key) || (!key[0])) 
		return s; 
	p = s; 
	dest = new char[lstrlen(str) + 12]; 
	while (*p) 
		p++; 
	for (i = 0; i < 12; i++) 
		*p++ = 0; 
	CBlowFish caca; 
	caca.Initialize((unsigned char*)key,lstrlen(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++ = (left & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8); 
		for (i = 0; i < 4; i++) 
			*d++ = (right & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8); 
	} 
	*d = 0; 
	delete s; 
	return dest; 
} 
 
void bfEncrypt (const char *key, const char *str, char *out) 
{ 
	memset(out, 0, sizeof(out)); 
	strcpy(out, encrypt_string(key,str)); 
} 
 
void bfDecrypt (const char *key, const char *str, char *out) 
{ 
	memset(out, 0, sizeof(out)); 
	strcpy(out, decrypt_string(key,str)); 
}