C #: Blowfish Зашифровать один меч - PullRequest
1 голос
/ 01 апреля 2009

Я перевожу 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 #? Я совершенно не уверен.

Заранее спасибо!

1 Ответ

1 голос
/ 02 апреля 2009

Blowfish работает на восьмибайтовых блоках. Единственный способ зашифровать данные, длина которых не превышает восьми байтов (или кратно восьми), - это заполнить их (в данном случае нулями).

Вам нужно передать восьмибайтовый буфер в вашу функцию C ++, поскольку вы шифруете на месте. Размещенный вами код фактически зашифрует четыре дополнительных байта смежной памяти ((DWORD *)(pInput + 4)), что явно не то, что вам нужно. Кроме того, для расшифровки требуются все восемь выходных байтов, поэтому, к сожалению, вы не можете просто передать четыре зашифрованных байта и ожидать, что они будут успешно расшифрованы на другом конце.

Я знаю, что это не решит вашу проблему - я не вижу способа ее решить, поскольку вы хотите отправить только четыре байта зашифрованных данных, а Blowfish всегда выдает минимум восемь!

...