1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
| // 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
#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 ;
}
}
} |
Partager