2017-08-08 13:53:47 +02:00
|
|
|
// 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
|
|
|
|
|
2017-08-09 23:49:00 +01:00
|
|
|
#include <cstdint>
|
2017-08-08 13:53:47 +02:00
|
|
|
#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])
|
|
|
|
|
|
|
|
|
|
|
|
BlowFish::BlowFish ()
|
|
|
|
{
|
|
|
|
PArray = new DWORD [18] ;
|
|
|
|
SBoxes = new DWORD [4][256] ;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlowFish::~BlowFish ()
|
|
|
|
{
|
|
|
|
delete PArray ;
|
|
|
|
delete [] SBoxes ;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the low level (private) encryption function
|
|
|
|
void BlowFish::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 BlowFish::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
|
2017-08-11 22:56:30 +01:00
|
|
|
void BlowFish::initialize (BYTE key[], int32_t keybytes)
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
int i, j ;
|
|
|
|
DWORD datal, datar ;
|
|
|
|
|
|
|
|
|
|
|
|
// 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] ;
|
|
|
|
}
|
|
|
|
|
2017-08-11 22:56:30 +01:00
|
|
|
int32_t v12; // eax@6
|
|
|
|
int32_t v13; // ecx@6
|
|
|
|
int32_t v14; // eax@8
|
|
|
|
int32_t v15; // edx@8
|
|
|
|
int32_t v16; // edx@8
|
|
|
|
int32_t v17; // eax@10
|
|
|
|
int32_t v18; // ecx@10
|
|
|
|
int32_t v19; // ecx@10
|
|
|
|
int32_t v20; // edx@12
|
|
|
|
int32_t v21; // edx@12
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-11 22:56:30 +01:00
|
|
|
int32_t v10 = keybytes;
|
2017-08-18 21:14:09 +09:00
|
|
|
uintptr_t v9 = (uintptr_t)key;
|
2017-08-11 22:56:30 +01:00
|
|
|
int32_t v8 = 0;
|
|
|
|
int32_t v11 = 0;
|
2017-08-08 13:53:47 +02:00
|
|
|
do {
|
|
|
|
v13 = (char)(*(BYTE *)(v8 + v9));
|
|
|
|
v12 = v8 + 1;
|
|
|
|
if ( v12 >= v10 )
|
|
|
|
v12 = 0;
|
|
|
|
v16 = (char)*(BYTE *)(v12 + v9);
|
|
|
|
v14 = v12 + 1;
|
|
|
|
v15 = (v13 << 8) | v16;
|
|
|
|
if ( v14 >= v10 )
|
|
|
|
v14 = 0;
|
|
|
|
v19 = (char)*(BYTE *)(v14 + v9);
|
|
|
|
v17 = v14 + 1;
|
|
|
|
v18 = (v15 << 8) | v19;
|
|
|
|
if ( v17 >= v10 )
|
|
|
|
v17 = 0;
|
|
|
|
v21 = (char)*(BYTE *)(v17 + v9);
|
|
|
|
v8 = v17 + 1;
|
|
|
|
v20 = (v18 << 8) | v21;
|
|
|
|
if ( v8 >= v10 )
|
|
|
|
v8 = 0;
|
|
|
|
*((DWORD *)PArray + v11++) ^= v20;
|
|
|
|
} while ( v11 < 18 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 BlowFish::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 BlowFish::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 BlowFish::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 ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|