You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
konversation/konversation/src/blowfish/oldblowfish.cpp

426 lines
11 KiB

/*
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.
*/
/*
Blowfish algorythms: Bruce Schneier and Jim Conger
Bruce Schneier, 1996, Applied Cryptography, 2nd ed., John Wiley & Sons
Blowfish Eggdrop algorythms: Robey Pointer
Copyright (C) 1994 Bruce Schneier <schneier@counterpane.com>
Copyright (C) 1996 Jim Conger <jconger@cox.net>
Copyright (C) Robey Pointer <robey@lag.net>
*/
//---------------------------------------------------------------------------
#include <string.h>
#include "oldblowfish1.h"
#include "oldblowfish2.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#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[(int)base64[i]]=i;
didinit=true;
}
return base64unmap[(int)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;
}
//---------------------------------------------------------------------------