Я перевожу C ++ TCP-клиент на C #. Клиент используется для кодирования 4 байтов массива с использованием blowfish.
C ++ Blowfish
C # Blowfish (C # NET)
C ++
BYTE response[6] =
{
0x00, 0x80, 0x01, 0x61, 0xF8, 0x17
};
// Encrypt the last 4 bytes of the packet only(0x01,0x061,0xF8,0x17)
blowfish.Encode(responce + 2, responce + 2, 4);
// Send the packet
send(s, (char*)sendPtr, sendSize, 0);
C #
responce = new byte[6] { 0x00, 0x80, 0x01, 0x61, 0xF8, 0x17};
// Encrypt the last 4 bytes of the packet only(0x01,0x061,0xF8,0x17)
Handshake.blowfish.Encrypt(responce, 2, responce, 2, 4);
// Send the packet
WS.sock.Send(encrypted);
В коде C ++ при вызове строки «Blowfish.Encode» с этими параметрами она переходит в функцию cBlowfish.Encrypt
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++;
// now encrypt them
Blowfish_encipher((DWORD *) pOutput, (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;
}
Чтобы было ясно, цикл выполняется только один раз из-за короткой длины пропущенных байтов (4).
Из этого огромного кода выполняется только один вызов (только один раз), вызов:
Blowfish_encipher((DWORD *) pInput, (DWORD *)(pInput + 4));
// означает, что код передает первые два оператора if, а затем покидает цикл и функцию.
С моей точки зрения, решение скрыто где-то внутри функции шифрования:
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;
}
Определения:
#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_Encipher в C ++ имеет два параметра: Input (xl) как dword и Output (xr) как dword.
Функция Clow Blowfish Encrypt_Block имеет четыре параметра, почему?
public void EncryptBlock(uint hi,uint lo,out uint outHi,out uint outLo)
В отличие от C ++ blowfish, EncryptBlock вызывает Encrypt, а не Encrypt для вызова EncryptBlock. Возможно, EncryptBlock НЕ является C ++ Blowfish_Encipher?
В любом случае, моя проблема заключается в том, что когда я вызываю код C ++ с этим массивом из 6 байтов, запрашивая код-раздув только для того, чтобы кодировать только последние 4 байта, он делает это.
Хотя если я вызываю функцию шифрования в C # с этими 4 байтами, она возвращает 0x00 (если вы хотите увидеть Blowfish C #, проверьте мои первые строки - я добавил туда гиперссылку).
Примечание. Я не могу изменить структуру пакета, она должна быть такой, но зашифрованной.
Я тоже пробовал это:
Зная, что функции C ++ Encrpypt выполняют только один вызов - blowfish Encipher. Я пытался вызывать EncryptBlock в C # напрямую, но есть Hi Uint32 и Low Uint32 в качестве входных и выходных, как их распространить в HI или LO? Будет ли это работать, если Encrypt_Block вызывает Blowfish Encrypt в C #? Я совершенно не уверен.
Заранее спасибо!