RC4 Crypt/Decrypt [Модификация]

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 25 Oct 2010.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Может кому и пригодиться, а может и нет. Писал один софт и очень потребовалось реализовать какое-нить простенькое шифрование. В голову сразу пришло RC4. Конечно не сказал бы я что оно стойкое, но для много софта сгодиться. В частности:
    1) Это поточный шифр по этому можно легко шифровать потоковые данные.
    2) довольно быстрая работа и легкая реализация
    3) дает более менее нормальное сокрытие инфы, к тому же ключи от 8 до 2048 бит.
    4) в моей модификации функция шифрования является функцией расшифрования.
    5) малый размер
    За основу шифрования был взят алгоритм генерации ключевых данных из RC4, а сама операция шифрования - банальный XOR

    1) Код на Си
    Code:
    #include <windows.h>
    
    void RC4_Init(BYTE* buf, BYTE* key, int key_len)
    {
    	BYTE temp;
    	int x;
    	int y;
     
    	for (x = 0; x < 256; x++)
    	{
    		buf[x] = x;
    	}
     
    	for (x = y = 0; x < 256; x++)
    	{
    		y = (y + key[x % key_len] + buf[x]) & 255;
    	        temp = buf[x];
            	buf[x] = buf[y];
    	        buf[y] = temp;
    	}
    }
    
     
    BYTE RC4_GetByte(BYTE* buf, int* x, int* y)
    {
        BYTE temp;
     
        *x = (*x + 1) & 255;
        *y = (*y + buf[*x]) & 255;
     
        temp = buf[*y];
        buf[*y] = buf[*x];
        buf[*x] = temp;
     
        return buf[(temp + buf[*y]) & 255];
    }
    
    
    void RC4_Crypt(char* input, int len, BYTE* key, int key_len)
    {
    	BYTE key_buf[256];
    	int rc4_x = 0;
    	int rc4_y = 0;
    	int x;
    	int y;
    	
    	RC4_Init(key_buf, key, key_len);
    	
    	for (y = 0; y < 10; y++)
    	{
    		for (x = 0; x < len; x++)
    		{
    			input[x] ^=  RC4_GetByte(key_buf, &rc4_x, &rc4_y);
    		}
    	}
    }
    
    Использование
    RC4_Crypt(буфер_для_шифровани, длинна_данных, ключ_шифрования, длинна_ключа);

    Код на php
    PHP:

    class Rc4Code
    {
        var 
    $key_buf;
        var 
    $rc4_x;
        var 
    $rc4_y;
        var 
    $key_len;
        
        function 
    Rc4InitKey($key)
        {
            
    $key_len strlen($key);
            for (
    $x 0$x 256$x++)
            {
                
    $this->key_buf[$x] = $x;
            }
     
            for (
    $x $y 0$x 256$x++)
            {
                
    $y = ($y ord($key[$x $key_len]) + $this->key_buf[$x]) & 255;
                
    $temp $this->key_buf[$x];
                
    $this->key_buf[$x] = $this->key_buf[$y];
                
    $this->key_buf[$y] = $temp;
            }
        }
        
        
        function 
    Rc4Code($key)
        {
            
    $this->Rc4InitKey($key);
            
            
    $this->rc4_x 0;
            
    $this->rc4_y 0;
            
    $this->key_len $key_len;
        }
        
        function 
    Rc4GetByte()
        {
            
    $this->rc4_x = ($this->rc4_x 1) & 255;
            
    $this->rc4_y = ($this->rc4_y $this->key_buf[$this->rc4_x]) & 255;
     
            
    $temp $this->key_buf[$this->rc4_y];
            
    $this->key_buf[$this->rc4_y] = $this->key_buf[$this->rc4_x];
            
    $this->key_buf[$this->rc4_x] = $temp;
     
            return 
    $this->key_buf[($temp $this->key_buf[$this->rc4_y]) & 255];
        }

        function 
    RC4Crypt($input)
        {
            
    $len strlen($input);
            for (
    $y 0$y 10$y++)
            {
                for (
    $x 0$x $len$x++)
                {
                    
    $input[$x] = chr(ord($input[$x]) ^ $this->Rc4GetByte()); 
                }
            }
            
            return 
    $input;
        }
    }

    Использование:
    $rc4 = new Rc4Code(ключ_шифрования);
    $out = $rc4->RC4Crypt(данные_для_шифрования);

    Код на Делфи
    Code:
    
    procedure RC4_Init(var buf : array of byte; key : string; key_len : integer);
    var
      temp : byte;
      x, y : integer;
    begin
      for x := 0 to 255 do buf[x] := x;
      y := 0;
    
      for x := 0 to 255 do
      begin
        y := (y + ord(key[(x mod key_len) + 1]) + buf[x]) and 255;
        temp := buf[x];
        buf[x] := buf[y];
        buf[y] := temp;
      end;
    end;
    
    
    function RC4_GetByte(var buf : array of byte; var x : integer; var y : integer) : byte;
    var
      temp : byte;
    begin
      x := (x + 1) and 255;
      y := (y + buf[x]) and 255;
    
      temp := buf[y];
      buf[y] := buf[x];
      buf[x] := temp;
      result := buf[(temp + buf[y]) and 255];
    end;
    
    procedure RC4_Crypt(var input : string; len : integer; key : string; key_len : integer);
    var
      key_buf : array [0..255] of byte;
      rc4_x : integer;
      rc4_y : integer;
      x : integer;
      y : integer;
    begin
      rc4_x := 0;
      rc4_y := 0;
      
      RC4_Init(key_buf, key, key_len);
    
      for y := 0 to 9 do
      begin
        for x := 1 to len do
        begin
          input[x] := chr(ord(input[x]) xor RC4_GetByte(key_buf, rc4_x, rc4_y));
        end;
      end;
    end;
    
    Использование:
    RC4_Crypt(строка_для шифрования, длинна_данных, ключ_шифрования, длинна_ключа);

    Вообще требовалось сделать быстрый шифр строк для вставки в сишные исходники, по этому написал вот такую вот функцию:
    Code:
    
    function Crypt(msg : string; key : string):string;
    var
      x : integer;
      ret : string;
      len : integer;
    begin
      len := length(msg);
      RC4_Crypt(msg, len, key, length(key));
    
      ret := 'char DATA[] = {'+#13#10+#9;
      for x := 1 to len do
      begin
        ret := ret + '0x' + inttohex(ord(msg[x]), 2);
        if (x <> len) then ret := ret + ', ';
        if x mod 16 = 0 then ret := ret + #13#10#9;
      end;
    
      result := ret + #13#10 + '};';
    end;
    
    var
      msg : string;
    begin
      msg := memo1.Lines.Text; // читаем входные данные
      msg := Crypt(msg, edit1.Text); // шифруем и на выходе получаем готовый кусок в сишном виде
      Memo2.Lines.Text := msg; // вставляем результат
    end;
    
    Примером шифрования строки:
    С ключем q123456
    Будут данные
    Этиже данные с ключем q123457
     
    #1 slesh, 25 Oct 2010
    Last edited: 25 Oct 2010
    1 person likes this.
  2. zeppe1in

    zeppe1in Elder - Старейшина

    Joined:
    12 Jul 2006
    Messages:
    343
    Likes Received:
    66
    Reputations:
    18
    таже история, только мне почему то в голову сразу пришло
    Code:
    	for (int i = 0;i<size;i++)
    	{
    		data[i]^=key;
    		key++;
    	}
    :D
    а тут такой подарок, отлично)