Base64 Encoding

ကျောင်းသားဘဝတုန်းက Encoding အကြောင်းတွေ သင်တော့ အိပ်ငိုက်နေခဲ့ဖူးပါတယ်။နားမလည်လို့ပါ။
လုပ်ငန်းခွင်ရောက်တော့လဲ သူက ကင်းမရပြန်ပါဘူး... ထပ်တွေ့ပါတယ်။
ဒီတော့ နားလည်အောင်ကြိုးစားရတော့တာပေါ့။
အခု လည်း ကိုယ်သိထားတာတွေ ကိုယ့်အတွေ့အကြုံတွေကို ပြန်ပြောပြဖို့ အချိန်ရောက်ပြီလို့ ယူဆမိပါတယ်။
ဒါကြောင့် Base64 Encoding ဆိုတာကို နည်းနည်း ပြန်မျှလိုပါတယ်။
သူ့ကို Multipurpose Internet Mail Extensions (MIME) အတွက်လဲ သုံးပါတယ်။
Email တွေ Network ပေါ်မှာ ဖြတ်သန်းသွားလာတဲ့အခါမှာ Base64 Encoding ကို သုံးတယ်ပေါ့ဗျာ။
နောက်ပြီး HTTP Based Basic Authentication တွေမှာလည်း သူ့ကို သုံးတယ်ဗျ။
ဘယ်လိုသုံးတာလဲ ဆိုတော့ Web Server တွေက username , password တောင်းတာ တွေ့ဖူးကြမယ်ထင်တယ်။ အဲ့လိုသုံးတာပေါ့။
ကဲ...ထားပါတော့ ပြောချင်တာက တော့ Base64 Encoding ဟာ အရေးပါတယ်ဆိုတာလေးသိစေချင်တာပါ။

စမယ်ဗျာ...
Base64 က Character တလုံးကို 6 bit ယူထားတဲ့ US-ASCII Charater Set ထဲက Character (၆၅) လုံးကို သုံးထားတယ်။
ဥပမာအနေနဲ့ပြောရမယ်ဆိုရင် m ဆိုတဲ့ Character ကိုယူမယ်ဆိုပါတော့။ m ရဲ့ base64 တန်ဖိုးက (၃၈) ဗျာ။
ဒီတန်ဖိုးဘယ်ကရလဲ မေးစရာရှိတယ်... Base64 Alpahbet Chart ဆိုတာကနေရတယ်ဗျ။ သူ့မှာ သက်ဆိုင်ရာ Character တလုံးချင်းစီအတွက် တန်ဖိုးတွေ ပါရှိပါတယ်။
ဒီတော့ Character တလုံးအတွက် Base64 တန်ဖိုးလိုချင်တဲ့အခါတိုင်း Base64 Chart ကို ကြည့်ရမယ်ပေါ့။
ကဲ.... m ဆိုတာကို ၃၈ လို့ သိထားပြီး သူ့ကို binary ပုံစံပြောင်းမယ် 100110 ရတယ်။

နောက်တမျိုးပြောကြည့်မယ်ဗျာ...

mne ဆိုတဲ့စာလုံးကို encode လုပ်ကြည့်တာပေါ့။

mne ကို ပထမဆုံး base64 decimal value ပြောင်းမယ်။

m = 109
n = 110
e = 101

ဒီတော့ mne က 109 110 101 ဖြစ်သွားပြီနော်...
တခါထပ်ပြီး binary value ပြောင်းမယ်။

109     110     101 = 01101101     01101110     01100101

8-bits ၃ ခု ပါတဲ့ binary value ရမယ်ဗျာ။ အဲ့ဒါကို 24-bit stream ဖြစ်အောင် တဆက်တည်းချရေးလိုက်ဗျာ။

011011010110111001100101 ဒီလိုရမယ်။

ရလာတဲ့ 24-bit binary value ကို ညာဖက် ကနေစပြီး 6 bits စီ ခွဲထုတ်မယ်ဗျာ။

011011      010110      111001      100101

ခွဲပြီးတဲ့ အခါ ရလာတဲ့ binary value တွေကို decimal value ပြန်ပြောင်းမယ်။

011011      010110      111001      100101 = 27    22    57    37

ရလာတဲ့ decimal value တွေကိုမှ Base64 Alphabet Chart သုံးပြီး Character တွေ အဖြစ်ပြန်ပြောင်းမယ်။

27 = b
22 = W
57 = 5
37 = l

ကဲ... အခု mne ဆိုတာကို Base64 နည်းနဲ့ encode လုပ်လိုက်တာ bW5l ဖြစ်သွားပြီ။ မြင်တယ်နော်။ ဒါပါပဲ encoding ဆိုတာ။

ရှင်းပြထားတာ ရှည်တယ် အတိုမှတ်ချင်တယ်ဆိုတဲ့သူတွေအတွက် အတိုမှတ်ဖို့ပြောပြမယ်။

၁။ Character တွေကို Base64 decimal value ပြောင်းပါ။
၂။ ရလာတဲ့ decimal value တွေကို binary value ပြောင်းပါ။
၃။ ပြောင်းထားတဲ့ binary value (8-bits ၃ ခု) တွေကို 24-bits stream ဖြစ်အောင် ချရေးပါ။
၄။ ရလာတဲ့ 24-bits stream ကို ညာဖက်ကနေစပြီး 6-bits စီခဲွထုတ်ပါ။
၅။ 6-bits စီ ခွဲပြီးတဲ့ ရလာတဲ့ binary value တွေကို decimal value ပြန်ပြောင်းပါ။
၆။ ရလာတဲ့ decimal value တွေကို base64 Alphabet Chart သုံးပြီး US-ASCII Character ပြန်ပြောင်းပါ။

ကဲ... ဒီလောက်ဆို ရှင်းပြီထင်ပါတယ်။
ပြောချင်တာ တခုကတော့ binary to decimal/ decimal to binary ပြောင်းဖို့အတွက် Scientific Calculator ရှိရင်ရပါပြီ။
Engineer တွေနဲ့ ကွန်ပျူတာသမားတွေကတော့ မလိုလောက်ပါဘူး။
Base64 Alphabet Chart ကို အပေါ်မှာ ကြည့်လို့ရပါတယ်။

Decoding ပြန်လုပ်ချင်တယ်ဆိုရင် အခု ပြောပြထားတဲ့ အဆင့်တွေကို ပြောင်းပြန်ပြန်လုပ်လိုက်ရုံပေါ့ဗျာ။

ဒါက Manual နည်းနဲ့ encode/decode လုပ်တာပါ။

Program သုံးပြီး encode/decode လုပ်ချင်သူများအတွက် အောက်က C program လေးကို သုံးနိုင်ပါတယ်။

#include <appletdefs.h>

#include <iac.h>

#include "base64.h"

 

static char encodingTable [64] = {

 

    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',  

    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',  

    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',  

    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'

                };

 

static unsigned long gethandlesize (Handle h) {

 

                return (GetHandleSize (h));

                } /*gethandlesize*/

 

 static boolean sethandlesize (Handle h, unsigned long newsize) {

                 SetHandleSize (h, newsize);

                return (MemError () == noErr);

                } /*sethandlesize*/

 

 static unsigned char gethandlechar (Handle h, unsigned long ix) {

 

                return ((*h) [ix]);

                } /*gethandlechar*/

 

 static void sethandlechar (Handle h, unsigned long ix, unsigned char ch) {

 

                (*h) [ix] = ch;

                } /*sethandlechar*/

 

 static boolean encodeHandle (Handle htext, Handle h64, short linelength) {

 

                /*

                encode the handle. some funny stuff about linelength -- it only makes

                sense to make it a multiple of 4. if it's not a multiple of 4, we make it

                so (by only checking it every 4 characters.

                further, if it's 0, we don't add any line breaks at all.

                */

 

                unsigned long ixtext;

                unsigned long lentext;

                unsigned long origsize;

                long ctremaining;

                unsigned char ch;

                unsigned char inbuf [3], outbuf [4];

                short i;

                short charsonline = 0, ctcopy;

                ixtext = 0;

                lentext = gethandlesize (htext);

                while (true) {

 

                                ctremaining = lentext - ixtext;

                                                if (ctremaining <= 0)

                                                break;

                                                              

                                for (i = 0; i < 3; i++) {

                                                                unsigned long ix = ixtext + i;

                                                                if (ix < lentext)

                                                                inbuf [i] = gethandlechar (htext, ix);

                                                else

                                                                inbuf [i] = 0;

                                                } /*for*/

                              

                                outbuf [0] = (inbuf [0] & 0xFC) >> 2;

                                outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);

                                outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);

                                outbuf [3] = inbuf [2] & 0x3F;

                                origsize = gethandlesize (h64);

              

                                if (!sethandlesize (h64, origsize + 4))

                                                return (false);

                              

                                ctcopy = 4;

                                switch (ctremaining) {

                                                case 1:

                                                                ctcopy = 2;

                                                                break;

                              

                                                case 2:

                                                                ctcopy = 3;

                                                                break;

                                                } /*switch*/

 

                                for (i = 0; i < ctcopy; i++)

                                                sethandlechar (h64, origsize + i, encodingTable [outbuf [i]]);

                                for (i = ctcopy; i < 4; i++)

                                                sethandlechar (h64, origsize + i, '=');

                              

                                ixtext += 3;

                                charsonline += 4;

                                if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/

                                                                if (charsonline >= linelength) {

                                              

                                                                charsonline = 0;

                                                                origsize = gethandlesize (h64);

                                              

                                                                if (!sethandlesize (h64, origsize + 1))

                                                                                return (false);

                                                                sethandlechar (h64, origsize, '\n');

                                                                }

                                                }

                                } /*while*/

                return (true);

                } /*encodeHandle*/

 

 static boolean decodeHandle (Handle h64, Handle htext) {

 

                unsigned long ixtext;

                unsigned long lentext;

                unsigned long origsize;

                unsigned long ctremaining;

                unsigned char ch;

                unsigned char inbuf [3], outbuf [4];

                short i, ixinbuf;

                boolean flignore;

                boolean flendtext = false;

                ixtext = 0;

                lentext = gethandlesize (h64);

                ixinbuf = 0;

                while (true) {

              

                                if (ixtext >= lentext)

                                                break;

                              

                                ch = gethandlechar (h64, ixtext++);

                                flignore = false;

              

                                if ((ch >= 'A') && (ch <= 'Z'))

                                                ch = ch - 'A';

                                else if ((ch >= 'a') && (ch <= 'z'))

                                                ch = ch - 'a' + 26;

                                else if ((ch >= '0') && (ch <= '9'))

                                                ch = ch - '0' + 52;

                                else if (ch == '+')

                                                ch = 62;

                                else if (ch == '=') /*no op -- can't ignore this one*/

                                                flendtext = true;

                                else if (ch == '/')

                                                ch = 63;

                                else

                                                flignore = true;

              

                                if (!flignore) {

              

                                                short ctcharsinbuf = 3;

                                                boolean flbreak = false;

                                                 if (flendtext) {

                                              

                                                                if (ixinbuf == 0)

                                                                                break;

                                                                if ((ixinbuf == 1) || (ixinbuf == 2))

                                                                                ctcharsinbuf = 1;

                                                                else

                                                                                ctcharsinbuf = 2;

                                              

                                                                ixinbuf = 3;

                                              

                                                                flbreak = true;

                                                                }

                                                inbuf [ixinbuf++] = ch;

                                                if (ixinbuf == 4) {

                                                                ixinbuf = 0;

                                                                outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);

                                                                outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);

                                                                outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);

                                                                origsize = gethandlesize (htext);

                                              

                                                                if (!sethandlesize (htext, origsize + ctcharsinbuf))

                                                                                return (false);

                                                                for (i = 0; i < ctcharsinbuf; i++)

                                                                                sethandlechar (htext, origsize + i, outbuf [i]);

                                                                }

                                                if (flbreak)

                                                                break;

                                                }

                                } /*while*/

 

                exit:

                return (true);

                } /*decodeHandle*/

 

 

void base64encodeVerb (void) {

                Handle h64, htext;

                short linelength;

 

                if (!IACgettextparam ((OSType) keyDirectObject, &htext))

                                return;

                if (!IACgetshortparam ((OSType) 'line', &linelength))

                                return;

                h64 = NewHandle (0);

                if (!encodeHandle (htext, h64, linelength))

                                goto error;

              

                DisposHandle (htext);

                IACreturntext (h64);

                return;

                error:

 

                IACreturnerror (1, "\perror encoding the Base 64 text");

                } /*base64encodeVerb*/

 

 void base64decodeVerb (void) {

                Handle h64, htext;

                if (!IACgettextparam ((OSType) keyDirectObject, &h64))

                                return;

                htext = NewHandle (0);

                if (!decodeHandle (h64, htext))

                                goto error;

                DisposHandle (h64);

                IACreturntext (htext);

                return;

                error:

                 IACreturnerror (1, "\perror decoding the Base 64 text");

                } /*base64decodeVerb*/

ကိုယ်တိုင်ရေးထားတာတော့မဟုတ်ပါ။အင်တာနက်က ရထားတာလေးပါ။ ဒီတော့ စမ်းကြည့်ချင်ရင် စမ်းကြည့်နိုင်ပါတယ်။ ဒါပေမယ့် ထုံးစံ အတိုင်း at your own risk နော်။

ပျော်ရွှင်ပါစေဗျာ။
( Be knowledgeable,pass it on then)








No comments :

Post a Comment