Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > RC4-реализация на C++ Builder


Автор: Atanvarno 8.6.2009, 16:43
Реализация алгоритма взята отсюда: http://en.wikipedia.org/wiki/Rc4

Код

unsigned char S[256];
unsigned int i, j;


//Инициализация
void rc4_init(unsigned char *key, unsigned int key_length) {
    for (i = 0; i < 255; i++)
        S[i] = i;

    for (i = j = 0; i < 255; i++) {
         unsigned char temp;

        j = (j + key[i % key_length] + S[i]) % 255;
        temp = S[i];
        S[i] = S[j];
        S[j] = temp;
    }

    i = j = 0;
}
//Генерация ключевого потока
/* PRGA */
 unsigned char rc4_output() {
     unsigned char temp;

    i = (i + 1) % 255;
    j = (j + S[i]) % 255;

    temp = S[j];
    S[j] = S[i];
    S[i] = temp;

    return S[(temp + S[j]) % 255];
}

//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
TFileStream *stream, *outstream;//Потоки для чтения и записи
unsigned char *c; //блок для чтения
unsigned char *key; //ключ
int size;
AnsiString str;
c= new unsigned char [256];
for (int y = 0; y < strlen((unsigned unsigned char*)c); y++)
        c[y]=0;

if(OpenDialog1->Execute())
        {Memo1->Lines->LoadFromFile(OpenDialog1->FileName);
        stream = new TFileStream(OpenDialog1->FileName,fmOpenRead|fmShareDenyWrite);}

if(OpenDialog2->Execute())
        outstream=new TFileStream(OpenDialog2->FileName,fmCreate|fmOpenWrite);
key=Edit1->Text.c_str();
rc4_init(key, strlen((unsigned char*)key));


//узнаём размер файла, читаем 256 символов, шифруем, если количество оставшихся символов <256, читаем оставшиеся символы. Шифруем и записываем в файл для сохранения[quote]

[/quote]

size=stream->Size;
while(size>=0)
             {
        if (size<256)
        {stream->Read(c,size);
        for (int y = 0; y < strlen((unsigned char*)c); y++)
            {c[y]=c[y]^ rc4_output();
            if (c[y]==NULL) break;
            }
        outstream->Write(c,size);
        }
         else{   
        stream->Read(c,256);
        for (int y = 0; y < strlen((unsigned unsigned char*)c); y++)
            {c[y]=c[y]^ rc4_output();
            if (c[y]==NULL) break;}
        outstream->Write(c,256);  //}
        for (int y = 0; y < strlen((unsigned unsigned char*)c); y++)
          c[i]=0;

        size=size-256;
        }

delete stream;
delete outstream;
Memo1->Lines->LoadFromFile(OpenDialog2->FileName);


}


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

Вот исходник: http://dump.ru/file/2865530

У меня возникает стойкое ощущение, что я не вижу какой-то элементарной ошибки.
Буду благодарен, если кто-нибудь подскажет.

Автор: xvr 8.6.2009, 17:00
Во первых (если мне не изменяет мой склероз), все числа 255 в RC4 надо заменить на 256
Во вторых - вот эти строки if (c[y]==NULL) break; у вас прекращают шифрование, если в потоке получится нулевой символ (а он получится, т.к. после шифрования поток уже не текстовый а бинарный, и в нем имеет право появится ЛЮБОЙ символ)

Автор: Atanvarno 8.6.2009, 17:19
Да, про NULL я понял, спасибо.
Насчёт 256 - дело явно не в этом, программа вообще перестала работать.

Автор: xvr 8.6.2009, 17:30
255/256 будет влиять на криптографические качества генерируемой последовательности (RC4). Работать оно будет в любом случае и на глаз отличия не заметишь. Отличия будут, если применить криптоанализ к результату, скорее всего устойчивость к взлому снизится (да и RC4 это уже называть нельзя будет smile )

Автор: Atanvarno 8.6.2009, 17:53
Так дело в том, что она не работает ни в первом, ни во втором варианте.  smile  smile 

Автор: xvr 8.6.2009, 19:04
В смысле 'не работает'? Перестает шифровать в середине блока? Это из за  if (c[y]==NULL) break;
А так же из за y < strlen((unsigned unsigned char*)c) в условии for
И вообще - пользоваться строковыми функциями для обработки бинарных данных - явно не самая удачная идея  smile 
Если вам нужно перекодировать файл, так и пишите:
Код

char b;
while(stream->Read(&b,1))
{
 b^=rc4_output();
 outstream->Write(&b,1);
}
Кстати, это - Memo1->Lines->LoadFromFile(OpenDialog2->FileName); тоже не привествуется - в выходном файле будет бинарные данные, в Memo получите абракадабру  smile 

Автор: Atanvarno 8.6.2009, 19:28
xvr,Спасибо Вам большое!
Таперича всё работает аки часы.

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