jasmine214--love

          只有當(dāng)你的內(nèi)心總是充滿快樂、美好的愿望和寧靜時,你才能擁有強壯的體魄和明朗、快樂或者寧靜的面容。
          posts - 731, comments - 60, trackbacks - 0, articles - 0

          Base64編碼---加密方法

          Posted on 2010-06-15 17:16 幻海藍(lán)夢 閱讀(1106) 評論(0)  編輯  收藏 所屬分類: 加密解密
          原文:http://www.luocong.com/articles/show_article.asp?Article_ID=17
          java:http://www.zhuoda.org/elite/34479.html

          各位看官應(yīng)該都是資深的網(wǎng)蟲了,小弟斗膽在此問問大家,平時上網(wǎng)時,除了泡MM、到論壇灌水、扔版磚……之外,進行的最多的是什么活動?對了,你一定會說:是收發(fā)電子郵件!(誰敢說自己沒收/發(fā)過電子郵件的?拉出去槍斃了!!)

          收/發(fā)E-mail的時候有一個安全性的問題——假想一下,你花了一整天時間給系花寫的情書,在發(fā)送的過程中被隔壁宿舍張三那小子截獲了(難道他是黑客??),更糟的是他是你的情敵啊……天,后果不堪設(shè)想!!因此,我們必須有一種比較可靠的加密方法,能夠?qū)﹄娮余]件的明文進行轉(zhuǎn)換,至少要得出一個無法被別人一眼就看出內(nèi)容來的東西,而且編碼/解碼的速度還要足夠快。(這時你可以再假想一下啦,張三那家伙截獲了你的肉麻情書,可是他一看:“咦?怎么亂七八糟的?垃圾郵件!!”——這樣一來你不就逃過大難了?!)

          Base64就是在這種背景下產(chǎn)生的加密方法。它的特點是:1、速度非常快。2、能夠?qū)⒆址瓵轉(zhuǎn)換成字符串B,而且如果你光看字符串B,是絕對猜不出字符串A的內(nèi)容來的。不信嗎?讓我們來看看下面這串東西:

          xOO6w6Osu7bTrbniwdnAz8LetcTnzbfXzOy12KOh

          呵呵,是什么啊?猜出來了嗎?其實它就是下面這段文字經(jīng)過Base64編碼產(chǎn)生的東東:

          你好,歡迎光臨老羅的繽紛天地!

          介紹說完啦,讓我們開始探討實質(zhì)性的東西。

          Base64是網(wǎng)絡(luò)上最常見的用于傳輸8Bit字節(jié)代碼的編碼方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的詳細(xì)規(guī)范。

          Base64要求把每三個8Bit的字節(jié)轉(zhuǎn)換為四個6Bit的字節(jié)(3*8 = 4*6 = 24),然后把6Bit再添兩位高位0,組成四個8Bit的字節(jié),也就是說,轉(zhuǎn)換后的字符串理論上將要比原來的長1/3。

          這樣說會不會太抽象了?不怕,我們來看一個例子:

          轉(zhuǎn)換前aaaaaabbccccddddeeffffff
          轉(zhuǎn)換后00aaaaaa00bbcccc00ddddee00ffffff

          應(yīng)該很清楚了吧?上面的三個字節(jié)是原文,下面的四個字節(jié)是轉(zhuǎn)換后的Base64編碼,其前兩位均為0。

          轉(zhuǎn)換后,我們用一個碼表來得到我們想要的字符串(也就是最終的Base64編碼),這個表是這樣的:(摘自RFC2045)


          ????????????????????????????Table 1: The Base64 Alphabet

          ??????Value Encoding??Value Encoding??Value Encoding??Value Encoding
          ?????????? 0 A????????????17 R????????????34 i????????????51 z
          ?????????? 1 B????????????18 S????????????35 j????????????52 0
          ?????????? 2 C????????????19 T????????????36 k????????????53 1
          ?????????? 3 D????????????20 U????????????37 l????????????54 2
          ?????????? 4 E????????????21 V????????????38 m????????????55 3
          ?????????? 5 F????????????22 W????????????39 n????????????56 4
          ?????????? 6 G????????????23 X????????????40 o????????????57 5
          ?????????? 7 H????????????24 Y????????????41 p????????????58 6
          ?????????? 8 I????????????25 Z????????????42 q????????????59 7
          ?????????? 9 J????????????26 a????????????43 r????????????60 8
          ??????????10 K????????????27 b????????????44 s????????????61 9
          ??????????11 L????????????28 c????????????45 t????????????62 +
          ??????????12 M????????????29 d????????????46 u????????????63 /
          ??????????13 N????????????30 e????????????47 v
          ??????????14 O????????????31 f????????????48 w???????? (pad) =
          ??????????15 P????????????32 g????????????49 x
          ??????????16 Q????????????33 h????????????50 y


          讓我們再來看一個實際的例子,加深印象!

          轉(zhuǎn)換前101011011011101001110110
          轉(zhuǎn)換后00101011000110110010100100110110
          十進制43274154
          對應(yīng)碼表中的值rbp2


          所以上面的24位編碼,編碼后的Base64值為 rbp2
          解碼同理,把 rbq2 的二進制位連接上再重組得到三個8位值,得出原碼。
          (解碼只是編碼的逆過程,在此我就不多說了,另外有關(guān)MIME的RFC還是有很多的,如果需要詳細(xì)情況請自行查找。)

          用更接近于編程的思維來說,編碼的過程是這樣的:

          第一個字符通過右移2位獲得第一個目標(biāo)字符的Base64表位置,根據(jù)這個數(shù)值取到表上相應(yīng)的字符,就是第一個目標(biāo)字符。
          然后將第一個字符左移4位加上第二個字符右移4位,即獲得第二個目標(biāo)字符。
          再將第二個字符左移2位加上第三個字符右移6位,獲得第三個目標(biāo)字符。
          最后取第三個字符的右6位即獲得第四個目標(biāo)字符。

          在以上的每一個步驟之后,再把結(jié)果與 0x3F 進行 AND 位操作,就可以得到編碼后的字符了。

          (感謝 Athena 指出以上描述中原有的一些錯誤!^_^)

          So easy! That’s all!!!

          可是等等……聰明的你可能會問到,原文的字節(jié)數(shù)量應(yīng)該是3的倍數(shù)啊,如果這個條件不能滿足的話,那該怎么辦呢?

          我們的解決辦法是這樣的:原文的字節(jié)不夠的地方可以用全0來補足,轉(zhuǎn)換時Base64編碼用=號來代替。這就是為什么有些Base64編碼會以一個或兩個等號結(jié)束的原因,但等號最多只有兩個。因為:

          余數(shù) = 原文字節(jié)數(shù) MOD 3

          所以余數(shù)任何情況下都只可能是0,1,2這三個數(shù)中的一個。如果余數(shù)是0的話,就表示原文字節(jié)數(shù)正好是3的倍數(shù)(最理想的情況啦)。如果是1的話,為了讓Base64編碼是4的倍數(shù),就要補2個等號;同理,如果是2的話,就要補1個等號。

          講到這里,大伙兒應(yīng)該全明白了吧?如果還有不清楚的話就返回去再仔細(xì)看看,其實不難理解的。

          下面我給出一個演示Base64編碼/解碼的程序,希望能對您有用。同時也希望您幫我完善它,利用它做出更多的用途,到時別忘了通知我一聲啊!(我現(xiàn)在太忙了)


          DLL的源代碼:Base64Dll.asm

          ;***********************************************
          ;程序名稱:演示Base64編碼/解碼原理
          ;作者:羅聰
          ;日期:2002-9-14
          ;出處:http://laoluoc.yeah.net(老羅的繽紛天地)
          ;注意事項:如欲轉(zhuǎn)載,請保持本程序的完整,并注明:
          ;轉(zhuǎn)載自“老羅的繽紛天地”(http://laoluoc.yeah.net)
          ;***********************************************

          .386
          .modelflat,stdcall
          optioncasemap:none

          include \masm32\include\windows.inc
          include \masm32\include\kernel32.inc
          include \masm32\include\user32.inc
          includelib \masm32\lib\kernel32.lib
          includelib \masm32\lib\user32.lib

          DllEntry????????proto:HINSTANCE,:DWORD,:DWORD
          Base64Encode????proto:DWORD,:DWORD
          Base64Decode????proto:DWORD,:DWORD

          .data
          ;Base64 -> ASCII mapping table
          base64_alphabet ????db????"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="

          ;ASCII -> Base64 mapping table
          base64table???????? db43dup(255)
          ?? ???? ????????????db62,255,255,255,63,52,53,54,55,56,57,58,59,60,61,255
          ????????????????????db255,255,0,255,255,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13
          ????????????????????db14,15,16,17,18,19,20,21,22,23,24,25,255,255,255,255
          ????????????????????db255,255,26,27,28,29,30,31,32,33,34,35,36,37,38
          ????????????????????db39,40,41,42,43,44,45,46,47,48,49,50,51
          ????????????????????db132dup(255)

          .code
          DllEntry????proc????hInst: HINSTANCE, reason:DWORD, reserved1:DWORD
          ????moveax, TRUE
          ????ret
          DllEntry????endp


          ;**********************************************************
          ;函數(shù)功能:進行Base64編碼
          ;參數(shù):
          ;????source??????????=????傳入的字符串
          ;????destination???? =????返回的編碼
          ;**********************************************************
          Base64Encode????proc????usesebxediesi source:DWORD, destination:DWORD
          ????LOCAL????sourcelen:DWORD

          ????invoke lstrlen, source
          ????mov sourcelen,eax

          ????mov??esi, source
          ????mov??edi, destination
          @@base64loop:
          ????xoreax,eax
          ????.if sourcelen ==1
          ????????lodsb????????????????????????;source ptr + 1
          ????????movecx,2?? ????????????????;bytes to output = 2
          ????????movedx,03D3Dh??????????????;padding = 2 byte
          ????????dec sourcelen????????????????;length - 1
          ????.elseif sourcelen ==2
          ????????lodsw????????????????????????;source ptr + 2
          ????????movecx,3?? ????????????????;bytes to output = 3
          ????????movedx,03Dh????????????????;padding = 1 byte
          ????????sub sourcelen,2???????????? ;length - 2
          ????.else
          ????????lodsd
          ????????movecx,4?? ????????????????;bytes to output = 4
          ????????xoredx,edx???????????????? ;padding = 0 byte
          ????????decesi??????????????????????;source ptr + 3 (+4-1)
          ????????sub sourcelen,3???????????? ;length - 3
          ????.endif

          ????xchgal,ah?? ????????????????????;flip eax completely
          ????rol??eax,16???????????????????? ;can this be done faster
          ????xchgal,ah

          ????@@:
          ????push??eax
          ????and?? eax,0FC000000h????????????;get the last 6 high bits
          ????rol?? eax,6???????????????????? ;rotate them into al
          ????mov?? al,??byteptr[offset base64_alphabet +eax]????????;get encode character
          ????stosb????????????????????????????;write to destination
          ????pop?? eax
          ????shl?? eax,6???????????????????? ;shift left 6 bits
          ????dec?? ecx
          ????jnz?? @B???????????????????????? ;loop

          ????cmp?? sourcelen,0
          ????jnz?? @@base64loop?????????????? ;main loop

          ????mov?? eax,edx?????????????????? ;add padding and null terminate
          ????stosd

          ????ret
          Base64Encode????endp


          ;**********************************************************
          ;函數(shù)功能:進行Base64解碼
          ;參數(shù):
          ;????source??????????=????傳入的編碼
          ;????destination???? =????返回的字符串
          ;**********************************************************
          Base64Decode????proc????usesebxediesi source:DWORD, destination:DWORD
          ????LOCAL????sourcelen:DWORD

          ????invoke lstrlen, source
          ????mov sourcelen,eax
          ????
          ????mov????esi, source???????????? ;esi <- source
          ????mov????edi, destination????????;edi <- destination
          ????mov????ecx, sourcelen
          ????shr????ecx,2
          ????cld
          ????
          ????;-------------[decoding part]---------------
          ????
          @@outer_loop:
          ????push?? ecx
          ????mov????ecx,4
          ????xor????ebx,ebx
          ????lodsd
          @@inner_loop:
          ????push?? eax
          ????and????eax,0ffh
          ????mov????al,byteptr[offset base64table +eax]
          ????cmp????al,255
          ????je???? @@invalid_char
          ????shl????ebx,6
          ????or???? bl,al
          ????pop????eax
          ????shr????eax,8
          ????dec????ecx
          ????jnz????@@inner_loop
          ????mov????eax,ebx
          ????shl????eax,8
          ????xchg?? ah,al
          ????ror????eax,16
          ????xchg?? ah,al
          ????stosd
          ????dec????edi
          ????pop????ecx
          ????dec????ecx
          ????jnz????@@outer_loop
          ????xor????eax,eax
          ????jmp????@@decode_done
          ????
          ????;-------------------------------------------
          ????
          @@invalid_char:
          ????mov????eax,-1
          @@decode_done:
          ????ret
          Base64Decode ENDP


          end DllEntry
          ;********************????over????********************
          ;by LC





          測試程序:base64.asm

          ;***********************************************
          ;程序名稱:演示Base64編碼/解碼原理
          ;作者:羅聰
          ;日期:2002-9-14
          ;出處:http://laoluoc.yeah.net(老羅的繽紛天地)
          ;注意事項:如欲轉(zhuǎn)載,請保持本程序的完整,并注明:
          ;轉(zhuǎn)載自“老羅的繽紛天地”(http://laoluoc.yeah.net)
          ;***********************************************

          .386
          .modelflat,stdcall
          optioncasemap:none

          include \masm32\include\windows.inc
          include \masm32\include\kernel32.inc
          include \masm32\include\user32.inc
          include Base64Dll.inc
          includelib \masm32\lib\kernel32.lib
          includelib \masm32\lib\user32.lib
          includelib Base64Dll.lib

          WndProc????????????proto:DWORD,:DWORD,:DWORD,:DWORD

          .const
          IDC_BUTTON_ENCODE????equ????3000
          IDC_BUTTON_DECODE????equ????3001
          IDC_EDIT_INPUT?? ????equ????3002
          MAXSIZE??????????????equ????260

          .data
          szDlgName????????????db????"lc_dialog",0
          szCaption????????????db????"BASE64 demo by LC",0
          szBuffer???????????? db????255dup(0)
          szText?????????? ????db????340dup(0)
          szMsg????????????????db????450dup(0)
          szTemplate_Encode????db????"字符串 ""%s"" 的Base64編碼是:",13,10,13,10,"%s",0
          szTemplate_Decode????db????"編碼 ""%s"" 經(jīng)過Base64還原后的字符串是:",13,10,13,10,"%s",0

          .code
          main:
          ????invoke GetModuleHandle, NULL
          ????invoke DialogBoxParam,eax,offset szDlgName,0, WndProc,0
          ????invoke ExitProcess,eax

          WndProc procusesedi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
          ????LOCAL hEdit: HWND

          ????.if uMsg == WM_CLOSE
          ????????invoke EndDialog, hWnd,0
          ????????
          ????.elseif uMsg == WM_COMMAND
          ????????moveax, wParam
          ????????movedx,eax
          ????????shredx,16
          ????????movzxeax,ax
          ????????.ifedx== BN_CLICKED
          ????????????.ifeax== IDCANCEL
          ????????????????invoke EndDialog, hWnd, NULL
          ????
          ????????????.elseifeax== IDC_BUTTON_ENCODE ||eax== IDOK
          ????????????????;取得用戶輸入的字符串:
          ????????????????invoke GetDlgItemText, hWnd, IDC_EDIT_INPUT,addr szBuffer,255

          ????????????????;進行 ASCII->Base64 轉(zhuǎn)換:
          ????????????????invoke Base64Encode,addr szBuffer,addr szText

          ????????????????;格式化輸出:
          ????????????????invoke wsprintf,addr szMsg,addr szTemplate_Encode,addr szBuffer,addr szText

          ????????????????;顯示結(jié)果:
          ????????????????invoke MessageBox, hWnd,addr szMsg,addr szCaption, MB_OK

          ????????????.elseifeax== IDC_BUTTON_DECODE
          ????????????????;取得用戶輸入的字符串:
          ????????????????invoke GetDlgItemText, hWnd, IDC_EDIT_INPUT,addr szBuffer,255

          ????????????????;進行 Base64->ASCII 轉(zhuǎn)換:
          ????????????????invoke Base64Decode,addr szBuffer,addr szText

          ????????????????;格式化輸出:
          ????????????????invoke wsprintf,addr szMsg,addr szTemplate_Decode,addr szBuffer,addr szText

          ????????????????;顯示結(jié)果:
          ????????????????invoke MessageBox, hWnd,addr szMsg,addr szCaption, MB_OK
          ????????????.endif

          ????????????;全選edit里面的內(nèi)容:
          ????????????invoke GetDlgItem, hWnd, IDC_EDIT_INPUT
          ????????????invoke SendMessage,eax, EM_SETSEL,0,-1

          ????????.endif
          ????.else
          ????????moveax, FALSE
          ????????ret
          ????.endif
          ????moveax, TRUE
          ????ret
          WndProc endp

          end main
          ;********************????over????********************
          ;by LC





          測試程序的資源文件:base64.rc

          #include "resource.h"

          #define IDC_BUTTON_ENCODE????3000
          #define IDC_BUTTON_DECODE????3001
          #define IDC_EDIT_INPUT?????? 3002
          #define IDC_STATIC?????????? -1

          LC_DIALOG DIALOGEX 10, 10, 195, 60
          STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION |
          ????WS_SYSMENU
          CAPTION "Base64 demo by LC"
          FONT 9, "宋體", 0, 0, 0x0
          BEGIN
          ????LTEXT?????????? "請輸入字符串:", IDC_STATIC, 11, 7, 130, 10
          ????EDITTEXT????????IDC_EDIT_INPUT, 11, 20, 173, 12, ES_AUTOHSCROLL
          ????DEFPUSHBUTTON?? "編碼(&E)", IDC_BUTTON_ENCODE, 38, 39, 52, 15
          ????PUSHBUTTON??????"解碼(&D)", IDC_BUTTON_DECODE, 104, 39, 52, 15
          END


          如果你發(fā)現(xiàn)了有bug,一定要告訴我啊,并請來信討論!mailto:lcother@163.net?subject=老羅,有關(guān)Base64的問題想跟你討論!

          最后給大家留下一個小小的習(xí)題,你知道下面這串Base64編碼的原文是什么嗎???:)
          0LvQu8T6xM3XxdDU19O/tM3qztK1xEJhc2U2NL3Ms8yjoSCjuqOp

          老羅
          2002-9-14


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 平泉县| 永昌县| 河津市| 赣榆县| 屏东市| 兖州市| 杨浦区| 恩施市| 揭西县| 鱼台县| 梁平县| 遂宁市| 武威市| 图们市| 蕲春县| 芒康县| 桓仁| 马关县| 开原市| 徐州市| 清水河县| 滨州市| 浦城县| 佛坪县| 红河县| 敖汉旗| 宣恩县| 石河子市| 辽宁省| 灵台县| 长宁区| 梅河口市| 华容县| 彭山县| 秦安县| 辽源市| 越西县| 澄江县| 丰原市| 门头沟区| 杭锦后旗|