Yazıyı, birkaç kütüphaneyi anlattığım upuzun bir yazı olarak yayınlamaktansa üç ayrı bölümde yayınlamaya karar verdim. Böylesinin hem benim yazmam açısından hem de okurun takip edebilmesi açısından daha kolay olacağını düşünüyorum. Yazıda başlıkta da yazdığım gibi unrar kütüphanesini kullanarak ve
MPI (Message Passing Interface) kütüphanesiyle birleştirerek kendi
yazdığım paralel bir şifre bulucuyu anlatacağım. Ancak sonraki yazıları ne zaman yayınların bunu iş yoğunluğu gösterecek.
Bölüm1: Unrar kütüphanesi
Unrar kütüphesinin
iyi bir dökümantasyonu yok ancak ben internette bulduğum bir belgeyi kısmen Türkçe'ye çevireceğim. Merak edenler bağlantıyı kullanarak belgenin orjinaline ulaşabilirler.
www.rarlabs.com'da linux için rar programı kaynak koduyla birlikte dağıtılıyor. Kodu satır satır incelemedim ama .rar dosyaları kişisel kodlarda kullanmak için Windows altında unrar.dll yada linux altında unrar.so adında rar açıcı (unrar) kütüphanesi geliyor. Ben kendi kodumda da bu kütüphaneyi kullandım. Kütüphane fonksiyonları kısaca şöyle:
- RAROpenArchive: Prototipi,
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData)
şeklindedir. Değişkenlerin ve yapıların tanımları unrar paketindeki dll.hpp dosyasında ve yukarıda verdiğim linkte var. Yapıda iki tane önemli alan var. Birisi char *ArcName diğeri de UINT OpenMode. İlki açılacak arşivin adını ve yolunu tutuyor. Diğeri de hangi modda açılacağını. OpenMode için iki tane öntanımlı değer var. Birisi RAR_OM_LIST diğeri de RAR_OM_EXTRACT. Listeleme modu biraz daha hızlı ama adı üzerinde sadece listelemek için. Hata durumunda NULL handle döndürüyor.
- RARCloseArchive: Prototipi,
şeklindedir. RAROpenArchive'den alınan handle ile dosya kapatılır.
- RARReadHeader: Prototipi,
int PASCAL RARReadHeader(HANDLE hArcData, struct RARHeaderData *HeaderData)
şeklindedir. Açılmış arşiv dosyanın içerisindeki ilk dosyanın başlığı okunur. Dosyalara ait başlık bilgileri önemlidir çünkü dosyanın şifrelenip şifrelenmediği bilgisi başlıktan alınır. Fonksiyon arşiv dosyası açıldıktan hemen sonra çağırılır. Eğer dosya adları şifrelenmişse fonksiyon ERAR_MISSING_PASSWORD hatasını döndürür.
.rar dosyalarda iki tür şifreleme yapılabilir. Birisi dosya dosya şifreleme, diğeri de tüm arşivin dosya adlarıyla birlikte şifrelemesi. İlkinde istenirse bazı dosyalara şifre verip bazıları açık olarak saklanabilir. Bunun dezavantajı şifrelerin bulunabilir olmasıdır. Örnegin arşivin içerisinde "Alphaville - Big in Japan.mp3" bulunduğunu varsayalım. Şifreyi bulmak isteyen kişi aynı dosyayı internetten bulabilirse (dosya boyutundan aynı olup olmadığı anlaşılabilir) .rar içerisinde şifrelenerek sıkıştırılmış veriyi şifrelemeden sıkıştırılmış veriyle karşılaştırarak şifreyi bulabilir. Arşivdeki diğer dosyaların şifresi aynıysa diğer dosyalar da açılabilir. Bundan korunmanın yolu dosya adlarıyla birlikte tüm arşivi şifrelemektir. İlk durumda WinRAR ile açıldığında dosya adları listelenecek ve şifrelenmiş olanlar yanlarında * ile görüntülecek; ikinci durumda WinRAR ile açmaya kalkar kalkmaz şifre soracak, içeriği göstermeyecektir.
Arşiv içerisindeki her dosya için RARReadHeader çağırılır. Son dosyadan sonra bu fonksiyon çağırıldığında ERAR_END_ARCHIVE döndürür. Arşivin geneli değil de dosya dosya şifreleme yapılmışsa RARReadHeader hata döndürmez onun yerine RARHeaderData'nın Flags alanındaki bir biti set eder. Bir dosyanın başlığı okunduktan sonra RARProcessFile çağırılarak bir sonraki dosyaya geçilir.
- RARProcessFile: Prototipi,
int PASCAL RARProcessFile(HANDLE hArcData, int Operation, char *DestPath, char *DestName)
şeklindedir. Başlığı RARReadHeader ile okunan dosyanın ne yapılacağı bu fonksiyonun Operation argumanıyla belirlenir. Operation için tanımlı değerler RAR_SKIP, RAR_TEST ve RAR_EXTRACT biçimindedir. Eğer dosya RAR_OM_LIST modunda açılmışsa bütün değerler RAR_SKIP'e eşdeğerdir.
.rar dosyaların .zip'lere göre önemli üstünlüğü katı arşiv (solid archive) oluşturulabilmesi. Arşivlerde dosyalar tek tek sıkıştırılabileceği gibi hepsi bir bütün olarak bir dosyada toplanıp sıkıştırılabilir. Linux'ta gzip de bzip de ayrı ayrı dosyaları sıkıştırmaz yalnızca karakter dizisini (stream) sıkıştırır. Dosyalar tek bir .tar dosya içerisinde birleştirilir (tar sıkıştırmaz) sonra gzip yada bzip ile sıkıştırılır. Benzeri katı arşiv .rar dosyalarda da geçerlidir. Katı arşivin avantajı biraz daha fazla sıkıştırabilir olmasıdır. Örneğin .jpg dosyalar zaten sıkıştırılmış olduklarından ayrı ayrı fazla sıkışmazlar ancak benzer header verilerine sahip .jpg'ler tek bir dosyada birleştirilirse benzer header'lar kolayca sıkıştırılır. Katı arşivin avantajı daha fazla sıkıştırılabilmesi olsa da arşivden bir dosya açmak için kendisinden önce gelen bütün dosyaların açılması gerekmektedir.
Katı arşiv dosyaları RAR_OM_EXTRACT modunda açılmışsa RAR_SKIP verildiğinde kendisinden önceki dosyalar yine açılır, bu nedenle katı arşivlerde dosyalara bakmak biraz daha zaman alır.
Eğer tek bir dosya şifrelenmişse açılmaya çalışıldığı zaman fonksiyon ERAR_BAD_DATA döndürür, oysa bu hata CRC hatasına karışılık gelir. Bunun açıklaması büyük olasılıkla şu şekildedir. Dosya sıkıştırılırken CRC'si hesaplanarak yazılır ancak sıkıştırılmış veri çıktısı girilen şifre üzerinden bir işlemden daha geçirilir. Basit olması açısından bunu XOR olarak kabul edelim. Sıkıştırılmış veri, açma (decompression) sırasında girilen şifre üzerinden XOR'lanıp sonra açma algoritmasına sokulur. Sonuçta çıkan verinin CRC'si eğer şifre yanlışsa kaydedilmiş CRC ile uyuşmayacaktır. Şifrenin ayrı olarak arşivin içerisinde kaydedilmeyip karakter dizisi üzerinden işleme sokulmasından dolayı .rar şifreleri yalnızca sözlük tabanlı saldırılarla bulunabilir. Hiçbir dosyasının bilinmediği bir arşiv dosyasın içeriğinden şifresinin bulunması olanaksızdır.
- RARSetPassword: Prototipi,
void PASCAL RARSetPassword(HANDLE hArcData, char *Password)
şeklindedir. Bu şifreli arşivler için en önemli fonksiyondur. Kullanımı prototipinden anlaşılacağı üzere basittir.
Hiç yorum yok:
Yorum Gönder