Http://www.luocong.com/articles/show_article.asp? Article_id = 17
Download the example Program (6.93 KB) in this section) |
You should be a senior online reader, and the younger brother is brave enough to ask, when surfing the internet, in addition to soaking the MM, bumping the Forum, throwing bricks ...... In addition, what activities are most carried out? By the way, you must say: It's sending and receiving emails! (Who dare say they have confiscated/sent an email? Pulled out and shot !!)
There is a security issue when sending/receiving e-mail-Imagine that you spent a whole day writing a love letter to the department, he was intercepted by Michael Zhang from the dormitory next door during the sending process (is he a hacker ??), What's worse, he's your rival ...... Day, the consequences are unimaginable !! Therefore, we must have a relatively reliable encryption method to convert the plaintext of an email. At least we need something that cannot be seen at a Glance by others, the encoding/decoding speed is also fast enough. (Now, you can imagine another story. Michael's guy intercepted your love letter, but he saw it: "Why? How is it messy? Spam !!" -- In this way, you will not be able to escape the difficulties ?!)
Base64 is the encryption method generated in this context. It features: 1. The speed is very fast. 2. You can convert string a to string B. If you look at string B, you cannot guess the content of string. Believe it? Let's take a look at the following string:
Xoo6w6osu7btrbniwdna z8letctnzbfxzoy12koh
What is it? Have you guessed it? In fact, it is the following text produced by base64 encoding:
Hello! Welcome to the colorful world of Lao Luo!
The introduction is complete. Let's start to explore things.
Base64 is one of the most common encoding methods used to transmit 8-bit code on the network. For details, refer to rfc2045 ~ Rfc2049, which has the mime detailed specification.
Base64 requires that each three 8-bit bytes be converted into four 6-bit bytes (3*8 = 4*6 = 24), and then 6-bit bytes be added with two more high 0 values, it consists of four 8-bit bytes. That is to say, the converted string is theoretically 1/3 longer than the original one.
Will it be too abstract? Not afraid. Let's look at an example:
Before Conversion |
Aaaaaabb |
Ccccdddd |
Eeffffff |
|
After conversion |
00 aaaaaa |
00 bbcccc |
00 ddddee |
00 ffffff |
Should it be clear? The above three bytes are the original text, and the following four bytes are base64 encoded after conversion, and the first two are both 0.
After conversion, we use a code table to obtain the desired string (that is, the final base64 encoding). This table is as follows: (from rfc2045)
Table 1: The base64 alphabet
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
6g 23x40 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 32G 49 x
16 Q 33 H 50 y
Let's take a look at the actual example to help you better understand it!
Before Conversion |
10101101 |
10111010 |
01110110 |
|
After conversion |
00101011 |
00011011 |
00101001 |
00110110 |
Decimal |
43 |
27 |
41 |
54 |
Values in the corresponding code table |
R |
B |
P |
2 |
Therefore, the base64 value of the preceding 24-bit encoding is rbp2.
Similarly, the original code is obtained by reorganizing the binary join of rbq2 to get three 8-bit values.
(Decoding is only the inverse process of encoding. I will not talk about it here. In addition, there are still many RFC related to mime. If you need details, please search for it yourself .)
The coding process is similar to that of programming:
The first character shifts two places to the right to obtain the location of the base64 table of the first target character. Based on this value, the corresponding character on the table is the first target character.
Then, move the first character four places to the left and the second character four places to the right to obtain the second target character.
Then, remove the second character from the left to the second and the third character to the right to get the third target character.
Finally, take the right 6 digits of the third character to obtain the fourth target character.
After each of the preceding steps, perform the and operation on the result and 0x3f to get the encoded characters.
(Thanks to Athena for pointing out some of the mistakes described above! ^_^)
So easy! That's all !!!
But wait ...... If you are smart, you may ask that the number of bytes in the original text should be a multiple of 3. What if this condition cannot be met?
The solution is as follows: the bytes in the original text can be supplemented with 0, and the base64 encoding is replaced with the = number during conversion. This is why some base64 encoding ends with one or two equal signs, but the equal signs can only be two at most. Because:
Remainder = number of original bytes mod 3
Therefore, the remainder can only be one of the three numbers 0, 1, and 2 in any case. If the remainder is 0, it indicates that the number of original bytes is exactly a multiple of 3 (ideally ). If it is 1, in order to make base64 encoding a multiple of 4, we need to add two equal signs. Similarly, if it is 2, we need to add one equal sign.
At this point, should everyone be clear? If you still have any questions, go back and take a closer look. It is not hard to understand.
The following is a program that demonstrates base64 encoding/decoding, hoping to be useful to you. At the same time, I hope you can help me improve it and use it for more purposes. Don't forget to let me know! (I am too busy now)
DLL source code: base64dll. ASM
; **************************************** ******* Program name: demonstrate base64 encoding/decoding principles ; Author: Luo Cong ; Date: 2002-9-14 Source: http://laoluoc.yeah.net (laoluo's colorful world) ; Note: If you want to reprint it, please keep the program complete and note: ; Reprinted from "Luo's colorful world" (http://laoluoc.yeah.net) ; **************************************** *******
.386 .Model flat,Stdcall Option Casemap: 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 dB 43 DUP (255) DB 62,255,255,255,63,52,53,54,55,56,57,58,59,60,61,255 DB 255,255,0,255,255,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13 DB 14,15,16,17,18,19,20,21,22,23,24,25,255,255,255,255 DB 255,255,26,27,28,29,30,31,32,33,34,35,36,37,38 DB 39,40,41,42,43,44,45,46,47,48,49,50,51 DB 132 DUP (255)
.Code Dllentry proc hinst: hinstance,Reason: DWORD,Reserved1: DWORD MoV eax,True RET Dllentry endp
; **************************************** ****************** Function: base64 encoding ; Parameters: ; Source = input string ; Destination = returned Encoding ; **************************************** ****************** Base64encode proc uses ebx edi esi Source: DWORD,Destination: DWORD Local sourcelen: DWORD
Invoke lstrlen,Source MoV sourcelen,Eax
MoV ESI,Source MoV EDI,Destination @ Base64loop: XOR eax,Eax .If sourcelen = 1 Lodsb; source PTR + 1 MoV ECx,2; bytes to output = 2 MoV edX,03d3dh; padding = 2 byte Dec sourcelen; Length-1 .Elseif sourcelen = 2 Lodsw; source PTR + 2 MoV ECx,3; bytes to output = 3 MoV edX,03dh; padding = 1 byte Sub sourcelen,2; Length-2 .Else Lodsd MoV ECx,4; bytes to output = 4 XOR edX,EdX; padding = 0 byte Dec ESI; source PTR + 3 (+ 4-1) Sub sourcelen,3; Length-3 .Endif
Xchg al,Ah; flip eax completely Rol eax,16; can this be done faster Xchg al,Ah
@@: Push eax And eax,0fc000000h; get the last 6 high bits Rol eax,6; rotate them into Al MoV al,Byte PTR [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
; **************************************** ****************** ; Function: base64 Decoding ; Parameters: ; Source = input Encoding ; Destination = returned string ; **************************************** ****************** Base64decode proc uses ebx edi esi 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,Byte PTR [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 |
Test procedure: base64.asm
; **************************************** ******* Program name: demonstrate base64 encoding/decoding principles ; Author: Luo Cong ; Date: 2002-9-14 Source: http://laoluoc.yeah.net (laoluo's colorful world) ; Note: If you want to reprint it, please keep the program complete and note: ; Reprinted from "Luo's colorful world" (http://laoluoc.yeah.net) ; **************************************** *******
.386 .Model flat,Stdcall Option Casemap: 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 255 DUP (0) Sztext dB 340 DUP (0) Szmsg dB 450 DUP (0) The base64 encoding of sztemplate_encode DB "string" "% s" "is :",13,10,13,10,"% S",0 Sztemplate_decode DB "encoding" "% s" the base64 restored string is :",13,10,13,10,"% S",0
.Code Main: Invoke getmodulehandle,Null Invoke dialogboxparam,Eax,Offset szdlgname,0,Wndproc,0 Invoke exitprocess,Eax
Wndproc proc uses EDI hwnd: hwnd,Umsg: uint,Wparam: wparam,Lparam: lparam Local hedit: hwnd
.If umsg = wm_close Invoke enddialog,Hwnd,0
.Elseif umsg = wm_command MoV eax,Wparam MoV edX,Eax SHR edX,16 Movzx eax,Ax .If edX = bn_clicked .If eax = idcancel Invoke enddialog,Hwnd,Null
.Elseif eax = idc_button_encode | eax = idok ; Get the user input string: Invoke getdlgitemtext,Hwnd,Idc_edit_input,ADDR szbuffer,255
; Ascii-> base64 conversion: Invoke base64encode,ADDR szbuffer,ADDR sztext
; Format the output: Invoke wsprintf,ADDR szmsg,ADDR sztemplate_encode,ADDR szbuffer,ADDR sztext
; Display result: Invoke MessageBox,Hwnd,ADDR szmsg,ADDR szcaption,Mb_ OK
.Elseif eax = idc_button_decode ; Get the user input string: Invoke getdlgitemtext,Hwnd,Idc_edit_input,ADDR szbuffer,255
; For base64-> ASCII conversion: Invoke base64decode,ADDR szbuffer,ADDR sztext
; Format the output: Invoke wsprintf,ADDR szmsg,ADDR sztemplate_decode,ADDR szbuffer,ADDR sztext
; Display result: Invoke MessageBox,Hwnd,ADDR szmsg,ADDR szcaption,Mb_ OK .Endif
; Select all the content in edit: Invoke getdlgitem,Hwnd,Idc_edit_input Invoke sendmessage,Eax,Em_setsel,0,-1
.Endif .Else MoV eax,False RET .Endif MoV eax,True RET Wndproc endp
End main ; *****************Over ******************* * ; By LC |
Resource file of the test program: 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 "enter a string:", idc_static, 11, 7,130, 10 Edittext idc_edit_input, 11, 20,173, 12, es_autohscroll Defpushbutton "encoding (& E)", idc_button_encode, 38, 39, 52, 15 Pushbutton "decoding (& D)", idc_button_decode, 104, 39, 52, 15 End |
If you find a bug, please let me know and discuss it with me! Lcother@163.net
Finally, I will leave you with a small exercise. Do you know the original text of this string of base64 encoding? :)
0lvqu8t6xm3xxddu19o/tm3qztk1xejhc2u2nl3ms8yjoscjuqop