Veritabanı Fieldlarının Şifrelenmesi için bir çözüm

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Veritabanı Fieldlarının Şifrelenmesi için bir çözüm

Mesaj gönderen Akin_Delphi »

Arkadaşlar,
Forumda aradım ancak bulamadım. Ayrıca google üzerinden de arattırdım ancak genelde hep ticari bileşen paketi siteleri çıkıyor.

Bu nedenle biraz deneme yanılma yoluyla bu konuya bir çözüm buldum. Umarım beğenirsiniz ve yorumlarınızı da bekliyorum. Bulduğum çözümü sizinle paylaşmak istiyorum. (Böylece bu ticari paketlere de gereksinimimiz kalmaz) Ayrıca çözümleyemediğim bir konu var (sıralama) o konuda fikir verebilirseniz de sevinirim.

Öncelikle bir özgeçmiş vereyim: Şimdi bir sözlük uygulamamız var. Bu sözlük uygulamamızın verileri, FB VT'de saklanıyor. Eğer nasip olursa ticari bir uygulama haline gelecek. Ancak kullanıcıya veritabanı dosyasını dağıtacağımız ve uygulamanın veritabanını gömülü (embedded) sunumcu şeklinde kullanacağı için, birilerinin basitçe VT içerisindeki kelime ve tanımları kopyalayıp kendi sözlüğünde kullanması riski var. Bunu önlemek için, VT içerisindeki alanları şifrelemeyi ve hemen göstermeden önce de deşifrelemeyi düşündüm.

Pekçok deneme ve yanılmadan sonra en kolay ve yapılabilir çözümün TField bileşeninin onGetText ve OnSetText olay işleyicilerinin kullanıması olduğunu gördüm.

Bunun için kodumuz şöyle:

Önce OnGetText ve OnSetText olay işleyicilerle tıpatıp aynı parametreleri olan iki prosedür oluşturuyoruz.

Kod: Tümünü seç

TForm1 = class(TForm)
...
...
...
    procedure DataFieldSetText(Sender: TField;const Text: String);
    procedure DataFieldGetText(Sender: TField;var Text: String;
    DisplayText: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
......

Daha sonra Ctrl-Shift-C tuş kombinasyonuna basıp, bu prosedürlerin iskeletinin birim (Unit) içerisinde otomatik olarak oluşturulmasını sağlıyoruz. Ve içlerini aşağıdaki şekilde dolduruyoruz.

Kod: Tümünü seç

procedure TForm1.DataFieldGetText(Sender: TField; var Text: String;
  DisplayText: Boolean);
begin
//bu jenerik get text
Text := Desifrele((Sender as TField).AsString);
end;

Kod: Tümünü seç

procedure TForm1.DataFieldSetText(Sender: TField; const Text: String);
var
gecicimetin : String;  
begin
gecicimetin := Text;
gecicimetin := Sifrele(gecicimetin);
(Sender as TField).AsString := gecicimetin;
end;
Ardından Formun (ya da DataModule'ün) OnCreate olayında aşağıdaki kodu yazıyoruz:

Kod: Tümünü seç

procedure TForm1.FormCreate(Sender: TObject);
Var
i : integer;
AComponent : TComponent;
begin
//burada ilgili fieldları bul ve bunların ONGetText ve OnSetText eventlerini ayarla
  For i := 0 to ComponentCount-1 do
  begin
  AComponent := Components[i];
    If AComponent is TField then
    begin
      If (AComponent as TField).Name =
      IBDataSet1ENCRYPTEDFIELD.Name then
      begin
      (AComponent as TField).OnGetText := DataFieldGetText;
      (AComponent as TField).OnSetText := DataFieldSetText;
      {$IFDEF HATAAYIKLA}
      OutputDebugString(PChar(Format('(AComponent as TField).Name:%s',[(AComponent as TField).Name])));
      {$ENDIF}
      end;
    end;
  end;
//burada ilgili fieldları bul ve bunların ONGetText ve OnSetText eventlerini ayarla SON


/burada veritabanını açma işlemlerini yapınız
..........
..........
/burada veritabanını açma işlemlerini yapınız SON
end;
Burada yaptığımız şey Formun (ya da DataModule'ün) OnCreate olay işleyicisinde form (ya da DataModule) üzerindeki bütün bileşenleri taramak ve eğer bulunan komponent TField tipine ve belirli bir TField'ın adına sahipse, bu ilgili TField'ın OnSetText olay işleyicisine DataFieldSetText prosedürümüzü, OnGetText olay işleyicisine ise DataFieldGetText prosedürümüzü tayin ediyoruz. Ayrıca yalnızca belirli isimlere sahip TField alanlarının OnGetText ve OnSetText olay işleyicilerini bizim jenerik olay işleyicilerimize tayin ettiğimiz için, yalnızca istediğimiz alanları şifrelemiş ve (gösterirken/ göstermeden hemen önce) deşifre etmiş oluyoruz. Dolayısıyla, otomatik artan (AutoIncrement) tip, trigger ve generator ile oluşturulmuş alanların olay işleyicilerini kesinlikle jenerik prosedürlerimize tayin etmiyoruz. Aksi takdirde bunların hem otomatik üretilmesi hem de Pimary Key olmaları itibariyle sorun çıkar.

Burada (daha) önemli olan diğer bir konu, bizim oluşturduğumuz prosedürlerin aldığı parametrelerle, OnSetText, OnGetText olay işleyicilerinin aldığı parametrelerin birebir aynı olması. Aksi takdirde bu tayin işlemini (yani (AComponent as TField).OnGetText := DataFieldGetText; vs işlemini) yapamıyoruz derleyici basitçe yapmayı reddediyor.

Diğer bir husus ise Sifrele/Desifrele fonksiyonu bu fonksiyonlar bir string parametresi alıyor ve string sonucu döndürüyor. Fonksiyonların içlerini yazmayacağım çünkü herkesin kendine göre bir şifreleme yöntemi var. Ancak burada ipucu vermek istiyorum. Şifreleme için bu fonksiyonlar içerisinde Delphi Encryption Compendium'un bileşenlerini (ücretsizdir) kullandım. Bu bileşenler 2048 bite kadar şifreleme yapabiliyor. Yani çok güçlü. :twisted: :twisted: :twisted: (Burada kötü kahkahalar atıldığını hayal edin.)

Bu işlemleri yapmadan önce boş bir veritabanı oluşturunuz. Bu veritabanı içerisinde TEST adlı bir tablomuz ve bu tablomuzun ise SIRANO ve ENCRYPTEDFIELD alanlarımız olsun.

Birer adet IBDataBase, IBTransaction, IBDataSet, Datasource bileşeni yerleştiriniz. Gerekli Login, Veritabanı konumu ve gerekli diğer parametreler neyse onları ayarlayınız ve IBDataSet'in SQL ifadelerini falan oluşturunuz.

Forma bir DBGrid, DBNavigator, bir DBEdit (veya DBMemo) bileşeni koyunuz ve DBGrid ve DBNavigator'un DataSource özelliğini DataSource'a ayarlayınız. Şimdi çalıştırınız, veri giriniz ve kaydediniz. Programı kapatırken, Commit, ya da CommitRetaining prosedürünü kullanınız. IBExpert'te aynı tablonun verilerine baktığınızda şaşıracaksınız. Çünkü alanın içerdiği veri, uygulamada şifrelenmemiş şekilde gösterilirken, VT içerisinde şifrelenmiş durumdadır. :twisted: :twisted: (Yine kötü adam kahkahaları....)

Şimdi elimde olanı paylaştıktan sonra, sizden bir konuda yardım etmenizi isteyeceğim. Şimdi bunun bir sözlük olması itibariyle, arama özelliği var (StoredProcedure (SP) ile hallettim). Ancak SP ve uygulama içerisindeki IBDataset bileşenlerinin order by KELIME COLLATE PXW_TURK ifadelerini kullanıyor. Ancak veri şifreli olduğu için (yani SP açısından anlamsız olduğu için), çekilen veriyi doğru şekilde sıralamıyor.

Acaba VT'den çekilen veriyi uygulama içerisinde (SQL, vs. kullanmaksızın) tekrar sıralamamın mümkünatı var mıdır? SQL kullanamayağım kesin çünkü veri şifrelenmiş durumda. Bu konuda bir fikri olan var mıdır? Saygılarımla.

Önemli Not : OnGetText ve OnSetText olay işleyicileri yalnızca veri bilinçli (Data Aware) bileşenler üzerinde veri değişikliği yapıldığında ateşleniyor. Eğer kod içerisinde alanların değerlerini programsal olarak değiştiriyorsak, OnGetText ve OnSetText olay işleyicileri ateşlenmiyor. Bu durumda, şu şekilde kod yazmak gerekiyor

Kod: Tümünü seç

IBDataSet1KELIME.AsString := Sifrele('Ne Mutlu Türküm Diyene');

Umarım birilerinin işine yarar ve hep birlikte daha gelişmiş bir hale getirebiliriz.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Akın_Delphi,

Uygulaman oldukça enteresan, fakat bunu decrypt edecek parolayı veya private_key'i de uygulamanla birlikte taşıma gereksinimin olduğu için 2048 bit şifrelenmesi pek de bir anlam ifade etmiyor. Debug ederek parolayı ele geçirmelerini de önlemen lazım. Bunun üzerinde de vakit harcaman gerektiğini düşünüyorum.

Uygulama içinde sort için, MemoryTable benzeri bir yapı kullanabilirsin. Ücretsiz sürümleri vardı.
Kullanıcı avatarı
aslangeri
Moderator
Mesajlar: 4322
Kayıt: 26 Ara 2003 04:19
Konum: Ankara
İletişim:

Mesaj gönderen aslangeri »

s.a.
UDF lere göz ataraktda belki bişeyler yapabilirsin.
sıralama için...
kolay gelsin.
Duyduğun Şeylerin Söylediklerim Olduğuna Eminim Ama
Anladığın Şeylerin Anlatmak İstediklerim Olduğuna Emin Değilim
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Mesaj gönderen Akin_Delphi »

coderlord yazdı:Akın_Delphi,

Uygulaman oldukça enteresan, fakat bunu decrypt edecek parolayı veya private_key'i de uygulamanla birlikte taşıma gereksinimin olduğu için 2048 bit şifrelenmesi pek de bir anlam ifade etmiyor. Debug ederek parolayı ele geçirmelerini de önlemen lazım. Bunun üzerinde de vakit harcaman gerektiğini düşünüyorum.

Uygulama içinde sort için, MemoryTable benzeri bir yapı kullanabilirsin. Ücretsiz sürümleri vardı.
Bu konuda haklısınız. Lisanslama açısından, Armadillo programının DR (Digital River) sürümünü kullanacağım ve Lisanslar donanım kilitli olacak. Yani yazılımı satın alan kişi bize program üzerinde belirlenecek olan donanım imzasını ve kullanıcı adını bize bildirecek ve dolayısıyla bizim vermiş olduğumuz key yalnızca belirli bir donanım imzasına (Hardware Fingerprint) sahip olan bilgisayarlarda çalışacak.

Armadillo DR sürümü programı şifreliyor. Dolayısıyla disassembly yapmak biraz zor. Ayrıca 2048 bit şifreleme yapmak sizin de dediğiniz gibi anlamsız ve CPU ve bellek israfı. Ancak Delphi Encryption Compendium bileşenleri 40 bitlik şifrelemeleri de destekliyor. Kaldı ki, çok aşırı derecede gizli bilgileri VT'de saklamayacağız. Sonuç olarak daha çok telif hakkı korumaya yönelik bir uygulama.
aslangeri yazdı:Akın_Delphi,
s.a.
UDF lere göz ataraktda belki bişeyler yapabilirsin.
sıralama için...
kolay gelsin.
a.s.
Şimdi açık söylemek gerekirse, UDF bildiğim kadarıyla dll'ler aracılığıyla yapılıyor ve ben de dll konusunda pek iyi değilim. Ayrıca uygulamayla birlikte verileri deşifreleyen bir dll vermek de çok akıllıca değil gibi geliyor.

Bu sıralama konusunda, dün gece biraz çalıştım. Şimdi verileri girerken, şifrelenmemiş VT içerisine gireceğiz. Eğer nasip olur da, sözlüğü tamamlarsak, ürün haline getirmeden önce şifreleyerek yeni bir veritabanına atmayı düşündüm. Şifrelenmemiş olanın verileri Türkçe karakterlere göre doğru bir şekilde sıralanmış olacağından dolayı, şifrelenmiş veritabanına programsal olarak atarken bir sorun olacağını düşünmüyorum.

Yalnız daha arama SP'nin iyi çalışıp çalışmadığını kontrol etmeye vaktim olmadı. Bunun üzerinde çalışmalıyım. Saygılarımla ve cevaplarınız için teşekkürler.
Kullanıcı avatarı
mepc
Üye
Mesajlar: 191
Kayıt: 26 Eyl 2003 11:39
Konum: Ankara

Mesaj gönderen mepc »

advantage veritabanında veritabanının kendi şifreleme yeteneği var.
Bilgi paylaşıldıkça güzeldir.
Kullanıcı avatarı
gkimirti
Admin
Mesajlar: 1956
Kayıt: 02 Eyl 2003 04:44
Konum: İstanbul

Mesaj gönderen gkimirti »

ÜŞENME,ERTELEME,VAZGEÇME
poshet303
Üye
Mesajlar: 235
Kayıt: 26 Eki 2005 01:15

Mesaj gönderen poshet303 »

Firebird de verilerimi nasıl korurum sorusu benimde üzerinde düşündüğüm bir konu oldu. Sizinkine benzer bir yöntem düşünmüştüm. Yalnız ben hazır fireleme rutinleri kullanmak yerine kendi rutinlerimi kullanacaktım.

Sıralama sorununa çözümüm şu idi. Eğer yaptığınız şifreleme veri sırasını bozmayacak bir şekilde tasarlanırsa veri sıranız bozulmaz. Ama dediğim gibi hazır rutinler bu kadar esneklik sağlayamayabilir.

Bir kaç mesele;
-Her şifre kırılabilir abi boşuna uğraşma!
Evet doğrudur fakat işin başka yönleride var. Bir FB veri tabanından biraz veritabanı bilgisi olan her kişi rahatlıkla verilerinizi alabilir. Ama sağlam şifrelenmiş bir bilgiyi almak ancak Binlerce kişide bir kaç kişinin başarabileceği bir iş. Kodu disassembly eden trace engineering te iyi sabırlı bir adam verilerimi alsın heleli hoş olsun, ne olcak.

Ayrıca verileri windowsta korumak için veritabanını şifrelemekte yetmiyor. Ve disassembly, trace ile uğraşmayada gerek yok. Bende bir sözlük programı üzerinde çalıştım (5,6 yıl önce) sözlük bilgisi lazımdı o zamanlar en iyi bilgi MOONSTAR da idi bir program yazıp moonstarın sözlük bilgilerini almıştım (17bin küsür kelime var Paradox tablosuna yazdm 35 mb tan büyük olmuştu "like" sorguları celeron333 te çok yavaş çalışıyordu. Moonstar ı yazanlar sıkıştırılmış bir veritabanı dosyası tasarlamışlar dosyadan direk almak imkansız).
Acaba benim yaptığıma benzer bişiyle kaç kişi uğraşmıştır.
Emek veren (illegal de olsa) hak eder.

Korumak içinde olabildiğince emek sarfetmeli.

FB de bu iş çok fazla uğraş istiyor (Kodu açık bir sistemde veri şifreleme ne denli gerekli ki). Access bile size daha rahat koruma sağlar. Advantage nin bu konuda iyi olduğunu bir kaç yerde daha okudum ama denemedim. Bu tür çözümler düşünülebilir.
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Mesaj gönderen Akin_Delphi »

gkimirti yazdı:viewtopic.php?t=1272&postdays=0&postord ... d&start=15
bu linki bir incele
Bu yararlı link için teşekkür ederim. Ancak, amatör programlama ruhumu geliştirmek için, yine de şifreleme yöntemini izlemeye devam edeceğim.
poshet303 yazdı: Her şifre kırılabilir abi boşuna uğraşma!
Evet doğrudur fakat işin başka yönleride var. Bir FB veri tabanından biraz veritabanı bilgisi olan her kişi rahatlıkla verilerinizi alabilir. Ama sağlam şifrelenmiş bir bilgiyi almak ancak Binlerce kişide bir kaç kişinin
Şimdi öncelikle bir şey söylemek istiyorum: Her şifre kırılabilir tabii ki, ancak işin matematiksel yönünü düşünmekte fayda var. Kullandığım şifreleme bileşenleri simetrik şifreleme/deşifreleme yapıyor. Ve şurası bir gerçek ki, simetrik şifreleme, asimetrik şifreleme (ya da diğer bir deyişle public key şifreleme) kadar sağlam değil.

Ayrıca Delphi Encryption Compendium içerisinde bulunan bileşenlerin çok ilginç bir özelliği var. Öncelikle şifreleme için iki bileşene ihtiyacın var: 1. THashmanager, 2. TCipherManager.

Şimdi diyeceksiniz ki, niye bileşenin yazarı iki bileşen kullanmayı şart koşmuş? Çok basit bir nedeni var: Güvenlik.

Bu bileşenlerle şifreleme yaptığınızda TCipherManager aslında şifre olarak girdiğiniz metni kullanmıyor. Bunun yerine girdiğiniz şifre metnini THashManager'dan geçirerek şifrenin Hash'ını hesaplıyor. Dolayısıyla, TCipherManager'a şifre olarak geçilen ve dolayısıyla şifrelemede kullanılan metin hiç bir zaman gerçekte şifre olarak girdiğiniz metin değil.

Bu durum sözlük (dictionary) saldırılarını imkansız hale getiriyor ve kaba kuvvet (brute force) saldırılarını ise çok güçleştiriyor.

İşin matematiğinden bahsetmişken şunu belirtmek istiyorum: Diyelim ki kullandığınız şifre 2048 bit uzunluğunda. Bu şu demek kullanılan şifre (girilen değil THashManager'ın oluşturduğu şifre) 256 karakter uzunluğunda. Yani bu demektir ki, eğer 128 ascii karakterimiz varsa, 128 üzeri 256 değişik kombinasyon var. Bu değerin karşılığı yaklaşık 2,8 x 10 üzeri 539 yani korkunç fazla miktarda kombinasyon var, ve kaba kuvvet saldırısında bulunan kişinin her bir kombinasyonu denemesi gerekiyor. Eğer 2,4 GHz'lik bir pentium işlemcili bir makinenin yalnızca bu işe tahsis edilip her saniye başı 2,8 milyon kombinasyonu denediğini varsayarsak, bu işlem 1,1 x on üzeri 533 saniye, 3,7 x 10 üzeri 525 yıl sürüyor.

Neyse bu bahis çok önemli değil, ben bileşenlerin sağladığı (ve en hızlı ve en az işlemci döngüsü tüketeceğini düşündüğüm) 40 bitlik şifreleme ile yetineceğim: yani amacım devlet sırları saklamak değil. :oops:

Zaten saldırıda bulunacak kişi ekranda (yani uygulamanın veri bilinçli bileşenleri üzerinde) neyin ne olduğunu gördüğü için muhtemelen saldırısını ona göre düzenleyecektir.

Amacım yalnızca birilerinin veriyi programsal olarak alıp, (gerek elektronik ortamda gerekse matbu ortamda) tekrar yayınlamasını zorlaştırmak ve mümkünse engellemek. Ve benim için bu işlemin yapılabilirliği önemli diye düşünüyorum. Yani bir amatör olduğum için, bu işin zevkini çıkartmak istiyorum.

Bu arada, debugging, disassembly konularıyla ilişkili olarak, şunları söylemek istiyorum. Daha önceki mesajımda, Armadillo (DR) kullanacağımı söylemiştim.

Şimdi bu Armadillo (DR) (buradan sonra ADR olarak söyleyeceğim, yazması daha kolay), uygulamaları (ki uygulamalar, yalnızca çalıştırılabilir exe dosyalarını değil aynı zamanda, dll, ActiveX, ActiveForm gibi kütüphane, hatta Delphi kütüphane dosyalarını bile içeriyor) güvenli hale getirmek üzere kullanılıyor.

Programın koruma şekli şu şekilde: Program güçlü bir şifreleme teknolojisi kullanarak tüm makine dilindeki kodu şifreliyor. Ayrıca debugger'ları algılama özelliği de var. Kod şifreli olduğundan, disassembler ile makine dilindeki kodu asm koduna dönüştürmek imkansız, debugger'ların da bağlanmasını engellediği için çalışan koddan bir şey almak da zor görünüyor.

Bu kadar geyikten sonra, asıl tartışmak istediğim konuyu gündeme getirmek istiyorum.

Önceki mesajlardan birinde, bir üye (sanırım Aslangeri) UDF'ler kullanabilirsin demişti. Ben de sıktım dişimi bu işlemi yaptım. Önce yine aynı bileşenleri kullanarak bir dll yazdım ve derledim. Sonra bu dll'yi bir uygulama içerisinde test ettim şifrelemeyi ve deşifrelemeyi yapabiliyormu diye. Oldukça güzel çalışıyor. (Bu arada bu dll'yi de ADR ile şifreleyeceğim.)

Ancak dll içerisinde yine bileşenleri kullandığım için, bileşenleri kütüphane içerisinde oluşturmak ve sonra yok etmek için iki fonksiyon yazdım.

Bu fonksiyonların döndürdüğü değer boolean tipinde. Bu sitede bulduğum delphi'de UDF dll'si oluşturma ve FB'de deklare etmekle ilgili makaleden yararlanarak UDF'yi VT'de tanımlamayı başardım. Yalnız tek bir problem var. Bu problem, daha önce söylemiş olduğum THashManager ve TCipherManager fonksiyonlarını oluşturan ve yok eden fonksiyonların geri döndürdüğü değerin boolean olmasıdır. Bu nedenle bunları FB'de UDF olarak tanımlayamıyorum çünkü veri tipleri içerisinde boolean diye bir değer yok. Ayrıca bu fonksiyon herhangi bir parametre almadığı için de (FB VT'de) nasıl tanımlayacağımı bilemedim. Şifreleme ve Deşifreleme fonksiyonlarını tanımlayabildim. Yalnız oluşturma ve yok etme fonksiyonlarını tanımlayamadığım için, henüz bunları FB üzerinde deneyemedim. :(

Bir de bir konu daha var: Şimdi dll'de bu oluşturma ve yok etme fonksiyonları çalıştırıldıktan sonra ancak ilgili bileşenler kullanılabilir hale geliyor ve ben her şifreleme ve deşifreleme işleminde bileşenleri oluşturup yok etmek konusunda gönülsüzüm. (Belki bellek sızıntısına neden olabilir).

Şimdi bu fonksiyonu bir kere çağırmak mümkün müdür? UDF dll'leri FB'de VT'ye her bağlantı yapıldığında yüklenmekte midir? Yoksa, atıyorum, yalnızca bunu bir SP'de çağırdığımda mı yüklenmekte ve yüklü olarak kalmaktadır? Yani eğer bunu her kullanışımda tekrar tekrar yükleniyorsa, bu durumda şifreleme ve deşifreleme fonksiyonları içerisinde oluşturup yok etmek daha mantıklı gibi. Ancak bir kere çağrıldığında bellekte yüklü olarak kalacaksa, bu durumda benim yaklaşımım daha iyi gibi geldi.

Ayrıca, bu dll'yi uygulama gömülü sunumcu (embedded server) olarak kullandığımda nasıl kullanacağım?

Umarım başınızı ağrıtmamışımdır. Saygılarımla.
Kullanıcı avatarı
sadettinpolat
Moderator
Mesajlar: 2131
Kayıt: 07 Ara 2003 02:51
Konum: Ankara
İletişim:

Mesaj gönderen sadettinpolat »

deşifreleme sözcüğünü okuyunca bi garip olduğumu belirtmek isterim :)

benim aklima takilan mevzular sunlar

yazdigin udf nin tam olarak islevi ve alacagi parametreler neler olacak?

dll in icinde sifrelenmis metni cozen bir udf in haricinde bir de ilgili sifreleme nesnelerini olusturan ayri bir udf mi var ?


bana gore su durumda udf kullanmak dusmana kendi silahini vermek gibi birşey... ufacik bir dll i sen neyle sifrelersen sifrele cozulmesi/incelenmesi cok basit olacaktir. bu da db deki sifrelenmis metinlerin kolayca cozulmesi demektir.
"Sevmek, ne zaman vazgececegini bilmektir." dedi, bana.

---
http://sadettinpolat.blogspot.com/
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Mesaj gönderen Akin_Delphi »

sadettinpolat yazdı:yazdigin udf nin tam olarak islevi ve alacagi parametreler neler olacak?

dll in icinde sifrelenmis metni cozen bir udf in haricinde bir de ilgili sifreleme nesnelerini olusturan ayri bir udf mi var ?

bana gore su durumda udf kullanmak dusmana kendi silahini vermek gibi birşey... ufacik bir dll i sen neyle sifrelersen sifrele cozulmesi/incelenmesi cok basit olacaktir. bu da db deki sifrelenmis metinlerin kolayca cozulmesi demektir.
Sayın sadettinpolat,

şimdi UDF dll'm'de 6 adet fonksiyon var. Bunların deklarasyonları aşağıdaki şekilde :

Kod: Tümünü seç

function HasMuduruOlustur:Boolean; cdecl; export;
function HasMuduruYoket:Boolean; cdecl; export;
function SifreMuduruOlustur:Boolean; cdecl; export;
function SifreMuduruYoket:Boolean; cdecl; export;
function S(Const S, Sifre:PChar):Pchar;cdecl; export;
function D(Const S, Sifre:PChar):Pchar;cdecl; export;

Şimdi ilk iki fonksiyon THashManager'ın oluşturulması ve yok edilmesiyle ilgili. Sonraki iki fonksiyon TCipherManager'ın oluşturulması ve yok edilmesiyle ilgili. Son iki fonksiyonu FB'de rahatlıkla tanımlayabildim. Çünkü parametre alıyorlar ve sonuç döndürüyorlar.

Baştaki dört fonksiyonu şu yüzden tanımlamak zorunda kaldım: Bu dll şifreleme / deşifreleme yapabilmesi için THashManager ve TCipherManager bileşenlerine ihtiyacı var. Bunları'da dll'de tanımladığım fonksiyonlar sayesinde oluşturuyorum / yok ediyorum. Bunları bir deneme uygulamasında test ettim. Eğer oluşturma / yok etme başarılı olursa, true döndürüyor. Yani normal dll olarak kullandığımda bu dört fonksiyonda herhangi bir sorun yok. Ancak FB'de tanımlarken, bunların herhangi bir parametre almaması ve boolean tipinde veri döndürmesi nedeniyle sorun yaşadım. Yani parametre almadıkları ve boolean bir değer döndürdükleri için nasıl tanımlayacağımı bilemedim.

Gerçi boolean değeri bir integerla değiştirip, başarılıysa 1 başarısızsa 0 da döndürebilirim. Ancak yine parametre almamaları nedeniyle, FB içerisinde tanımlamakta zorluk yaşayacağım gibi geliyor.

Şimdi deşifreleme konusunda haklısınız. Başlangıçta ben de bu şekilde düşünmüştüm. Ve bu UDF'yi tanımlama sebebim aslında sıralama değil. Sıralamayı nihai olarak nasip olurda ürün haline getirmeden önce doğru sıralamada verileri kaydederek çözeceğim. Ancak alanların verilerine şifreleme uyguladığınızda, kısmi arama özelliğini kaybediyorsunuz.

Dolayısıyla, bu UDF'nin asıl amacı, VT içerisinde kısmi kelime aramayı sağlamak. Yani, atıyorum, arama edit'i içerisine "a" harfi girdiniz, içinde "a" harfi geçen bütün kayıtları geri döndürecek. Ve geri döndürdüğü kayıtlar kesinlikle deşifrelenmiş değil. Yani geri döndürdüğü kayıtlar da FB VT'ye göz atan meraklı hacker/cracker açısından anlamsız veriler olacak. Dolayısıyla burada çok büyük bir kaygı olmadığını düşünüyorum.

Ayrıca paranoya bu ya, D (deşifreleme) ve S (şifreleme) fonksiyonlarına geçtiğim şifre parametresini gerekirse, bir kaç rasgele (ancak sistem çapında sabit) olan parametreyle karıştırıp, bir kaç kere (değişik uzunluk ve değişik algoritmaları kullanan) değişik anahtarlarla şifreleme / deşifreleme yaparak, fonksiyonlara parametre olarak geçebilirim. Fonksiyonlar da aldıkları bu parametreyi export edilmeyen fonksiyonlar yardımıyla bu farklı keylerle bir kaç şifreleme / deşifreleme işlemini tersinden yaparak geçmiş olduğum gerçek keyi elde edebilirler. Dolayısıyla debugging yapan kişinin işi daha zor hale gelir.

Bu yöntemin basit bir şeklini bu dll içerisinde uyguladım. Yalnızca yapılabilirliğini görmek açısından.

Bu arada aslında S (şifreleme) fonksiyonu gereksiz: Bunu yalnızca dll'i test etmek açısından koydum. Yani deneme uygulaması içerisinde dll'nin deşifreleme yaptığını anlayabilmek için önce şifreleme yapmalı değil mi?

Ayrıca internette anti-debugging tricks diye pek çok bilgi buldum. Gerçi bunlar asm kullanıyorlar ve benim açımdan ASM Çince gibi. Dolayısıyla bir parça Çince öğrenmemin zamanı geldi gibi. :lol:

Bir de arama yapan SP'nin metni şu şekilde:

Kod: Tümünü seç

CREATE PROCEDURE LOOKUPENGLISH (
    WORDTOLOOKUP VARCHAR(240) CHARACTER SET WIN1254)
RETURNS (
    RESULTMEANINGS VARCHAR(3000) CHARACTER SET WIN1254,
    RESULTRECNOS SMALLINT,
    RESULTWORDS VARCHAR(240) CHARACTER SET WIN1254)
AS
begin
  for
  select tblenglish.sirano, tblenglish.kelime, tblenglish.anlami
  from tblenglish
  where tblenglish.kelime containing :wordtolookup
  order by tblenglish.kelime COLLATE PXW_TURK
  into :resultrecnos, :resultwords, :resultmeanings
  do suspend;
 end
Bu D (deşifreleme) fonksiyonunu biraz daha değiştireceğim. Bu yalnızca bir deneme. Muhtemelen D fonksiyonunu aşağıdaki hale getiririm.

Kod: Tümünü seç

function D(Const S, KayitS, Sifre:PChar):Int;cdecl; export;
Burada ilk sabit olan S aranan metin (ya da karakter), ikinci sabit KayitS (şifrelenmiş durumda olan ve dışarıya asla deşifrelenmiş şekli geri döndürülmeyecek olan) kaydın metni, sonuç olan Int ise, başarılı ise 1 başarısızsa 0 olacak.

Yukarıdaki SP'yi de buna göre değiştireceğim (ama nasıl yapacağım konusunda şimdilik hiç bir fikrim yok, o da ayrı mesele). Böylece UDF'yi kullanmama rağmen, SP'yi çalıştıracak kişi asla kaydın verilerinin deşifrelenmiş halini göremeyecek; yalnızca bulmuşsa, 1 bulamamışsa 0 değer elde edecek.

Belki Sayın gkimirti'nin verdiği linkteki tekniklerle birleştirip, işi daha da karmaşık hale getirebilirim. Ancak şimdilik şifreleme üzerinde odaklanacağım.

Bu arada acaba UDF dll'lerinin nasıl belleğe yüklendiği ve bellekten çıkarıldığı konusunda bir fikriniz var mı? Yani bir kere mi yoksa her çağrıldığında mı yükleniyor / çıkarılıyor?

Saygılarımla,
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Mesaj gönderen Akin_Delphi »

Akin_Delphi yazdı:Bu arada, debugging, disassembly konularıyla ilişkili olarak, şunları söylemek istiyorum. Daha önceki mesajımda, Armadillo (DR) kullanacağımı söylemiştim.

Şimdi bu Armadillo (DR) (buradan sonra ADR olarak söyleyeceğim, yazması daha kolay), uygulamaları (ki uygulamalar, yalnızca çalıştırılabilir exe dosyalarını değil aynı zamanda, dll, ActiveX, ActiveForm gibi kütüphane, hatta Delphi kütüphane dosyalarını bile içeriyor) güvenli hale getirmek üzere kullanılıyor........
Herkesten özür diliyorum. Bu armadillo konusunda yanıltıcı bilgi vermişim. Bende bulunan Armadillo (DR), bu programın Digital River tarafından dağıtılan Public (yani halka açık, herkes tarafından kullanılan) ücretsiz sürümü imiş. Dolayısıyla, şifrelemeyi ve debugger belirleme özellikleri var ancak en güçlü korumayı Pro versiyonu sağlıyor. Elimdeki public versiyon mesela delphi'yle bağlanmamı ve tek tek talimat setlerini takip etmemi engelliyor (ancak bir kaç talimatı F8'le trace edebiliyorum. Sonra döngüden çıkıyor). Ayrıca Debugger Protection seçeneğini açtığınızda garip bir durum meydana geliyor. Programı çalıştırdığınızda aynı anda ve aynı isimli iki process birden oluşuyor. Bunlardan birisini öldürürseniz, diğeri de ölüyor. Bunlardan birisine debuggerla bağlanabiliyorsunuz ve bir kaç talimatı trace etmenize izin veriyor. Diğeri ise basitçe başarısız oluyor. :shock: Ancak dokümantasyona göre Pro sürümü daha da iyi.

Bu konuda özürlerimi kabul ediniz.
Akin_Delphi yazdı: Ayrıca, bu dll'yi uygulama gömülü sunumcu (embedded server) olarak kullandığımda nasıl kullanacağım?
Bu konuda bilgi buldum. Aslında Embedded Server'ın Readme belgesinde bu konu belirtilmiş yalnızca uygulamanın alt klasörüne tıpkı dil dosyaları için yaptığımız gibi bir UDF klasörü oluşturmamız ve UDF dll'mizi oraya koymak yeterli imiş.
:D
Diğer konuları da borland'ın Haber Gruplarında sordum. Umarım yanıt alabilirim. Yanıt alırsam buraya aldığım yanıtı yazacağım.

Saygılarımla,
Kullanıcı avatarı
aslangeri
Moderator
Mesajlar: 4322
Kayıt: 26 Ara 2003 04:19
Konum: Ankara
İletişim:

Mesaj gönderen aslangeri »

s.a.
fonksiyonlar geriye boolean değer dönderdiği için fb ye udf olarak alamadım demişsin. Ancak bu fonkisyonları sen yazdın. result değerinide sen belirleyebilirsin.
true=1 false=0 şeklinde bir tanımlama yaparsan
fonkisyonlarının tipini integer (sayısal) tanımlama yeterli olacaktır gibime geliyor.
kolay gelsin.
Duyduğun Şeylerin Söylediklerim Olduğuna Eminim Ama
Anladığın Şeylerin Anlatmak İstediklerim Olduğuna Emin Değilim
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Mesaj gönderen Akin_Delphi »

aslangeri yazdı:s.a.
fonksiyonlar geriye boolean değer dönderdiği için fb ye udf olarak alamadım demişsin. Ancak bu fonkisyonları sen yazdın. result değerinide sen belirleyebilirsin.
true=1 false=0 şeklinde bir tanımlama yaparsan
fonkisyonlarının tipini integer (sayısal) tanımlama yeterli olacaktır gibime geliyor.
kolay gelsin.
a.s.
Şimdi fonksiyonların döndürdüğü tipi değiştirebilirim. Ancak sorun şu ki, ilk dört fonksiyon parametre almıyor. Ve parametre almadığı için (IBExpress aracılığıyla) FB içerisinde tanımlayamadım.

Daha olmazsa, dummy parameter (yani aslında kullanılmayan yalnızca girilen bir parametre) türü bir şey yapacağım. Çünkü dll loading unloadingle ilgili olarak Borland Haber Gruplarından da şu ana kadar bir bilgi alamadım. :(
Saygılarımla.
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Kısmi başarı ve bir sorun

Mesaj gönderen Akin_Delphi »

Tekrar merhabalar,

Oldukça gelişme elde ettim. Ve bunları sizinle paylaşmak istiyorum.

Öncelikle dll'm içerisindeki fonksiyonları değiştirerek hem tanımlamayı hem de FB içerisinde kullanmayı başardım. :lol:

Fonksiyonlar şu hale geldi:

Kod: Tümünü seç

function HasMuduruOlustur(Const Dummy: Integer):Integer; cdecl; export;
function HasMuduruYoket(Const Dummy: Integer):Integer; cdecl; export;
function SifreMuduruOlustur(Const Dummy: Integer):Integer; cdecl; export;
function SifreMuduruYoket(Const Dummy: Integer):Integer; cdecl; export;
function S(Const S, Sifre:PChar):PChar;cdecl; export;
function D(Const SAnahtarKelime, SIcindeAranan, Sifre:PChar):Integer;cdecl; export;
function D_M(Const SAnahtarKelime, SIcindeAranan, Sifre:PChar):Integer;cdecl; export;
İlk dört fonksiyonun döndürdüğü değeri integer olarak tanımladım ve parametresiz olmaları sorununu da Dummy adlı aslında kullanılmayacak bir integer parametre kullanarak hallettim.

Bu UDF dll'sinin fonksiyonlarını FB'de aşağıdaki şekilde tanımladım :

HasMuduruOlustur fonksiyonu :

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION ENCARAHMO
    INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'HasMuduruOlustur' MODULE_NAME 'ARAMA'
HasMuduruYoket fonksiyonu :

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION ENCARAHMY
    INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'HasMuduruYoket' MODULE_NAME 'ARAMA'
SifreMuduruOlustur fonksiyonu :

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION ENCARASMO
    INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'SifreMuduruOlustur' MODULE_NAME 'ARAMA'
SifreMuduruYoket fonksiyonu :

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION ENCARASMY
    INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'SifreMuduruYoket' MODULE_NAME 'ARAMA'
D fonksiyonu :

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION ENCARAMA_D
    CSTRING(240),
    CSTRING(240)
RETURNS INTEGER BY VALUE
ENTRY_POINT 'D' MODULE_NAME 'ARAMA'
S fonksiyonu aslında VT'de kullanılmayacağından ve daha sonra Dll'den çıkarılacağından dolayı hiç tanımlanmamıştır. D_M fonksiyonunu aşağıda açıklayacağım.

Bunları Arama SP'si içerisinde aşağıdaki şekilde kullanabildim:

Kod: Tümünü seç

CREATE PROCEDURE LOOKUPTESTENGENCRYPTED (
    WORDTOLOOKUP VARCHAR(240))
RETURNS (
    RESULTMEANINGS VARCHAR(3000) CHARACTER SET WIN1254,
    RESULTRECNOS SMALLINT,
    RESULTWORDS VARCHAR(240) CHARACTER SET WIN1254)
AS
DECLARE VARIABLE I INTEGER;
begin
  /* Procedure Text */
  i = encarahmo(1);
  i = encarasmo(1);
  /*suspend; */
  for
  select tblenglishencrypted.sirano, tblenglishencrypted.kelime, tblenglishencrypted.anlami
  from tblenglishencrypted
  where (encarama_d(:wordtolookup, tblenglishencrypted.kelime)=1)
  /*order by tblenglishencrypted.kelime COLLATE PXW_TURK*/
  into :resultrecnos, :resultwords, :resultmeanings
  do suspend;
  i = encarahmy(1);
  i = encarasmy(1);
end

Kod: Tümünü seç

  i = encarahmo(1);
  i = encarasmo(1);
ve

Kod: Tümünü seç

  i = encarahmy(1);
  i = encarasmy(1);
kısımları dll içerisindeki THashManager ve TCipherManager bileşenlerini başlangıçta döngünün dışında oluşturmamı ve sonda yine döngünün dışında yok etmemi sağlıyor. Bu sayede atıyorum 10,000 kaydım var, bileşenleri 10,000 kere oluşturup 10,000 kere yok etmemiş oluyorum. Ayrıca parametre olarak geçtiğim (1) değerinin de hiç bir önemi yok.

SP içerisinde i adlı aslında gereksiz olan bir değişken tanımlamak zorunda kaldım çünkü oluşturma ve yoketme fonksiyonlarını bir şeye eşitlemezsem FB (IBExpert) basitçe yapmayı reddediyor.

UDF dll'si sayesinde SP, aramak için kullanılan anahtar kelime karşılığında uygun kayıtları (şifrelenmemiş olarak) doğru bir şekilde döndürüyor.

Şimdi yaptıklarımı paylaştıktan sonra, takıldığım bir konu var, o konuda yardımcı olursanız sevinirim. :(

Şimdi D fonksiyonunu ayrıca kelimelerin anlamları içerisinde anahtar kelime aramak için de başka bir SP içerisinde kullanıyorum. Ancak anlamlar alanı 3000 karakter uzunluğunda. Çünkü yalnızca anlamları değil ayrıca yorumları, nüansları vs.'yi de içeriyor. Bu nedenle uzun olmak zorunda.

Şimdi D fonksiyonunun parametreleri 240 büyüklüğünde ayarlandığından aynı fonksiyon tanımlamasını anlamları arayan SP içerisinde kullandığımda. IBExpert (ve tabii ki uygulama) bazen aşağıdaki hata mesajını veriyor:

Arithmetic overflow or divisionby zero occurred vs. vs. (yani aritmetik taşma ya da sıfıra bölme meydana geldi).

Dolayısıyla bu durumu önlemek için, aşağıdaki şekilde bir de D_M fonksiyonu tanımladım: D_M fonksiyonunun dll içerisindeki içeriği ve kodu tamamen D fonksiyonu ile aynı.

Bu D_M fonksiyonunu FB'de aşağıdaki şekilde tanımladım:

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION ENCARAMA_D_M
    CSTRING(3000),
    CSTRING(3000)
RETURNS INTEGER
ENTRY_POINT 'D_M' MODULE_NAME 'ARANA'
Ancak bu UDF'yi SP içerisinde kullanmaya kalktığımda (yani SP içerisindeki değişikliği yapıp derlemeye çalıştığımda), SP derlenmiyor ve değişikliği yapamıyorum. Aşağıdaki hatayı veriyor.
Unsuccessful execution caused by a system error that precludes successful execution of subsequent statements.
Access to UDF library "ARAMA.DLL" is denied by server administrator.

Changes will be rolled back.
Yani
Aşağıdaki ifadelerin başarılı bir şekilde yerine getirilmesini önleyen bir sistem hatası tarafından çalıştırma başarısızlığı meydana getirildi.
"ARAMA.DLL" UDF kütüphanesine erişim sunumcu yöneticisi tarafından reddedildi.

Değişiklikler geri alınacak.
Bu ne demektir? Yani diğer fonksiyonları rahatlıkla kullanıyor. Ancak bun da arıza çıkarıyor. Bir fikri olan var mıdır? Saygılarımla,
Kullanıcı avatarı
aslangeri
Moderator
Mesajlar: 4322
Kayıt: 26 Ara 2003 04:19
Konum: Ankara
İletişim:

Mesaj gönderen aslangeri »

s.a.
tam emin olmamakla beraber cstring(3000) parametresinden dolayı yapıyor olabilir kanaatindeyim.
Parametreleri değiştirip (3000 i küçültüp)denermisiniz. Sorunun kaynağı tespit edilirse çözüm kolaylaşır.
kolay gelsin.
Duyduğun Şeylerin Söylediklerim Olduğuna Eminim Ama
Anladığın Şeylerin Anlatmak İstediklerim Olduğuna Emin Değilim
Cevapla