C++ Base64 Encode ve Decode

24 Kas 2016 · 7 dk okuma süresi

Özellikle mail eklerini gönderirken yararlanılan bir kodlama(encoding) yöntemi olan Base64 kodlaması; ikili(binary) verinin ASCII standarlarındaki metin dosyasına dönüşümünü sağlar. İlk olarak Base64 hakkında bazı noktaları anlattıktan sonra C++ dili ile Base64 encode ve decode işlemlerini gerçekleştireceğiz.

Base64 kodlamasının temel amaçlarından biri maillere attachment(ek) eklenebilmesini sağlamaktır. Çünkü, mail göndermemizi sağlayan SMTP(Simple Mail Transfer Protocol) protokolü resim, müzik, video, uygulama gibi binary türündeki verileri göndermek için uygun bir protokol değildir. Dolayısıyla MIME(Multipurpose Internet Mail Extensions) denilen bir standartla birlikte Binary türündeki veriler Base64 ile kodlanıyor ve SMTP protokolü üzerinden gönderilebiliyor. Mail gönderildikten sonra karşı tarafta Binary türündeki veriler yine Base64 standartlarına göre decode ediliyor ve gerekli formata dönüştürülüyor.

Base64 kodlaması temel olarak bir verinin farklı sembollerle ifade edilmesidir. Bu semboller içinde 64 farklı karakterin bulunduğu karakter dizisidir. Zaten kodlamaya verilen isim bu karakterlerin sayısından gelmektedir. Bahsi geçen bu 64 karakter aşağıdaki gibidir:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

Yukarıdaki karakterlere dikkat ederseniz hepsi ASCII standartlarında karakterlerdir ve dolayısıyla her karakterin ASCII karşılığı olarak ifade edilen sayısal karşılığı vardır. Örneğin A karakterinin ASCII karşılığı 65 iken a karakterinin karşılığı 97’dir.  Aşağıda tabloda karakterlerin, başta ASCII olmak üzere farklı tabandaki karşılıkları verilmiştir:

ascii_table

Şimdi adım adım Base64 kodlamasının nasıl yapıldığını inceleyelim ardından kodlama bölümüne geçeceğiz.

  1. Base64 ile kodlanacak veri alınır.
  2. Alınan bu verideki her karakterin ASCII tablosundaki değeri alınır. (örneğin f harfinin kodu 70'tir. )
  3. ASCII tablosundan alınan değerlerin ikilik tabandaki karşılıkları alınır. (örneğin 2. adımda bulduğumuz f karakterinin ASCII karşılığı olan 70'in ikilik tabandaki değeri ‭0100 0110‬'dir.)
  4. Oluşan bu ikilik tabandaki veriyi 6 bitlik gruplara böleceğiz. Çünkü 6 bitlik bir verinin alabileceği en büyük değer 63'tür. Sıfır sayısını da işin içine katınca toplamda 64 taneye denk gelir bu da Base64 kodlamasında kullanılan karakterlerin sayısına eşittir.
  5. İkilik tabandaki verinin 6 bitlik gruplara tam bölünmesi gerekiyor. Bu nedenle 6 bitlik gruplara tam bölünmediği durumlarda 6 bitlik gruplara tam bölünecek şekli alana kadar her biri sıfır olmak üzere ekstra 8 bit(1 byte) ekliyoruz. Sonuç olarak eklenilen yeni bytelarla birlikte toplam bit miktarı 6'ya tam bölünecek şekilde olmalıdır. Tabi bu hesap işlemi farklı yollarla da yapılabilir ama sonuç aynı olmalıdır. Örneğin toplam bit sayısının 6'ya tam bölünmesi dışında 24 ve 24'ün katına eşitlenene kadar 1 byte eklersek yine aynı sonuca ulaşırız. Örneğin birazdan göreceğiniz C++ örneğinde daha farklı bir formül kullandım.
  6. 6 Bitlik gruplara böldüğümüz her verinin Onluk tabandaki karşılığını buluyoruz. Bulduğumuz bu değer 0-63 arasında olacaktır dolayısıyla bu bulunan sayı bize Base64 karakterlerinin bulunduğu diziden hangi karakteri alacağımız verir. Örneğin elimizde 3Byte(24Bit)'lık veri var ve bu veriyi 6 Bitlik gruplara böldük. Toplamda 4 tane 6 Bitlik grubumuz oldu ve her grup bize 0-63 arasında değer verecek bizde bu değerleri birleştirince Base64 ile kodlanmış veriyi elde edeceğiz.
  7. Son olarak verimizin sonuna eklediğimiz ekstra Byte miktarı kadar eşittir(=) işareti koyuyoruz. Eğer verimiz ekstra Bayt eklemeden uygun formatı sağlamışsa eşittir kullanmamıza gerek kalmayacaktır.

Şimdi adım adım anlatılanı biraz gözünüzde canlandırmak için aşağıdaki tabloyu inceleyebilirsiniz:

İçerik a b
ASCII 97 (0x61) 98 (0x62) 0 (0x00)
Bit Kalıbı 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0
Base64 Index 24 22 8 0
Base64-encoded Y W I =

Tabloda 2 karakterden oluşan “ab” şeklindeki string, Base64 ile kodlandıktan sonra “YWI=” şekline dönüşmüştür. Dikkat ederseniz ekstradan 1Byte eklendiği için kodlanmış verinin sonunda 1 tane eşittir(=) karakteri var.

Eklenecek ekstra Byte miktarı maksimum 2 tanedir. Dolayısıyla kodlanmış verinin sonuna gerekiyorsa 1 veya 2 tane eşittir(=) karakteri eklenebilir. Eklenecek eşittir miktarına Padding dersek Padding değeri veri uzunluğuna bağlı olarak 0-1-2-0-1-2 şeklinde tekrarlar.

Şimdi yukarıdaki tablonun farklı bir örneğini yapalım:

İçerik a b c
ASCII 97 (0x61) 98 (0x62) 99 (0x63)
Bit Kalıbı 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 1
Base64 Index 24 22 8 35
Base64-encoded Y W J j

Dikkat ederseniz burada ekstra Byte eklemeye ihtiyaç olmadan gereken format sağlandı dolayısıyla kodlanmış verinin sonunda Padding görevi gören eşittir(=) sembolü yok.

Şimdi Base64 Encode ve Decode işlemimizi gerçekleştirecek C++ örneğimize geçelim. Örneği daha rahat görebilmek veya projeyi doğrudan indirmek için https://github.com/firateski/cppBase64EncodeDecode adresinden GitHub üzerine eklediğim projeye gidebilirsiniz.

Gerekli açıklamaları kodlar üstünde yaptım ama yine de sorunuz olursa yorum kısmında veya iletişim bölümünden sorabilirsiniz.


ASCII Tablosu Kaynağı: www.asciitable.com