作者:iamlasong
一、编码规则
编码规则网上很多,为了文章的完整性,这里简单的叙述一下。Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24 位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。这样就把一个3字节为一组的数据重新编码成了4个字节。当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。这时在最后一组填充1到2个0字节。并在最后编码完成后在结尾添加1到2个 “=”。
例:将对ABC进行BASE64编码:
1、首先取ABC对应的ASCII码值。A(65)B(66)C(67);
2、再取二进制值A(01000001)B(01000010)C(01000011);
3、然后把这三个字节的二进制码接起来(010000010100001001000011);
4、 再以6位为单位分成4个数据块,并在最高位填充两个0后形成4个字节的编码后的值,(00010000)(00010100)(00001001)(00000011),其中蓝色部分为真实数据;
5、再把这四个字节数据转化成10进制数得(16)(20)(9)(3);
6、最后根据BASE64给出的64个基本字符表,查出对应的ASCII码字符(Q)(U)(J)(D),这里的值实际就是数据在字符表中的索引。
即:ABC编码为QUJD
同理,我们可以实现编码案例: AB编码为QUI= A编码为QQ==
注:BASE64字符表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
二、解码规则
解码过程就是把4个字节再还原成3个字节,再根据不同的数据形式把字节数组重新整理成数据。
三、编码目的
为什么发明这么个编码呢,其实这个编码的原理是很简单的,“破解”也很容易,电子邮件刚出来的时候,只传递英文字符,这没有问题,但是后来,中国人,日本人都要发email,这样问题就来了,因为这些字符有可能会被邮件服务器或者网关当成命令处理,故必须得有一种编码来对邮件进行加密,但是加密的目的是为了能够使得一些原始的服务器不出问题,加密简单,这样客户端程序加密解密也快,又要是明文Ascii编码,这样Base64就诞生了。当初设计人员主要是考虑了两个问题:
1、加密算法复杂程度和效率
2、如何处理传输
Base64基本都能满足,如果因为发一封邮件把cpu占到100%或者把内存给用完了,那就完全没必要了,编码之后只要普通人一眼看不出内容就行了。
四、VB实现的编码和解码函数(调试成功)
'VB Base64 编码/加密函数: Function Base64Encode(Str() As Byte) As String 'Base64 编码 On Error GoTo over '排错 Dim buf() As Byte,length As Long,mods As Long Const B64_CHAR_DICT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" mods = (UBound(Str) + 1) Mod 3 '除以3的余数 length = UBound(Str) + 1 - mods ReDim buf(length / 3 * 4 + IIf(mods <> 0,4,0) - 1) Dim i As Long For i = 0 To length - 1 Step 3 buf(i / 3 * 4) = (Str(i) And &HFC) / &H4 buf(i / 3 * 4 + 1) = (Str(i) And &H3) * &H10 + (Str(i + 1) And &HF0) / &H10 buf(i / 3 * 4 + 2) = (Str(i + 1) And &HF) * &H4 + (Str(i + 2) And &HC0) / &H40 buf(i / 3 * 4 + 3) = Str(i + 2) And &H3F Next If mods = 1 Then buf(length / 3 * 4) = (Str(length) And &HFC) / &H4 buf(length / 3 * 4 + 1) = (Str(length) And &H3) * &H10 buf(length / 3 * 4 + 2) = 64 buf(length / 3 * 4 + 3) = 64 ElseIf mods = 2 Then buf(length / 3 * 4) = (Str(length) And &HFC) / &H4 buf(length / 3 * 4 + 1) = (Str(length) And &H3) * &H10 + (Str(length + 1) And &HF0) / &H10 buf(length / 3 * 4 + 2) = (Str(length + 1) And &HF) * &H4 buf(length / 3 * 4 + 3) = 64 End If For i = 0 To UBound(buf) Base64Encode = Base64Encode + Mid(B64_CHAR_DICT,buf(i) + 1,1) Next over: End Function
'VB Base64 解码/解密函数: Function Base64Decode(B64 As String) As Byte() 'Base64 解码 On Error GoTo over '排错 Dim OutStr() As Byte,i As Long,j As Long Const B64_CHAR_DICT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" If InStr(1,B64,"=") <> 0 Then B64 = Left(B64,InStr(1,"=") - 1) '判断Base64真实长度,除去补位 Dim length As Long,mods As Long mods = Len(B64) Mod 4 length = Len(B64) - mods ReDim OutStr(length / 4 * 3 - 1 + Switch(mods = 0,mods = 2,1,mods = 3,2)) For i = 1 To length Step 4 Dim buf(3) As Byte For j = 0 To 3 buf(j) = InStr(1,B64_CHAR_DICT,Mid(B64,i + j,1)) - 1 '根据字符的位置取得索引值 Next OutStr((i - 1) / 4 * 3) = buf(0) * &H4 + (buf(1) And &H30) / &H10 OutStr((i - 1) / 4 * 3 + 1) = (buf(1) And &HF) * &H10 + (buf(2) And &H3C) / &H4 OutStr((i - 1) / 4 * 3 + 2) = (buf(2) And &H3) * &H40 + buf(3) Next If mods = 2 Then OutStr(length / 4 * 3) = (InStr(1,length + 1,1)) - 1) * &H4 + ((InStr(1,length + 2,1)) - 1) And &H30) / 16 ElseIf mods = 3 Then OutStr(length / 4 * 3) = (InStr(1,1)) - 1) And &H30) / 16 OutStr(length / 4 * 3 + 1) = ((InStr(1,1)) - 1) And &HF) * &H10 + ((InStr(1,length + 3,1)) - 1) And &H3C) / &H4 End If Base64Decode = OutStr '读取解码结果 over: End Function
五、函数调用实例
Private Sub Command1_Click() Dim sou_code() As Byte Dim des_code() As Byte Dim sou_str,des_str As String Dim i,kk As Integer sou_str = "ABCAB" kk = Len(sou_str) - 1 ReDim sou_code(kk) For i = 0 To kk sou_code(i) = Asc(Mid(sou_str,i + 1,1)) Next i kk = UBound(sou_code) des_str = Base64Encode(sou_code()) MsgBox "Encode: " & des_str des_code = Base64Decode(des_str) MsgBox "Decode: " & des_code(0) & des_code(1) & des_code(2) & des_code(3) & des_code(4) '& des_code(5) des_str = "" For i = 0 To kk des_str = des_str & Chr(des_code(i)) Next i MsgBox des_str End Sub
六、结语
如果仅仅是实现二进制数据用文本方式传输,最简单的编码就是将每个字节用16进制表示,这样只用到16个字符(0-9,A-F)就可以了,不过,1个字节的数据变成2个字节,数据量增加了一倍;Base64编码后,3个字节的数据变成4个字节,数据量只增加了三分之一,兼顾了简单和效率。