00001
00002
00003 #include "pch.h"
00004 #include "blowfish.h"
00005
00006 NAMESPACE_BEGIN(CryptoPP)
00007
00008 Blowfish::Blowfish(const byte *key_string, unsigned int keylength, CipherDir dir)
00009 : pbox(ROUNDS+2), sbox(4*256)
00010 {
00011 assert(keylength == KeyLength(keylength));
00012
00013 unsigned i, j=0, k;
00014 word32 data, dspace[2] = {0, 0};
00015
00016 memcpy(pbox, p_init, sizeof(p_init));
00017 memcpy(sbox, s_init, sizeof(s_init));
00018
00019
00020 for (i=0 ; i<ROUNDS+2 ; ++i)
00021 {
00022 data = 0 ;
00023 for (k=0 ; k<4 ; ++k )
00024 data = (data << 8) | key_string[j++ % keylength];
00025 pbox[i] ^= data;
00026 }
00027
00028 crypt_block(dspace, pbox);
00029
00030 for (i=0; i<ROUNDS; i+=2)
00031 crypt_block(pbox+i, pbox+i+2);
00032
00033 crypt_block(pbox+ROUNDS, sbox);
00034
00035 for (i=0; i<4*256-2; i+=2)
00036 crypt_block(sbox+i, sbox+i+2);
00037
00038 if (dir==DECRYPTION)
00039 for (i=0; i<(ROUNDS+2)/2; i++)
00040 std::swap(pbox[i], pbox[ROUNDS+1-i]);
00041 }
00042
00043
00044 void Blowfish::crypt_block(const word32 in[2], word32 out[2]) const
00045 {
00046 word32 left = in[0];
00047 word32 right = in[1];
00048
00049 const word32 *const s=sbox;
00050 const word32 *p=pbox;
00051
00052 left ^= p[0];
00053
00054 for (unsigned i=0; i<ROUNDS/2; i++)
00055 {
00056 right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)])
00057 ^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)])
00058 ^ p[2*i+1];
00059
00060 left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
00061 ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
00062 ^ p[2*i+2];
00063 }
00064
00065 right ^= p[ROUNDS+1];
00066
00067 out[0] = right;
00068 out[1] = left;
00069 }
00070
00071 void Blowfish::ProcessBlock(const byte *in, byte *out) const
00072 {
00073 word32 left, right;
00074 GetBlockBigEndian(in, left, right);
00075
00076 const word32 *const s=sbox;
00077 const word32 *p=pbox;
00078
00079 left ^= p[0];
00080
00081 for (unsigned i=0; i<ROUNDS/2; i++)
00082 {
00083 right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)])
00084 ^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)])
00085 ^ p[2*i+1];
00086
00087 left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
00088 ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
00089 ^ p[2*i+2];
00090 }
00091
00092 right ^= p[ROUNDS+1];
00093
00094 PutBlockBigEndian(out, right, left);
00095 }
00096
00097 NAMESPACE_END