Simetrik Şifreleme - Part 2


#1

Bir önceki yazımızda simetrik şifreleme yöntemlerinden block cipher’ ları anlatmıştık. Bu yazımda ise stream cipher lardan bahsedeceğim. Block cipher’ lar belirli bir veri boyutu üzerinde işlem yapıyorlar, stream cipherlar ile ise istenilen boyutlarda veri şifrelenebilir.

Aslında stream cipherlar temel olarak Pseudo-random generator kullarak One Time Pad simüle ediliyor. One Time Pad kısaca tam olarak şifrelenmek istenen verinin büyüklüğü kadar bir veriyle XOR işlemine tabi tutulması. Stream cipherlarda temel bir anahtardan veri ile XOR lanacak bir veri üretilmesidir.

Stream cipherlar performans olarak block cipherlardan daha iyidir. Fakat güvenlik açısından bakıldığında aynı başarıyı gösteremeyebilir. İyi şeçilmemiş bir “Pseudo Random Generator” bilgi sızıntısına sebep olabileceğinden tüm şifreleme sisteminin çökmesine sebebiyet verebilir.

Bundan bağımsız olarak Stream cipherlar block cipherlarda bulunan bütünlük (integrity) ve yetkilendirme (authenticantion) özelliklerini bulundurmaz. Bu yönüyle de block cipherlar daha güvenli bir şifreleme imkanı sağlarlar denilebilir.

Aşağıda Adam Beck tarafından implemente edilen RC4 stream cipher kodunu bulabilirsiniz.

#include <stdio.h>

#define buf_size 1024

typedef struct rc4_key
{      
   unsigned char state[256];       
   unsigned char x;        
   unsigned char y;
} rc4_key;

#define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t

void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key)
{
  int i;
  unsigned char t;
  unsigned char swapByte;
  unsigned char index1;
  unsigned char index2;
  unsigned char* state;
  short counter;

  state = &key->state[0];
  for(counter = 0; counter < 256; counter++)
  state[counter] = counter;
  key->x = 0;
  key->y = 0;
  index1 = 0;
  index2 = 0;
  for(counter = 0; counter < 256; counter++)
  {
    index2 = (key_data_ptr[index1] + state[counter] + index2) % 256;
    swap_byte(&state[counter], &state[index2]);
    index1 = (index1 + 1) % key_data_len;
  }
}

void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key)
{
  unsigned char t;
  unsigned char x;
  unsigned char y;
  unsigned char* state;
  unsigned char xorIndex;
  short counter;

  x = key->x;
  y = key->y;
  state = &key->state[0];
  for(counter = 0; counter < buffer_len; counter++)
  {
    x = (x + 1) % 256;
    y = (state[x] + y) % 256;
    swap_byte(&state[x], &state[y]);
    xorIndex = (state[x] + state[y]) % 256;
    buffer_ptr[counter] ^= state[xorIndex];
  }
  key->x = x;
  key->y = y;
}

int main(int argc, char* argv[])
{
  char seed[256];
  char data[512];
  char buf[buf_size];
  char digit[5];
  int hex, rd,i;
  int n;
  rc4_key key;

  if (argc < 2)
  {
    fprintf(stderr,"%s key <in >out\n",argv[0]);
    exit(1);
  }
  strcpy(data,argv[1]);
  n = strlen(data);
  if (n&1)
  {
    strcat(data,"0");
    n++;
  }
  n/=2;
  strcpy(digit,"AA");
  digit[4]='\0';
  for (i=0;i<n;i++)
  {
    digit[2] = data[i*2];
    digit[3] = data[i*2+1];
    sscanf(digit,"%x",&hex);
    seed[i] = hex;
  }

  prepare_key(seed,n,&key);
  rd = fread(buf,1,buf_size,stdin);
  while (rd>0)
  {
    rc4(buf,rd,&key);
    fwrite(buf,1,rd,stdout);
    rd = fread(buf,1,buf_size,stdin);
  }
}