Tôi đang dịch ứng dụng khách C++ TCP sang C#. Ứng dụng khách này được sử dụng để mã hóa 4 byte của một mảng bằng cách sử dụng Blowfish.
Cá nóc C++
C# Blowfish (C# NET)
C++
Phản hồi BYTE [6] =
{
0x00, 0x80, 0x01, 0x61, 0xF8, 0x17
};
// Chỉ mã hóa 4 byte cuối cùng của gói (0x01,0x061,0xF8,0x17)
Blowfish.Encode(phản hồi + 2, phản hồi + 2, 4);
// Gửi gói tin
gửi(s, (char*)sendPtr, sendSize, 0);
C#
phản hồi = byte mới [6] { 0x00, 0x80, 0x01, 0x61, 0xF8, 0x17};
// Chỉ mã hóa 4 byte cuối cùng của gói (0x01,0x061,0xF8,0x17)
Handshake.blowfish.Encrypt(phản hồi, 2, phản hồi, 2, 4);
// Gửi gói tin
WS.sock.Send(được mã hóa);
Trong mã C++, khi dòng "Blowfish.Encode" được gọi với các tham số này, nó sẽ nhập hàm cBlowfish.Encrypt
DWORD cBlowFish::Encode(BYTE * pInput, BYTE * pOutput, DWORD lSize)
{
DWORD lCount, lOutSize, lGoodBytes;
BYTE *pi, *po;
int tôi, j;
int SameDest =(pInput == pOutput ? 1 : 0);
lOutSize = GetOutputLength(lSize);
for(lCount = 0; lCount < lOutSize; lCount += 8)
{
if(SameDest) // nếu dữ liệu được mã hóa đang được ghi vào bộ đệm đầu vào
{
if(lCount < lSize - 7) // nếu không xử lý các byte không đồng đều ở cuối
{
Blowfish_encipher((DWORD *) pInput, (DWORD *)(pInput + 4));
}
else // đệm cuối dữ liệu bằng byte rỗng để hoàn tất mã hóa
{
po = pInput + lSize // trỏ vào byte sau cuối dữ liệu thực tế
j =(int)(lOutSize - lSize); // số byte được đặt thành null
for(i = 0; i < j; i++)
*po++ = 0;
Blowfish_encipher((DWORD *) pInput, (DWORD *)(pInput + 4));
}
pĐầu vào += 8;
}
else // bộ đệm đầu ra không bằng bộ đệm đầu vào nên phải sao chép
{ // đầu vào vào bộ đệm đầu ra trước khi mã hóa
if(lCount < lSize - 7) // nếu không xử lý các byte không đồng đều ở cuối
{
pi = pĐầu vào;
po = pĐầu ra;
cho(i = 0; i < 8; i++)
// sao chép byte vào đầu ra
*po++ = *pi++;
// bây giờ mã hóa chúng
Blowfish_encipher((DWORD *) pOutput, (DWORD *)(pOutput + 4));
}
else // đệm cuối dữ liệu bằng byte rỗng để hoàn tất mã hóa
{
lGoodBytes = lSize - lCount; // số byte dữ liệu còn lại
po = pĐầu ra;
for(i = 0; i <(int) lGoodBytes; i++)
*po++ = *pInput++;
for(j = i; j < 8; j++)
*po++ = 0;
Blowfish_encipher((DWORD *) pOutput, (DWORD *)(pOutput + 4));
}
pĐầu vào += 8;
pĐầu ra += 8;
}
}
trả về lOutSize;
}
Để rõ ràng, vòng lặp chỉ được thực hiện một lần vì độ dài của byte được truyền ngắn hơn (4).
Chỉ có một cuộc gọi được thực hiện (chỉ một lần) từ mã khổng lồ này và cuộc gọi là:
Blowfish_encipher((DWORD *) pInput, (DWORD *)(pInput + 4));
// Chỉ ra rằng mã vượt qua hai câu lệnh if đầu tiên rồi rời khỏi vòng lặp và hàm.
Theo quan điểm của tôi, giải pháp được ẩn giấu ở đâu đó trong chức năng mã hóa:
void cBlowFish::Blowfish_encipher(DWORD *xl, DWORD *xr)
{
công đoàn từ Xl, Xr;
Xl.dword = *xl;
Xr.dword = *xr;
Xl.dword ^= PArray [0];
VÒNG(Xr, Xl, 1);
VÒNG(Xl, Xr, 2);
VÒNG(Xr, Xl, 3);
VÒNG(Xl, Xr, 4);
VÒNG(Xr, Xl, 5);
VÒNG(Xl, Xr, 6);
VÒNG(Xr, Xl, 7);
VÒNG(Xl, Xr, 8);
VÒNG(Xr, Xl, 9);
VÒNG(Xl, Xr, 10);
VÒNG(Xr, Xl, 11);
VÒNG(Xl, Xr, 12);
VÒNG(Xr, Xl, 13);
VÒNG(Xl, Xr, 14);
VÒNG(Xr, Xl, 15);
VÒNG(Xl, Xr, 16);
Xr.dword ^= PArray [17];
*xr = Xl.dword;
*xl = Xr.dword;
}
定义:
#define S(x,i) (SBoxes[i][xwbyte##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])
Vấn đề là hàm Blowfish_Encipher trong C++ có hai tham số: Đầu vào(xl) dưới dạng dword và Đầu ra(xr) dưới dạng dword.
Hàm Blowfish Encrypt_Block trong C# có bốn tham số.
public void EncryptBlock(uint hi,uint lo,out uint outHi,out uint outLo)
Không giống như cá kiếm C++, EncryptBlock gọi Encrypt thay vì Encrypt gọi EncryptBlock. Có lẽ EncryptBlock không phải là C++ Blowfish_Encipher?
Dù sao, vấn đề của tôi là khi tôi gọi mã C++ của mình bằng một mảng 6 byte, tôi yêu cầu Blowfish chỉ mã hóa 4 byte cuối cùng, đúng như vậy.
Mặc dù nếu tôi gọi hàm mã hóa trong C# bằng 4 byte này, nó sẽ trả về 0x00. (Nếu bạn muốn xem C# Blowfish, hãy xem dòng đầu tiên của tôi - tôi đã thêm siêu liên kết vào đó).
Lưu ý rằng tôi không thể thay đổi cấu trúc gói tin, lẽ ra nó phải như vậy nhưng được mã hóa.
Tôi cũng đã thử điều này:
Biết rằng hàm Encrpypt của C++ chỉ thực hiện một lệnh gọi - Blowfish Encipher. Tôi đã thử gọi trực tiếp EncryptBlock bằng C# nhưng đầu vào và đầu ra có Hi Uint32 và Low Uint32, làm cách nào tôi có thể phân tán chúng thành HI hoặc LO? Điều này có hoạt động không nếu Encrypt_Block gọi Blowfish Encrypt trong C#? Tôi không chắc.
Cảm ơn trước!
Tôi là một lập trình viên xuất sắc, rất giỏi!