上一篇:ASP使用MYSQL数据库全攻略 >>
奇妙的Base64编码
收/发e-mail的时候有一个安全性的问题--假想一下,你花了一整天时间给系花写的情书,在发送的过程中被隔壁宿舍张三那小子截获了(难道他是黑客??),更糟的是他是你的情敌啊……天,后果不堪设想!!因此,我们必须有一种比较可靠的加密方法,能够对电子邮件的明文进行转换,至少要得出一个无法被别人一眼就看出内容来的东西,而且编码/解码的速度还要足够快。(这时你可以再假想一下啦,张三那家伙截获了你的肉麻情书,可是他一看:“咦?怎么乱七八糟的?垃圾邮件!!”--这样一来你不就逃过大难了?!)
base64就是在这种背景下产生的加密方法。它的特点是:1、速度非常快。2、能够将字符串a转换成字符串b,而且如果你光看字符串b,是绝对猜不出字符串a的内容来的。不信吗?让我们来看看下面这串东西:
xoo6w6osu7btrbniwdnaz8letctnzbfxzoy12koh
呵呵,是什么啊?猜出来了吗?其实它就是下面这段文字经过base64编码产生的东东:
你好,欢迎光临老罗的缤纷天地!
介绍说完啦,让我们开始探讨实质性的东西。
base64是网络上最常见的用于传输8bit字节代码的编码方式之一,大家可以查看rfc2045~rfc2049,上面有mime的详细规范。
base64要求把每三个8bit的字节转换为四个6bit的字节(3*8 = 4*6 = 24),然后把6bit再添两位高位0,组成四个8bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
这样说会不会太抽象了?不怕,我们来看一个例子:
转换前 aaaaaabb ccccdddd eeffffff
转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff
应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的base64编码,其前两位均为0。
转换后,我们用一个码表来得到我们想要的字符串(也就是最终的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
让我们再来看一个实际的例子,加深印象!
转换前 10101101 10111010 01110110
转换后 00101011 00011011 00101001 00110110
十进制 43 27 42 54
对应码表中的值 r b q 2
所以上面的24位编码,编码后的base64值为 rbq2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,在此我就不多说了,另外有关mime的rfc还是有很多的,如果需要详细情况请自行查找。)
用更接近于编程的思维来说,编码的过程是这样的:
第一个字符通过右移2位获得第一个目标字符的base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符左移6位加上第二个字符右移4位,即获得第二个目标字符。
再将第二个字符左移4位加上第三个字符右移6位,获得第三个目标字符。
最后取第三个字符的右6位即获得第四个目标字符.
so easy! that’s all!!!
可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?
我们的解决办法是这样的:原文的字节不够的地方可以用全0来补足,转换时base64编码用=号来代替。这就是为什么有些base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:
余数 = 原文字节数 mod 3
所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦)。如果是1的话,为了让base64编码是4的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。
讲到这里,大伙儿应该全明白了吧?如果还有不清楚的话就返回去再仔细看看,其实不难理解的。
下面我给出一个演示base64编码/解码的程序,希望能对您有用。同时也希望您帮我完善它,利用它做出更多的用途,到时别忘了通知我一声啊!(我现在太忙了)
dll的源代码:base64dll.asm
;***********************************************
;程序名称:演示base64编码/解码原理
;作者:罗聪
;日期:2002-9-14
;http://laoluoc.yeah.net(老罗的缤纷天地)
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自“老罗的缤纷天地”(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
;**********************************************************
;函数功能:进行base64编码
;参数:
; source = 传入的字符串
; destination = 返回的编码
;**********************************************************
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
;**********************************************************
;函数功能:进行base64解码
;参数:
; source = 传入的编码
; destination = 返回的字符串
;**********************************************************
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
--------------------------------------------------------------------------------
测试程序:base64.asm
;***********************************************
;程序名称:演示base64编码/解码原理
;作者:罗聪
;日期:2002-9-14
;http://laoluoc.yeah.net(老罗的缤纷天地)
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自“老罗的缤纷天地”(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)
sztemplate_encode db "字符串 ""%s"" 的base64编码是:", 13, 10, 13, 10, "%s", 0
sztemplate_decode db "编码 ""%s"" 经过base64还原后的字符串是:", 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
;取得用户输入的字符串:
invoke getdlgitemtext, hwnd, idc_edit_input, addr szbuffer, 255
;进行 ascii->base64 转换:
invoke base64encode, addr szbuffer, addr sztext
;格式化输出:
invoke wsprintf, addr szmsg, addr sztemplate_encode, addr szbuffer, addr sztext
;显示结果:
invoke messagebox, hwnd, addr szmsg, addr szcaption, mb_ok
.elseif eax == idc_button_decode
;取得用户输入的字符串:
invoke getdlgitemtext, hwnd, idc_edit_input, addr szbuffer, 255
;进行 base64->ascii 转换:
invoke base64decode, addr szbuffer, addr sztext
;格式化输出:
invoke wsprintf, addr szmsg, addr sztemplate_decode, addr szbuffer, addr sztext
;显示结果:
invoke messagebox, hwnd, addr szmsg, addr szcaption, mb_ok
.endif
;全选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
--------------------------------------------------------------------------------
测试程序的资源文件: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
如果你发现了有bug,一定要告诉我啊,并请来信讨论!lcother@163.net
最后给大家留下一个小小的习题,你知道下面这串base64编码的原文是什么吗? :)
0lvqu8t6xm3xxddu19o/tm3qztk1xejhc2u2nl3ms8yjoscjuqop
vb: base64 加/解密 (只适用于英文)
使用:
call encode(.......) 加密
call decode(.......) 解密
-------- cut begins here-----
private const base64 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/"
public function encode(decryptedtext as string) as string
dim c1, c2, c3 as integer
dim w1 as integer
dim w2 as integer
dim w3 as integer
dim w4 as integer
dim n as integer
dim retry as string
for n = 1 to len(decryptedtext) step 3
c1 = asc(mid$(decryptedtext, n, 1))
c2 = asc(mid$(decryptedtext, n + 1, 1) + chr$(0))
c3 = asc(mid$(decryptedtext, n + 2, 1) + chr$(0))
w1 = int(c1 / 4)
w2 = (c1 and 3) * 16 + int(c2 / 16)
if len(decryptedtext) >= n + 1 then w3 = (c2 and 15) * 4 + int(c3 / 64) else w3 = -1
if len(decryptedtext) >= n + 2 then w4 = c3 and 63 else w4 = -1
retry = retry + mimeencode(w1) + mimeencode(w2) + mimeencode(w3) + mimeencode(w4)
next
encode = retry
end function
public function decode(a as string) as string
dim w1 as integer
dim w2 as integer
dim w3 as integer
dim w4 as integer
dim n as integer
dim retry as string
for n = 1 to len(a) step 4
w1 = mimedecode(mid$(a, n, 1))
w2 = mimedecode(mid$(a, n + 1, 1))
w3 = mimedecode(mid$(a, n + 2, 1))
w4 = mimedecode(mid$(a, n + 3, 1))
if w2 >= 0 then retry = retry + chr$(((w1 * 4 + int(w2 / 16)) and 255))
if w3 >= 0 then retry = retry + chr$(((w2 * 16 + int(w3 / 4)) and 255))
if w4 >= 0 then retry = retry + chr$(((w3 * 64 + w4) and 255))
next
decode = retry
end function
private function mimeencode(w as integer) as string
if w >= 0 then mimeencode = mid$(base64, w + 1, 1) else mimeencode = ""
end function
private function mimedecode(a as string) as integer
if len(a) = 0 then mimedecode = -1: exit function
mimedecode = instr(base64, a) - 1
end function
-------- cut ends -----
()
相关文章:
- · 3.从实例开始
- · 2.PHP入门
- · 1.PHP简介
- · 随机头像PHP版
- · 自动跳转中英文页面
- · 从IIS到SQL Server数据库安全
- · 通用数据库显示程序
- · ASP实用函数库
- · 漂亮但不安全的CTB
- · 无组件图片与文本同步存入数据库的最简单的办法
- · 利用PHP创建动态图像
- · 精妙SQL语句
- · 用ASP动态生成JS表单验证代码
- · 用ASP编写网上调查投票系统
- · 轮换的logo显示
- · ip签名探针
- · ASP下载系统防盗链方法
- · ASP开发网页牢记注意事项
- · IIS6.0下ASP的新增功能
- · 图片或banner的随机显示
- · 判断Cookies是否处于开启状态
- · 主页javascript特效19则
- · Script经典文章
- · 用ASP做全文检索
- · WEB应用中报表打印的实现
- · 控制输出字符串长度区别中英文
- · ADO连接数据库字符串大全
- · vbscript与javascript传递变量
- · WSH 直接将查询数据结果生成EXCEL表
- · 树型结构在ASP中的简单解决
- · 用Object for OLE访问Oracle
- · ASP中使用SQL语句
- · 继承派生多态
- · ASP中处理#include
- · 编写自己的缓冲区溢出利用程序
- · PHP4.23在WindowsXP下的IIS和Apache2两种服务器上的安装实例
- · 前后左右出现的窗口
- · 点击右键就弹出一个菜单
