📄 blowfish.cpp
字号:
x <<= 8;
x |= *(p++);
iCount++;
if(iCount == m_keylength)
{
//All bytes used, so recycle bytes
iCount = 0;
p = reinterpret_cast<unsigned char*>(&key[0]);
}
}
m_auiP[i] ^= x;
}
//Reflect P and S boxes through the evolving Blowfish
SBlock block(0UL,0UL); //all-zero block
for(i=0; i<18; )
Encrypt(block), m_auiP[i++] = block.m_uil, m_auiP[i++] = block.m_uir;
for(j=0; j<4; j++)
for(int k=0; k<256; )
Encrypt(block), m_auiS[j][k++] = block.m_uil, m_auiS[j][k++] = block.m_uir;
//Initialization Flag
m_bInit = true;
}
//Resetting the Initialization Vector
void CBlowFish::ResetChain()
{
if(false==m_bInit)
throw runtime_error(string(sm_szErrorMsg1));
m_oChain = m_oChain0;
}
//Compute Signature
void CBlowFish::Signature(char* pcSig)
{
//8+56+1+1+1
char acSigData[68] = {0};
strcat(acSigData, "BLOWFISH");
int iLen = strlen(acSigData);
memcpy(acSigData+iLen, m_apKey.get(), m_keylength);
sprintf(acSigData+iLen+m_keylength, "%d%d", m_iMode, m_iPadding);
CSHA oSHA;
oSHA.AddData(acSigData, strlen(acSigData));
oSHA.FinalDigest(pcSig);
}
//Sixteen Round Encipher of Block
void CBlowFish::Encrypt(SBlock& block)
{
unsigned int uiLeft = block.m_uil;
unsigned int uiRight = block.m_uir;
uiLeft ^= m_auiP[0];
uiRight ^= F(uiLeft)^m_auiP[1]; uiLeft ^= F(uiRight)^m_auiP[2];
uiRight ^= F(uiLeft)^m_auiP[3]; uiLeft ^= F(uiRight)^m_auiP[4];
uiRight ^= F(uiLeft)^m_auiP[5]; uiLeft ^= F(uiRight)^m_auiP[6];
uiRight ^= F(uiLeft)^m_auiP[7]; uiLeft ^= F(uiRight)^m_auiP[8];
uiRight ^= F(uiLeft)^m_auiP[9]; uiLeft ^= F(uiRight)^m_auiP[10];
uiRight ^= F(uiLeft)^m_auiP[11]; uiLeft ^= F(uiRight)^m_auiP[12];
uiRight ^= F(uiLeft)^m_auiP[13]; uiLeft ^= F(uiRight)^m_auiP[14];
uiRight ^= F(uiLeft)^m_auiP[15]; uiLeft ^= F(uiRight)^m_auiP[16];
uiRight ^= m_auiP[17];
block.m_uil = uiRight;
block.m_uir = uiLeft;
}
//Sixteen Round Decipher of SBlock
void CBlowFish::Decrypt(SBlock& block)
{
unsigned int uiLeft = block.m_uil;
unsigned int uiRight = block.m_uir;
uiLeft ^= m_auiP[17];
uiRight ^= F(uiLeft)^m_auiP[16]; uiLeft ^= F(uiRight)^m_auiP[15];
uiRight ^= F(uiLeft)^m_auiP[14]; uiLeft ^= F(uiRight)^m_auiP[13];
uiRight ^= F(uiLeft)^m_auiP[12]; uiLeft ^= F(uiRight)^m_auiP[11];
uiRight ^= F(uiLeft)^m_auiP[10]; uiLeft ^= F(uiRight)^m_auiP[9];
uiRight ^= F(uiLeft)^m_auiP[8]; uiLeft ^= F(uiRight)^m_auiP[7];
uiRight ^= F(uiLeft)^m_auiP[6]; uiLeft ^= F(uiRight)^m_auiP[5];
uiRight ^= F(uiLeft)^m_auiP[4]; uiLeft ^= F(uiRight)^m_auiP[3];
uiRight ^= F(uiLeft)^m_auiP[2]; uiLeft ^= F(uiRight)^m_auiP[1];
uiRight ^= m_auiP[0];
block.m_uil = uiRight;
block.m_uir = uiLeft;
}
//Semi-Portable Byte Shuffling
inline void BytesToBlock(unsigned char const* p, SBlock& b)
{
unsigned int y;
//Left
b.m_uil = 0;
y = *p++;
y <<= 24;
b.m_uil |= y;
y = *p++;
y <<= 16;
b.m_uil |= y;
y = *p++;
y <<= 8;
b.m_uil |= y;
y = *p++;
b.m_uil |= y;
//Right
b.m_uir = 0;
y = *p++;
y <<= 24;
b.m_uir |= y;
y = *p++;
y <<= 16;
b.m_uir |= y;
y = *p++;
y <<= 8;
b.m_uir |= y;
y = *p++;
b.m_uir |= y;
}
inline void BlockToBytes(SBlock const& b, unsigned char* p)
{
unsigned int y;
//Right
y = b.m_uir;
*--p = Byte(y);
y = b.m_uir >> 8;
*--p = Byte(y);
y = b.m_uir >> 16;
*--p = Byte(y);
y = b.m_uir >> 24;
*--p = Byte(y);
//Left
y = b.m_uil;
*--p = Byte(y);
y = b.m_uil >> 8;
*--p = Byte(y);
y = b.m_uil >> 16;
*--p = Byte(y);
y = b.m_uil >> 24;
*--p = Byte(y);
}
//Encryption for a string of chars
void CBlowFish::Encrypt(char const* in, char* out, size_t n)
{
if(false==m_bInit)
throw runtime_error(string(sm_szErrorMsg1));
//n should be > 0 and multiple of m_blockSize
if(n<1 || n%m_blockSize!=0)
throw runtime_error(string(sm_szErrorMsg6));
SBlock work;
if(CBC == m_iMode) //CBC mode, using the Chain
{
SBlock chain(m_oChain);
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(reinterpret_cast<unsigned char const*>(in), work);
work ^= chain;
Encrypt(work);
chain = work;
BlockToBytes(work, reinterpret_cast<unsigned char*>(out+=8));
}
}
else if(CFB == m_iMode) //CFB mode, using the Chain
{
SBlock chain(m_oChain);
for(; n >= 8; n -= 8, in += 8)
{
Encrypt(chain);
BytesToBlock(reinterpret_cast<unsigned char const*>(in), work);
work ^= chain;
chain = work;
BlockToBytes(work, reinterpret_cast<unsigned char*>(out+=8));
}
}
else //ECB mode, not using the Chain
{
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(reinterpret_cast<unsigned char const*>(in), work);
Encrypt(work);
BlockToBytes(work, reinterpret_cast<unsigned char*>(out+=8));
}
}
}
//Decryption for a string of chars
void CBlowFish::Decrypt(char const* in, char* out, size_t n)
{
if(false==m_bInit)
throw runtime_error(string(sm_szErrorMsg1));
//n should be > 0 and multiple of m_blockSize
if(n<1 || n%m_blockSize!=0)
throw runtime_error(string(sm_szErrorMsg6));
SBlock work;
if(CBC == m_iMode) //CBC mode, using the Chain
{
SBlock crypt, chain(m_oChain);
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(reinterpret_cast<unsigned char const*>(in), work);
crypt = work;
Decrypt(work);
work ^= chain;
chain = crypt;
BlockToBytes(work, reinterpret_cast<unsigned char*>(out+=8));
}
}
else if(CFB == m_iMode) //CFB mode, using the Chain, not using Decrypt()
{
SBlock crypt, chain(m_oChain);
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(reinterpret_cast<unsigned char const*>(in), work);
Encrypt(chain);
crypt = work;
work ^= chain;
chain = crypt;
BlockToBytes(work, reinterpret_cast<unsigned char*>(out+=8));
}
}
else //ECB mode, not using the Chain
{
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(reinterpret_cast<unsigned char const*>(in), work);
Decrypt(work);
BlockToBytes(work, reinterpret_cast<unsigned char*>(out+=8));
}
}
}
void CBlowFish::EncryptFile(string const& rostrFileIn, string const& rostrFileOut)
{
if(false==m_bInit)
throw runtime_error(string(sm_szErrorMsg1));
//Check if the same file for input and output
if(rostrFileIn == rostrFileOut)
{
ostrstream ostr;
ostr << sm_szErrorMsg8 << rostrFileIn << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Open Input File
ifstream in(rostrFileIn.c_str(), ios::binary);
if(!in)
{
ostrstream ostr;
ostr << sm_szErrorMsg7 << rostrFileIn << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Open Output File
ofstream out(rostrFileOut.c_str(), ios::binary);
if(!out)
{
ostrstream ostr;
ostr << sm_szErrorMsg7 << rostrFileOut << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Computing the signature
char acSig[33] = {0};
Signature(acSig);
//Writing the Signature
out.write(acSig, 32);
//Resetting the chain
ResetChain();
//Reading from file
char szLargeBuff[BUFF_LEN+1] = {0};
char szBuffIn[DATA_LEN+1] = {0};
char szBuffOut[DATA_LEN+1] = {0};
CDoubleBuffering oDoubleBuffering(in, szLargeBuff, BUFF_LEN, DATA_LEN);
int iRead;
while((iRead=oDoubleBuffering.GetData(szBuffIn)) > 0)
{
if(iRead < DATA_LEN)
iRead = Pad(szBuffIn, iRead);
//Encrypting
Encrypt(szBuffIn, szBuffOut, iRead);
out.write(szBuffOut, iRead);
}
in.close();
out.close();
}
void CBlowFish::DecryptFile(string const& rostrFileIn, string const& rostrFileOut)
{
if(false==m_bInit)
throw runtime_error(string(sm_szErrorMsg1));
//Check if the same file for input and output
if(rostrFileIn == rostrFileOut)
{
ostrstream ostr;
ostr << sm_szErrorMsg8 << rostrFileIn << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Open Input File
ifstream in(rostrFileIn.c_str(), ios::binary);
if(!in)
{
ostrstream ostr;
ostr << sm_szErrorMsg7 << rostrFileIn << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Open Output File
ofstream out(rostrFileOut.c_str(), ios::binary);
if(!out)
{
ostrstream ostr;
ostr << sm_szErrorMsg7 << rostrFileOut << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Computing the signature
char acSig[33] = {0};
Signature(acSig);
char acSig1[33] = {0};
//Reading the Signature
in.read(acSig1, 32);
//Compare the signatures
if(memcmp(acSig1, acSig, 32) != 0)
{
ostrstream ostr;
ostr << sm_szErrorMsg9 << rostrFileIn << sm_szErrorMsg10 << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Resetting the chain
ResetChain();
//Reading from file
char szLargeBuff[BUFF_LEN+1] = {0};
char szBuffIn[DATA_LEN+1] = {0};
char szBuffOut[DATA_LEN+1] = {0};
CDoubleBuffering oDoubleBuffering(in, szLargeBuff, BUFF_LEN, DATA_LEN);
int iRead;
while((iRead=oDoubleBuffering.GetData(szBuffIn)) > 0)
{
//Encrypting
Decrypt(szBuffIn, szBuffOut, iRead);
out.write(szBuffOut, iRead);
}
in.close();
out.close();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -