basit string şifreleme (xor)

Yazdığınız makaleleri ve üyelerimizin işine yarayacağını düşündüğünüz kodlarınızı gönderebilirsiniz. Bu foruma soru sormayın!
Cevapla
Kullanıcı avatarı
mege
Admin
Mesajlar: 2360
Kayıt: 05 Şub 2004 04:32
Konum: Beşiktaş
İletişim:

basit string şifreleme (xor)

Mesaj gönderen mege »

Kod: Tümünü seç

const
  C1 = 52845;
  C2 = 22719;

function Encrypt(const S: String; Key: Word): String;
var
  I: byte;
begin
  Result[0] := S[0];
  for I := 1 to Length(S) do begin
    Result[I] := char(byte(S[I]) xor (Key shr 8));
    Key := (byte(Result[I]) + Key) * C1 + C2;
  end;
end;

function Decrypt(const S: String; Key: Word): String;
var
  I: byte;
begin
  Result[0] := S[0];
  for I := 1 to Length(S) do begin
    Result[I] := char(byte(S[I]) xor (Key shr 8));
    Key := (byte(S[I]) + Key) * C1 + C2;
  end;
end;
:arrow: Kaynak

dikkat : küçük işler için :)
.-.-.-.-.-.-.-. ^_^
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

veya

Kod: Tümünü seç

function Decrypt(const S: String; Key: Word): String;
begin 
    Result:= Encrypt(S, Key);
end;
:wink:
ferhat71
Üye
Mesajlar: 4
Kayıt: 07 Haz 2005 09:07

Mesaj gönderen ferhat71 »

arkadaşlar bu koddaki satırların ne anlama geldiğini açıklarsanız sevinirim.
bildiğim kadarıyla xor iki baytı karşılaştırıyor.orda "byte(S)" yazılacağına
"ord(S)" yazılsaydı olmazmıydı?
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

ferhat71 yazdı:orda "byte(S)" yazılacağına
"ord(S)" yazılsaydı olmazmıydı?

Olurdu niye olmasın.
ng
Üye
Mesajlar: 192
Kayıt: 01 Mar 2004 11:49
Konum: Bursa
İletişim:

Mesaj gönderen ng »

neden küçük işler için ?
büyük işler için nasıl bir şifreleme önerirsin ?
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Kırması çoook kolay da ondan.

Büyük işler için DES, AES, Blowfish yeterlidir.
Kullanıcı avatarı
delphist
Üye
Mesajlar: 595
Kayıt: 05 Oca 2005 04:34

Mesaj gönderen delphist »

Element 0 inaccessible use Length or Setlength hatası alıyorum dll içine atatığım zaman sebebi nedir.


//aslangeri tarafından edit edildi..

Not :Makaleler forumunda soru sormak uygun değil. Cevap vermek isteyen arkadaşlar aşağıdaki linki kullansınlar....
viewtopic.php?p=78665
poshet303
Üye
Mesajlar: 235
Kayıt: 26 Eki 2005 01:15

Mesaj gönderen poshet303 »

Bu bir makale incelemesi olduğu için bu makale altına ekledim.

Kod: Tümünü seç

Result[0] := S[0]; 
Bu kısım Pascal da çalışır ama Delphi de erişilemez. coderlord
un viewtopic.php?p=78665
daki çözümü yada basitçe

Kod: Tümünü seç

 Result:=S;
Kullanabilir.

Bu XOr algoritması enteresan. Klasik XOR ile kodlamada Encrypt eden kod aynı zamanda Decrypt eder. O nedenle olsa gerek coderlord

Kod: Tümünü seç

function Decrypt(const S: String; Key: Word): String; 
begin 
    Result:= Encrypt(S, Key); 
end; 
Yazmış ama burda bu işe yaramaz. Encrypt eden fonksiyon Decrypt eden fonksiyondan farklı.
Programı yazan akıllıca bir yöntemle benimde merak etttiğim bir sorunu çözmüş.
XOr işlemi esnasında eğer String içersindeki bir değer Anahtara eşitse Encrypt edildiğinde 0 değeri elde ediliyor. C stringlerinde bu string sonu olduğu için ve windows C stringleri ile çalıtığı için sizin string in bu değerden sonrası uçuyordu.
Burda önce matematiksel dönüşüm (ilk gördüğümde şaşırttı beni çünkü byte üzerinde işlem yapılıyor halbuki dönüşüm sonrası byte a sığmayacak değerler oluşuyor Key zaten word tanımlanmış) sonrada bit operasyonu (bu operasyonla word ü byte a çevirmiş) yapılıyor ve sonuçta Ascii 0 sorunu çözülüyor.

Bu kodun tek dezavantajı XOR anahtarı olarak sadece word kullanması haliyle 64000 küsür ihtimalle kodlanan string çözülebilir. Halbuki ben çok uzun anahtarlar kullanıyordum. Çözümü neredeyse imkansız (tabi Ascii 0 sorunu yaşıyordum).

XOR oldukça güçlü bir şifreleme aslında kullanımı basit, aynı kot ile hem Encrypt hem Decrypt işlemi yapılabiliyor. Çözmenin yolu ise şifrelenmiş veri parçası ile ona denk şifrelenecek veri parçası elde etmek.


İyi eğlenceler
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

poshet303 yazdı: Yazmış ama burda bu işe yaramaz. Encrypt eden fonksiyon Decrypt eden fonksiyondan farklı.
Haklısın. Bu gözümden kaçmış. İyi yakalamışsın. :)
ylmz
Üye
Mesajlar: 110
Kayıt: 18 Mar 2005 02:32
Konum: Antalya

Mesaj gönderen ylmz »

merhaba,
ferhat71 yazdı:arkadaşlar bu koddaki satırların ne anlama geldiğini açıklarsanız sevinirim.
bildiğim kadarıyla xor iki baytı karşılaştırıyor.orda "byte(S)" yazılacağına
"ord(S)" yazılsaydı olmazmıydı?

Kod: Tümünü seç

Result[0] := S[0] 

Stringler aslında bir char dizisi olarak bellekte tutulurlar.Ve bu dizinin ilk byte stringin uzunluğunu verir.bir örnek vermek gerekirse

Kod: Tümünü seç

  var
    Str: String[10]
gibi bir tanımlama yaptığımızda Str değişkenimiz için bellekte 11 byte yer ayrılır.Bunun ilk byte ı string değişkenimizin uzunluğu geri kalan 10 byte da değişkenimizin değerini içerecek.

Kod: Tümünü seç

   Str := 'abcdefghiz';
bu atamada str için ayrılmış 11 byte uzunluğundaki belleğin içeriği şöyle olacak

s[0] = 10
s[1] = 'a'
s[2] = 'b'
s[3] = 'c'
s[4] = 'd'
s[5] = 'e'
s[6] = 'f'
s[7] = 'g'
s[8] = 'h'
s[9] = 'i'
s[10] = 'z'

o halde "Result[0] := S[0]" satırı fonksyondan (Result) dönecek değerin uzunluğu ile parametre olarak aldığımız "s" değerinin uzunluğunu birbirine eşitler.Böyle bir eşitleme yapmamızın sebebi ise daha sonra result'un her byte na tek tek atama yapmamız gerektiği içindir. burada "Result := S" yapmamızda aslında bize aynı sonucu verecektir.(Tam olarak olmasada!)
Şimdi Decrypt fonksiyonuunda kullanılan diğer fonksiyonları incelemeden bir süreliğine bitlere kadar inip bellekte asıl olarak neler yapıldığına daha yakından bakalım.

bellekte (bilgisayarda) herşey bir dizi "1" ve "0" dan oluşur.Burada "0" ve "1" değerini alan bu anahtarlara bit diyoruz. Anlamlı olabilecek en küçük değeri ancak 8 bit ile ifade edebiliyoruz ki bu 8 bite de byte denir.Örnek olarak "A" harfinin bellekteki görünüşü şöyledir.

Kod: Tümünü seç

0 1 0 0 0 0 0 1     
- - - - - - - -
"A" ascii tablosunda 65 ile ifade edilir 65 in ise ikilik koddaki gösterimi budur.

Bir bitle sadece iki değeri ifade edbiliriz."0" ve "1". iki bitle ise "00", "01", "10","11'. toplam 2^2 = 4.
bu formülden 8 bitle 2^8 = 256 farklı değeri ifade edebiliriz.

Kod: Tümünü seç

var
  A: Byte;
gibi bir tanımlamayla bellekte pozitif bir sayı tutmak için bir byte'lık bir yer ayırmış oluruz.Bir byte ile ifade edebileceğimiz en küçük ve en büyük sayılar

Kod: Tümünü seç

   0 0 0 0 0 0 0 0   = 0
   1 1 1 1 1 1 1 1   = 255
en küçüğü 0 ve en büyüğü 255 olmak üzere toplam 256 adet farklı değer.

Kod: Tümünü seç

var
  A: Word;
gibi bir tanımlamayla a değişkeni için bellekte iki byte yer ayırmış oluruz ki buradada ifade edebileceğimiz
2^16 = 65536 farklı değer olur.en büyüğü 65535.

peki ya negatif sayılar.

negatif sayıları ifade etmek için en yüksek anlamlı bit (en soldaki bit) işaret biti olarak kabul edilir.Pozitif sayılar için "0" negatif sayılar için "1" ile ifade edilir.

Kod: Tümünü seç

var
  A: ShortInt;
tanımlamasıyla bellekte bir sayı tutmak için (negatif yada pozitif) bir byte lık yer ayrılır.

Kod: Tümünü seç

 Değer            bellek
  ------------     ---------------
  A := 1;          0 0 0 0 0 0 0 1
  A := 2;          0 0 0 0 0 0 1 0
  A := -1;         1 0 0 0 0 0 0 1   (?????)
Pozitif sayıları ifade etmek için ilk biti işaret biti olarak kullandığımızda geriye elimizde 7 bit kalır ki bununlada ifade edebileceğimiz en büyük sayı

Kod: Tümünü seç

 
0    1 1 1 1 1 1 1    =  127 olur.
-     - - - - - - - 
i.b
-1 i ifade etmek için ilk akla gelen

Kod: Tümünü seç

1     0 0 0 0 0 0 1 
-     - - - - - - -
İ.B                                  (İ.B: İşaret biti)
şeklinde olmaz.Aslında negatif sayılar ilk biti işaret biti olmak üzere geri kalan bitlerin 2 ye tümleyeni şekline gösterilir.2 ye tümleyen ise 1 e tümleyenin (yani "0" ise "1", "1" ise "0") 1 fazlası alınarak elde edilir.örnek olarak "-1" i iafade etmek için "1", 2 ye tümleyerek gösterelim.

Kod: Tümünü seç

0 0 0 0 0 0 0 1   = 1
1 1 1 1 1 1 1 0   ---> 1 e tümleyeni
+             1
1 1 1 1 1 1 1 1   ---> (2 ye tümleyen yani "-1" bellekteki görüntüsü)
2 ye tümleyeni bulmanın kısa yolu : ikiye tümleyeni kısa yoldan yapmak için en sağdaki bitten başlayarak sola doğru ilk "1" e kadara olan bitleri değiştirmeden bırakıp sonraki bitleri 1 e tümlemeyerek sonuca ulaşabiliriz.

"-1" in "1 1 1 1 1 1 1 1" şekilinde gösterildiğini gözlerinizle görmek için formun üzerine bir buton ve bir edit koyarak button1.onclik olayna şu kodu yazın.

Kod: Tümünü seç

var
  a: Shortint;
  sayac: Integer;
begin
  Edit1.Clear;
  a := -1;
  for sayac := 0 to 7 do
    Edit1.Text := InttoStr((a shr sayac) And 1) + Edit1.Text;
end;
Decrypt fonksiyonunu incelemeye devam edelim.

ord / byte : karakterin ascii kodunu verir. Ord('A') = 65 Ord('B') = 66... gibi.
Chr : Ord fonksiyonunun tersini yapar. Chr(65) = 'A' gibi.
shr, shl : bit düzeyinde işlem yapar. örnek olarak
65 syısının ("A" karakteri) bellekte nasıl tutulduğuna bakalım.

Kod: Tümünü seç

            
                  0 1 0 0 0 0 0 1   ("A" karakteri bellekte bu şekilde tutuluyor.)
                  - - - - - - - - 
Shr bu yapıyı (bitleri) bir derece sağa öteler SHR(ight)
Shl bu yapıyı bir derece sola öteler SHL(eft)

buradan yola çıkarsak

(65 shr 1) = (01000001 shr 1) = (00100000) = 32 olur. Yani bir derece sağa kaydırınca yarısını almış oluyoruz(daha doğrusu div 2).Bir de tersini yapalım

(32 shl 1) = (00100000 shl 1) = (0100000000) = 64 oldu.

özetlemek gerekirse
A * 2 = (A shl 1)
A div 2 = (A Shr 1) oldu.

lojik kapılar(And, Or, Xor, Not):

Kod: Tümünü seç

       And | 1   0         Or  | 1   0        Xor | 1   0       
       ------------        ------------       ------------
       1   | 1   0         1   | 1   1        1   | 0   1
       ------------        ------------       ------------
       0   | 0   0         0   | 1   0        0   | 1   0
       ------------        ------------       ------------
And, Or ve Xor işlenecek iki değeri alarak sonuç üretir."Not" operatörü ise adı üstünde tersini alır.Yani
Not(1) = 0 ve Not(0) = 1, Not (1 and 0) = 1 gibi.

yukarıdaki örnekten yola çıkarsak iki byte xor kapısından şöyle alabiliriz.
(00100101 xor 11101001) = (11001100) olur.işlemi daha iyi görmek için alt altta yazıyorum.

Kod: Tümünü seç

       00100101
       11101001        XOR
       -------------------
       11001100
bir değeri iki defa aynı değerle xor kapısından geçirirsek yine ilk değeri elde ederiz.Örnek

1 Xor 1 Xor 1 = 1
1 Xor 0 xor 0 = 1
0 xor 1 xor 1 = 0
0 xor 0 xor 0 = 0

o halde Decrypt fonksiyonundaki

Kod: Tümünü seç

    Key := (byte(S[I]) + Key) * C1 + C2;
satırını aradan çıkarırsak

Kod: Tümünü seç

        function DecryptAndEncrypt(const S: String; Key: Word): String; 
        var 
          I: byte; 
        begin 
          Result[0] := S[0]; 
          for I := 1 to Length(S) do
            Result[I] := char(byte(S[I]) xor (Key shr 8)); 
          end;
elde edeceğimiz bu DecryptAndEncrypt fonksiyonu hem şifreleme yapar hemde bu şifreyi çözer.DecryptAndEncrypt fonksiyonunun Decrypt fonksiyonuna göre çözülmesi daha kolay bir şifreleme yapacağı açıktır.Ayrıca bu fonksiyonun şifreleme yapabilmesi için "key" parametresinin değeri en az 256 olmalıdır.Çünkü 256 dan daha küçük değerler ancak en sağdaki 8 biti değiştireceğinden ve biz (Key shr 8) yani bu sayıyı bit düzeyinde 8 defa sağa öteleyeceğimizden her zaman "0" ile xor kapısını girecektir ki dolayısıyla gönderdiğimiz stringi olduğu gibi geri almış oluruz.Demekki Decrypt fonksiyonun anahtarı

Kod: Tümünü seç

Key := (byte(S[I]) + Key) * C1 + C2; 
satırıdır.Eğer ben bu satırdaki işlemlerin tersini yapan bir kod yazarsam encrypt fonksiyonunu bulmuş olurum.Örnek olarak encrypt fonksiyonuna bir alternatif yazmaya çalışalım.

Kod: Tümünü seç

       01    function Decrypt(const S: String; Key: Word): String; 
       02    var 
       03      I: byte; 
       04    begin 
       05       Result[0] := S[0]; 
       06       for I := 1 to Length(S) do begin 
       07         Result[I] := char(byte(S[I]) xor (Key shr 8)); 
       08         Key := (byte(S[I]) + Key) * C1 + C2; 
       09       end; 
       10    end;
burada

Kod: Tümünü seç

Result[I] := char(byte(S[I]) xor (Key shr 8)); 
her seferinde

Kod: Tümünü seç

Key := (byte(S[I]) + Key) * C1 + C2;
satırında belirlenen "key" e göre bir karakteri şifreler.Bunun tersini yapmam için Encrypt fonksiyonunda bana gelen S zaten şifrelenmiş olduğundan ilk önce bu şifreyi çözerek

Kod: Tümünü seç

Key := (byte(S[I]) + Key) * C1 + C2;
satırına girmesini sağlarımki o da şu şekilde olur.

Kod: Tümünü seç

byte(S[I] xor (key shr 8)
şimdi bunu gerekli yere yazarsam

Kod: Tümünü seç

Key := (byte(S[I]) + Key) * C1 + C2;
satırının tersi

Kod: Tümünü seç

Key := ((Ord(S[I]) xor (Key shr 8)) + Key) * C1 + C2;
olur.

şimdi Encrypt fonksiyonunun tamamı şu şekilde olur.

Kod: Tümünü seç

  function TForm1.Encrypt(const S: String; Key: Word): String;
  var
    I: byte;
  begin
    Result := S;
    for I := 1 to Length(S) do begin
      Result[I] := Char(Ord(S[I]) xor (Key shr 8));
      Key := ((Byte(S[I]) xor (Key shr 8)) + Key) * C1 + C2;
    end;
  end;
son olarak C1 ve C2 sabitlerine bakalım.

Kod: Tümünü seç

const 
  C1 = 52845; 
  C2 = 22719;
olarak tanımlanmışlarıdır.Oysa bizim fonksiyonlarımızdaki "Key" parametresi word olarak tanımlanmıştır ve word olarak tanımlanmış bir değişkenin alabileceği max değer

Kod: Tümünü seç


word := 0..65535 dir.

Key := (byte(S[I]) + Key) * C1 + C2;  stırında
         ------------------
              x
x'in alabileceği en küçük değerde bile ( 1 * 52845 + 22719) "Key" değişkenimiz sınırlarını aşacaktır.

iyi çalışmalar.
En son ylmz tarafından 16 Mar 2006 11:35 tarihinde düzenlendi, toplamda 1 kere düzenlendi.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Eline sağlık.
ylmz yazdı: o halde "Result[0] := S[0]" satırı fonksyondan (Result) dönecek değerin uzunluğu ile parametre olarak aldığımız "s" değerinin uzunluğunu birbirine eşitler.
Eski short string tanımı için söylediğin şey geçerli ancak Delphi'nin default olarak kullanmaya başladığı long string'lerde bu tanımlamayı yapamazsın.

Yapmaya kalkarsan Delphi derleyicisi
Element 0 inaccessible - ..
hatası verecek ve 0. indexe erişmeni reddedecektir.
ylmz
Üye
Mesajlar: 110
Kayıt: 18 Mar 2005 02:32
Konum: Antalya

Mesaj gönderen ylmz »

merhaba,
coderlord yazdı:Eline sağlık.

Eski short string tanımı için söylediğin şey geçerli ancak Delphi'nin default olarak kullanmaya başladığı long string'lerde bu tanımlamayı yapamazsın.

Yapmaya kalkarsan Delphi derleyicisi
Element 0 inaccessible - ..
hatası verecek ve 0. indexe erişmeni reddedecektir.
haklısın.
bu satırı derlemek isteyen arkadaşlar için küçük bir hatırlatma yapayım.

eğer project - option seçeneklerine girer compiler tabındaki "huge strings" parametresini kapatırsanız bu satırı derleyebilirsiniz.Ayrıca bu seçeneği kapattığınızda direk F9 ile bu satır çalışmayabilir.Delphini derleyici direktiflerini tekrar okumasını sağlamak için Build All Project menüsünü deneyin.Kolay gelsin.
Cevapla