Konuyu Paylaş : facebook gplus twitter

Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Delphi Rijndael Encryption/Decryption Kütüphanesi
#1
Merhaba "Delphi Can"lar,

Kendi projelerimde de kullandığım, Library projesi olarak (.dll) yazmış olduğum, Delphi projelerinizde Encryption/Decryption işlemlerinizi yapabileceğiniz, Rijndael - CBC - 128 bit şifreleme kullanan, kolay ve kullanışlı bir projeyi sizlerle paylaşıyorum.

Veri tabanına, ini dosyalara, vs. bazı bilgileri şifreleyip yazmak ve okurken de sadece biz çözebilmek isteriz. Bu kütüphanede aynı metin her şifrelendiğinde kafa karıştırmak için farklı bir şifrelenmiş metin oluşturulur. Ama çözerken aynı sonuca ulaşırız. Bu projeyi derlediğimizde Rijndael.dll oluşturulur. Sonrasında bu dll' i projelerinize import ederek çok kolay bir şekilde kullanabilirsiniz. Ayrıca, şifreleme ve çözme metodlarına 2. parametre olarak 12 karakterli bir şifre göndererek kullanılmakta. Bu şekilde her projeyi farklı bir şifreleme yapısıyla kullanabilirsiniz.

Rijndael.dpr içeriği;
library Rijndael;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  SysUtils,
  Classes,
  DECCipher,
  Dialogs,
  DECUtil, DECHash, DECFmt;

var
  ACipherClass: TDECCipherClass = TCipher_Rijndael;
  ACipherMode: TCipherMode = cmCBCx;
  AHashClass: TDECHashClass = THash_Whirlpool;
  ATextFormat: TDECFormatClass = TFormat_Mime64;
  AKDFIndex: LongWord = 1;

{$R *.res}
function StrToHex(const Value: string): string;
var
  I: Integer;
begin
  Result := '';
  for I := 1 to length(value) do
    result := result + IntToHex(Ord(Value[I]), 2);
end;

function HexToStr(const Value: string): string;
var
  I: Integer;
begin
  Result := '';
  for I := 1 to length(value) do
  begin
    if ((I mod 2) = 1) then
    begin
      result := result + Chr(StrToInt('0x'+ Copy(Value, I, 2)));
    end;
  end;
end;


function encode (const source: pchar; var out: pchar; key: pchar) : boolean;
var
  aes: TCipher_Rijndael;
begin
  aes := TCipher_Rijndael.Create;
  aes.Init(key);
  out := pchar(StrToHex(aes.EncodeBinary(HexToStr(source))));
end;

function decode (const source: pchar; var out: pchar; key: pchar) : boolean;
var
  aes: TCipher_Rijndael;
begin
  aes := TCipher_Rijndael.Create;
  aes.Init(key);
  out := pchar(StrToHex(aes.DecodeBinary(HexToStr(source))));
end;

function Encrypt(const AText: WideString; APassword : WideString): WideString;
var
  // APassword : WideString;
  ASalt: Binary;
  AData: Binary;
  APass: Binary;
begin
  if length(AText) = 0 then begin
    result := '';
    exit;
  end;

  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := RandomBinary(16);
    APass := ValidHash(AHashClass).KDFx(APassword[1], Length(APassword) * SizeOf(APassword[1]), ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    SetLength(AData, Length(AText) * SizeOf(AText[1]));
    Encode(AText[1], AData[1], Length(AData));
    Result := ValidFormat(ATextFormat).Encode(ASalt + AData + CalcMAC);
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(APass);
  end;
end;

function Decrypt(const AText: WideString; APassword : WideString): WideString;
var
  // APassword : WideString;
  ASalt: Binary;
  AData: Binary;
  ACheck: Binary;
  APass: Binary;
  ALen: Integer;
begin
  if length(AText) = 0 then begin
    result := '';
    exit;
  end;

  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := ValidFormat(ATextFormat).Decode(AText);
    ALen := Length(ASalt) - 16 - BufferSize;
    AData := System.Copy(ASalt, 17, ALen);
    ACheck := System.Copy(ASalt, ALen + 17, BufferSize);
    SetLength(ASalt, 16);
    APass := ValidHash(AHashClass).KDFx(APassword[1], Length(APassword) * SizeOf(APassword[1]), ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    SetLength(Result, ALen div SizeOf(AText[1]));
    Decode(AData[1], Result[1], ALen);
    if ACheck <> CalcMAC then
      raise Exception.Create('Invalid data');
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(ACheck);
    ProtectBinary(APass);
  end;
end;

exports Encrypt, Decrypt;

begin
end.

Projenin tamamı Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol yer almaktadır. 

Projeye kütüphaneyi ekleme;
(implementation satırı üstüne aşağıdaki iki satır eklenir.)

 function Encrypt(const AText: WideString; APassword : WideString): WideString; external 'Rijndael.dll';

 function Decrypt(const AText: WideString; APassword : WideString): WideString; external 'Rijndael.dll';

implementation

Kullanım örneği;

var
 _sifre : WideString;
 _sifrelenmis : WideString;
 _cozulmus : WideString;
begin
 _sifre = '123';
 _sifrelenmis := Encrypt(sifre,'852357jMl???');
 _cozulmus := Decrypt(_sifrelenmis,'852357jMl???');

 showmessage(_sifrelenmis);
 showmessage(_cozulmus);
end;

Umarım faydalı olur...
Cevapla
#2
Merhaba,
Öncelikle emeğinize sağlık. Ufak bir sorum olacak; bu projeyi derleyebilmek için 3. parti bileşenlere ihtiyaç var mı? (Varsa hangileri)
Cevapla
#3
Merhaba,

Anladığım kadarıyla "Delphi Encryption Compendium" bileşen setini kullanıyor. Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol adresinden indirebilirsiniz.

Ama kodun genelinde ciddi sorunlar var:
1. Bazı fonksiyonlarda create edilen nesneler free edilmiyor. Aşağıdaki fonksiyona bakın:

function encode (const source: pchar; var out: pchar; key: pchar) : boolean;
var
 aes: TCipher_Rijndael;
begin
 aes := TCipher_Rijndael.Create;
 aes.Init(key);
 out := pchar(StrToHex(aes.EncodeBinary(HexToStr(source))));
end;

Benzer sorun decode fonksiyonunda da var.

2. DLL dosyasının hemen tepesindeki commentte yazılanlar dikkate alınmamış. Bu kütüphaneyi kullanırken anlamsız bellek hataları ile karşılaşabilirsiniz. Commentte yazılanları kabaca tercüme edecek olursa:
"DLL'nin bellek yönetimi ile ilgili önemli not: Eğer bu DLL'de export edilen fonksiyon ve procedure'lerden herhangi birisi string veri tipinde parametre alıyor veya sonuç döndürüyorsa hem DLL'in hem de projenizin ilk unit'i ShareMem olmalıdır." 
Daha sonraki satırları birebir çevirmeyim, ama ShareMem ekleyince BORLNDMM.DLL dosyasını da programınız ile dağıtmanız gerekiyor. Eğer bunu yapmak istemiyorsanız, string veri tipini değil, PChar veya Shortstring kullanmanız gerekiyormuş.

3. Son olarak böyle bir DLL dosyasına gerçekten ihtiyaç var mı? Ben olmadığını düşünüyorum. Zaten 3. parti bir bileşen kullanılıyor. Bu DLL dosyasını ayrı bir helper unit olarak yazsak ve bunu projemize eklesek, programımızı dağıtmak için bir de DLL ile uğraşmayacağız ve program Single Exe olabilecek ki bu da Delphi'nin üstün yanlarından birisi.

4. Bu biraz bireysel, ama lütfen şu "with" ifadesini kullanmayın. Tamam, yazarken kolay gibi geliyor ama yazarken kurtulduğunuz iki harf yüzünden (with için kullandığınız ifadeyi bir harfli bir değişkene atayın ve sonuna da bir "." koyun. Toplamda iki harf etti) hem çok daha fazla hata çıkıyor ve hem de DEBUG etmek büyük bir eziyet haline geliyor. Kısaca "with" kullanmayın ve henüz yolun başındaysanız, alışkanlık haline gelmeden vazgeçin.

İyi çalışmalar
Cevapla
#4
(04-12-2017, Saat: 08:15)Bahadir.Alkac Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlMerhaba,

Anladığım kadarıyla "Delphi Encryption Compendium" bileşen setini kullanıyor. Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol adresinden indirebilirsiniz.

Ama kodun genelinde ciddi sorunlar var:
1. Bazı fonksiyonlarda create edilen nesneler free edilmiyor. Aşağıdaki fonksiyona bakın:

function encode (const source: pchar; var out: pchar; key: pchar) : boolean;
var
 aes: TCipher_Rijndael;
begin
 aes := TCipher_Rijndael.Create;
 aes.Init(key);
 out := pchar(StrToHex(aes.EncodeBinary(HexToStr(source))));
end;

Benzer sorun decode fonksiyonunda da var.

2. DLL dosyasının hemen tepesindeki commentte yazılanlar dikkate alınmamış. Bu kütüphaneyi kullanırken anlamsız bellek hataları ile karşılaşabilirsiniz. Commentte yazılanları kabaca tercüme edecek olursa:
"DLL'nin bellek yönetimi ile ilgili önemli not: Eğer bu DLL'de export edilen fonksiyon ve procedure'lerden herhangi birisi string veri tipinde parametre alıyor veya sonuç döndürüyorsa hem DLL'in hem de projenizin ilk unit'i ShareMem olmalıdır." 
Daha sonraki satırları birebir çevirmeyim, ama ShareMem ekleyince BORLNDMM.DLL dosyasını da programınız ile dağıtmanız gerekiyor. Eğer bunu yapmak istemiyorsanız, string veri tipini değil, PChar veya Shortstring kullanmanız gerekiyormuş.

3. Son olarak böyle bir DLL dosyasına gerçekten ihtiyaç var mı? Ben olmadığını düşünüyorum. Zaten 3. parti bir bileşen kullanılıyor. Bu DLL dosyasını ayrı bir helper unit olarak yazsak ve bunu projemize eklesek, programımızı dağıtmak için bir de DLL ile uğraşmayacağız ve program Single Exe olabilecek ki bu da Delphi'nin üstün yanlarından birisi.

4. Bu biraz bireysel, ama lütfen şu "with" ifadesini kullanmayın. Tamam, yazarken kolay gibi geliyor ama yazarken kurtulduğunuz iki harf yüzünden (with için kullandığınız ifadeyi bir harfli bir değişkene atayın ve sonuna da bir "." koyun. Toplamda iki harf etti) hem çok daha fazla hata çıkıyor ve hem de DEBUG etmek büyük bir eziyet haline geliyor. Kısaca "with" kullanmayın ve henüz yolun başındaysanız, alışkanlık haline gelmeden vazgeçin.

İyi çalışmalar

Belki alakasız olacak kusura bakmayın ama, mesajınız bana programlama hayatına C# ya da ona benzer otomatik hafıza yönetimi yapan programlama dilleri ile başlayanların; diğer dillerde ne kadar da zorlanacağını ve hatalı kodlar yazacağını hatırlattı. Oysa Delphi ile programlamaya başlayan birisi, try/finally kullanmaya da alışmış ise; diğer dillerde hafıza yönetimi açısından hiç de zorlanmaz.

Programlama disiplini önemli vesselam.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#5
(04-12-2017, Saat: 00:14)uparlayan Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlMerhaba,
Öncelikle emeğinize sağlık. Ufak bir sorum olacak; bu  projeyi derleyebilmek için 3. parti bileşenlere ihtiyaç var mı? (Varsa hangileri)

Merhaba,

Evet.  Bahadır Bey cevaplamış.  "Delphi Encryption Compendium" gerekiyor.

(04-12-2017, Saat: 08:15)Bahadir.Alkac Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlMerhaba,

Anladığım kadarıyla "Delphi Encryption Compendium" bileşen setini kullanıyor. Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol adresinden indirebilirsiniz.

Ama kodun genelinde ciddi sorunlar var:
1. Bazı fonksiyonlarda create edilen nesneler free edilmiyor. Aşağıdaki fonksiyona bakın:

function encode (const source: pchar; var out: pchar; key: pchar) : boolean;
var
 aes: TCipher_Rijndael;
begin
 aes := TCipher_Rijndael.Create;
 aes.Init(key);
 out := pchar(StrToHex(aes.EncodeBinary(HexToStr(source))));
end;

Benzer sorun decode fonksiyonunda da var.

2. DLL dosyasının hemen tepesindeki commentte yazılanlar dikkate alınmamış. Bu kütüphaneyi kullanırken anlamsız bellek hataları ile karşılaşabilirsiniz. Commentte yazılanları kabaca tercüme edecek olursa:
"DLL'nin bellek yönetimi ile ilgili önemli not: Eğer bu DLL'de export edilen fonksiyon ve procedure'lerden herhangi birisi string veri tipinde parametre alıyor veya sonuç döndürüyorsa hem DLL'in hem de projenizin ilk unit'i ShareMem olmalıdır." 
Daha sonraki satırları birebir çevirmeyim, ama ShareMem ekleyince BORLNDMM.DLL dosyasını da programınız ile dağıtmanız gerekiyor. Eğer bunu yapmak istemiyorsanız, string veri tipini değil, PChar veya Shortstring kullanmanız gerekiyormuş.

3. Son olarak böyle bir DLL dosyasına gerçekten ihtiyaç var mı? Ben olmadığını düşünüyorum. Zaten 3. parti bir bileşen kullanılıyor. Bu DLL dosyasını ayrı bir helper unit olarak yazsak ve bunu projemize eklesek, programımızı dağıtmak için bir de DLL ile uğraşmayacağız ve program Single Exe olabilecek ki bu da Delphi'nin üstün yanlarından birisi.

4. Bu biraz bireysel, ama lütfen şu "with" ifadesini kullanmayın. Tamam, yazarken kolay gibi geliyor ama yazarken kurtulduğunuz iki harf yüzünden (with için kullandığınız ifadeyi bir harfli bir değişkene atayın ve sonuna da bir "." koyun. Toplamda iki harf etti) hem çok daha fazla hata çıkıyor ve hem de DEBUG etmek büyük bir eziyet haline geliyor. Kısaca "with" kullanmayın ve henüz yolun başındaysanız, alışkanlık haline gelmeden vazgeçin.

İyi çalışmalar

Merhaba,

Uyarılar ve bilgilendirme için teşekkürler.

1. Dikkatsizlik ve aceleden.
2. Farkettim ama yine aceleden ilgilenmedim. 
3. Normalde bu şekilde çalışıyor. Delphi 2010' da yazıp diğer (XE8, XE 10.2) sürümlerde sorun yaşayınca böyle bir kullanım ihtiyacı doğdu. 
4. Bu da yoğurt yiyiş tarzı diyelim Smile

1. ve 2. maddeleri düzeltiyorum...
Cevapla

Konuyu Paylaş : facebook gplus twitter



Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Delphi'de Indy SMTP ile e-mail gönderme. (GMail, Yandex, Yahoo vb.) csunguray 6 388 09-04-2018, Saat: 02:34
Son Yorum: dkadir
  Delphi Direktif Kullanımı narkotik 3 189 12-03-2018, Saat: 00:44
Son Yorum: mcuyan
  Delphi'de AES şifreleme (AES128, AES192, AES256) csunguray 1 164 20-02-2018, Saat: 13:50
Son Yorum: klavye
  Delphi Firemonkey Local İp Adresi Öğrenme esrehmaan 12 1.557 15-02-2018, Saat: 15:15
Son Yorum: elixir84
  Delphi'de Veritabanı İle Kullanıcı Ekleme hyperxman 0 166 08-02-2018, Saat: 01:18
Son Yorum: hyperxman



Konuyu Okuyanlar: 1 Ziyaretçi