Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > rc4 шифрование/дешифрование строки


Автор: Kasiro 17.9.2012, 23:38
Доброго времени суток.

Необходимо шифровать/дешифровать строку алгоритмом RC4.
Нашел в инете исходники http://www.codeproject.com/Articles/35374/Two-Efficient-Classes-for-RC4-and-Base64-Stream-Ci (rc4, вывод текста base64)
вроде работают нормально, но есть ошибки, к примеру

clear_temporary_files=0 - 1snHkN01uvr9XqrVDRJTcqBP66YAHHI= (а у меня получается 1snHkN01uvr9XqrVDRJTcqBP66ZzHDE= )

расшифровка в таком случае немного кривая, большая часть фразы расшифровывается корректно, но есть и косяки
в чем дело не могу понять

Проверял корректность шифрования с помощью онлайн сервиса http://isv.appspot.com/app/enc

есть ли у кого нибудь рабочий код шифрования/дешифрования RC4?

PS: пробовал пользоваться DCPCrypt, хорошая библиотека, но вот какой ключ используется в процесси шифровки я так и не понял, библиотека каким то хитрым образом вычисляет реальный ключ на основе того с которого идет инициализация.... если кто нибудь знает как в этот компонент подсунуть свой ключ - я был бы очень благодарен.

Автор: artsb 18.9.2012, 09:00
У меня всё работает.

С сайта http://isv.appspot.com/app/enc
Цитата

Текстовый ключ: 39f85c443c8dd89e
Строка для шифрования: clear_temporary_files=0
Результат в BASE64: H1CqS8ZVZTzM/BuRMSwqCNb40j/0M6k=


У меня
Цитата

1. Использовал класс CRC4 по ссылке http://www.codeproject.com/Articles/35374/Two-Efficient-Classes-for-RC4-and-Base64-Stream-Ci
2. Кодировал в Base64 с помощью EncodeBase64(), которая находится в EncdDecd.hpp

Текстовый ключ: 39f85c443c8dd89e
Строка для шифрования: clear_temporary_files=0
Результат в BASE64: H1CqS8ZVZTzM/BuRMSwqCNb40j/0M6k=

Код

    AnsiString sResult;
    char cBuffer[1024];
    CRC4 crc;

    strcpy(cBuffer, AnsiString(edtText->Text).c_str());

    crc.Encrypt(cBuffer, AnsiString(edtKey->Text).c_str());

    sResult = EncodeBase64(cBuffer, strlen(cBuffer));

    edtOutput->Text = sResult;


ЗЫ извиняюсь за кривой код.

Автор: Kasiro 18.9.2012, 09:40
Да, все верно, пробовал ваш вариант, все получилось как на сайте

затем попробовал ваш код только со своим ключем, и получил проблему которая и была

Текстовый ключ: KfSLOhtP7SPBdvRlNIKu4sR3suLQ6bcd4621d373cade
Строка для шифрования: clear_temporary_files=0
Результат в BASE64 (на сайте): 1snHkN01uvr9XqrVDRJTcqBP66YAHHI=
Результат в BASE64 (в проге):   1snHkN01uvr9XqrVDRJTcqBP66ZzHDA=

есть идеи? мб ключ слишком длинный?





Автор: Kasiro 18.9.2012, 09:55
что интересно, если в этом ключе я удаляю хоть один символ, все начинает работать как надо....

Автор: artsb 18.9.2012, 11:44
Разобрался.
ВОт это закомментируйте:
Код

            if(k == *(pszText + m))      /* avoid '\0' among the
                            encoded text; */
                   k = 0;


Удалите define:
Код

#define swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))

Вместо него используйте функцию:
Код

void inline swap(unsigned char &с1, unsigned char &с2)
{
    unsigned char t = с1;
    с1 = с2;
    с2 = t;
}

Автор: Kasiro 18.9.2012, 12:42
спасибо, сделал все как вы написали, но получил результат вот такой:

Name    Value
D    { "1snHkN01uvr9XqrVDRJTcqBP66Y=" }

закоментировал вот так:

Код

            for (m = 0; m < ilen; m++)
            {
                i = (i + 1) &0xff;
                j = (j + *(sbox + i)) &0xff;
                swap(*(sbox+i),*(sbox + j));  /* randomly Initialize the key sequence */
                k = *(sbox + ((*(sbox + i) + *(sbox + j)) &0xff ));
                //if(k == *(pszText + m))       /* avoid '\0' beween the decoded text; */
                //    k = 0;
                *(pszText + m) ^=  k;
            }
            return pszText;

Автор: artsb 18.9.2012, 13:07
Ах, да. Нужно длину строки заранее запоминать, т.к. теперь в строке могут быть '\0'.
Т.е. как-то так:
Код

    AnsiString sResult;
    char cBuffer[1024];
    int iLen;
    CRC4 crc;

    strcpy(cBuffer, AnsiString(edtText->Text).c_str());
    iLen = strlen(cBuffer); // или edtText->Text.Length()
    crc.Encrypt(cBuffer, AnsiString(edtKey->Text).c_str());
    sResult = EncodeBase64(cBuffer, iLen);
    edtOutput->Text = sResult;

Автор: Kasiro 18.9.2012, 15:16
спасибо огромное)) работает как надо)
а не подскажите как сделать обратный процесс? расшифровку?
потому что тот вариант что наваял я, возвращает мне только кусочек фразы - clear_temporary_file


Код

    AnsiString sResult;
    char cBuffer[2048];
    int iLen;
    CRC4 crc;

    strcpy(cBuffer, MSG.t_str());
    iLen = strlen(cBuffer);

    TByteDynArray IDunit=DecodeBase64(cBuffer);

              sResult.SetLength(IDunit.High+1);
              memcpy(const_cast<void*>(sResult.data()),&IDunit[0],sResult.Length()-1);


    crc.Decrypt(sResult.c_str(), Key.t_str());
    return sResult;

Автор: artsb 18.9.2012, 15:34
Всё тот же злополучный 0. Класс будет выглядеть так:
Код

void inline swap(unsigned char &c1, unsigned char &c2)
{
    unsigned char t = c1;
    c1 = c2;
    c2 = t;
}


class CRC4
{
public:

    CRC4 ()
    {
        memset(sbox,0,sizeof(sbox));
        memset(key,0,sizeof(key));
    }
    virtual ~CRC4 ()
    {
        memset(sbox,0,sizeof(sbox));  /* remove Key traces in memory  */
        memset(key,0,sizeof(key));
    }

    char *Encrypt(char *pszText,const char *pszKey, int iTextLen = 0)
    {
        i=0, j=0,n = 0;
        ilen = (int)strlen(pszKey);

        for (m = 0;  m < 256; m++)  /* Initialize the key sequence */
        {
            *(key + m)= *(pszKey + (m % ilen));
            *(sbox + m) = m;
        }
        for (m=0; m < 256; m++)
        {
            n = (n + *(sbox+m) + *(key + m)) &0xff;
            swap(*(sbox + m),*(sbox + n));
        }

        if(iTextLen > 0)
        {
            ilen = iTextLen;
        }
        else
        {
            ilen = (int)strlen(pszText);
        }

        for (m = 0; m < ilen; m++)
        {
            i = (i + 1) &0xff;
            j = (j + *(sbox + i)) &0xff;
            swap(*(sbox+i),*(sbox + j));  /* randomly Initialize the key sequence */
            k = *(sbox + ((*(sbox + i) + *(sbox + j)) &0xff ));
            *(pszText + m) ^=  k;
        }

        return pszText;
    }

    char *Decrypt(char *pszText, const char *pszKey, int iTextLen)
    {
        if(iTextLen < 1)
        {
            return NULL;
        }

        return Encrypt(pszText, pszKey, iTextLen) ;  /* using the same function as encoding */
    }

private:
    unsigned char sbox[256];      /* Encryption array             */
    unsigned char key[256],k;     /* Numeric key values           */
    int  m, n, i, j, ilen;        /* Ambiguously named counters   */
};


Добавлено через 2 минуты и 11 секунд
Код

    TByteDynArray arr;
    char cBuffer[1024];
    CRC4 crc;

    arr = DecodeBase64(AnsiString(edtOutput->Text));

    memset(cBuffer, 0, sizeof(cBuffer));
    memcpy(cBuffer, &(arr[0]), arr.Length);

    crc.Decrypt(cBuffer, AnsiString(edtKey->Text).c_str(), arr.Length);

    edtResult->Text = cBuffer;

Автор: Kasiro 18.9.2012, 16:00
спасибо большое) все отлично работает smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)