首页 > 代码库 > VB实现Base64 编码

VB实现Base64 编码

作者: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, B64, "=") - 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, 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, B64_CHAR_DICT, Mid(B64, length + 1, 1)) - 1) * &H4 + ((InStr(1, B64_CHAR_DICT, Mid(B64, length + 2, 1)) - 1) And &H30) / 16
    ElseIf mods = 3 Then
        OutStr(length / 4 * 3) = (InStr(1, B64_CHAR_DICT, Mid(B64, length + 1, 1)) - 1) * &H4 + ((InStr(1, B64_CHAR_DICT, Mid(B64, length + 2, 1)) - 1) And &H30) / 16
        OutStr(length / 4 * 3 + 1) = ((InStr(1, B64_CHAR_DICT, Mid(B64, length + 2, 1)) - 1) And &HF) * &H10 + ((InStr(1, B64_CHAR_DICT, Mid(B64, 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个字节,数据量只增加了三分之一,兼顾了简单和效率。