base64

base64_4分词条

  Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。
  Base64要求把每三个8Bit字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

目录 [隐藏]

base64 为什么要使用Base64

       

    在email传输中,加密是肯定的,但是加密的目的不是让用户发送非常安全的Email。这种加密方式主要就是“防君子不防小人”。即达到一眼望去完全看不出内容即可。基于这个目的加密算法的复杂程度和效率也就不能太大和太低。和上一个理由类似,MIME协议等用于发送Email的协议解决的是如何收发Email,而并不是如何安全的收发Email。因此算法复杂度要小,效率要高,否则因为发送Email而大量占用资源,路就有点走歪了。

    但是,如果是基于以上两点,那么我们使用最简单的恺撒法即可,为什么Base64看起来要比恺撒法复杂呢?这是因为在Email的传送过程中,由于历史原因,Email只被允许传送ASCII字符,即一个8位字节的低7位。因此,如果您发送了一封带有非ASCII字符(即字节的最高位是1)的Email通过有“历史问题”的网关时就可能会出现问题。网关可能会把最高位置为0!很明显,问题就这样产生了!因此,为了能够正常的传送Email,这个问题就必须考虑!所以,单单靠改变字母的位置的恺撒之类的方案也就不行了。关于这一点可以参考RFC2046。基于以上的一些主要原因产生了Base64编码。

base64 加密解密算法

       

转换前 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 41 54
对应码表中的值 r b p 2


所以上面的24位编码,编码后的Base64值为 rbp2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,在此我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详细情况请自行查找。)

用更接近于编程的思维来说,编码的过程是这样的:

第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。
再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。
最后取第三个字符的右6位即获得第四个目标字符。

在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。

可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?

我们的解决办法是这样的:原文的字节不够的地方可以用全0来补足,转换时Base64编码用=号来代替。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:

余数 = 原文字节数 MOD 3

所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦)。如果是1的话,为了让Base64编码是4的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。

base64 在URL中的应用

       

  Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
  然而,标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。
  为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“*”和“-”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
  另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。
  此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。

base64 VB的Base64编码函数定义

       

  注:其中DigestStrToHexStr为可在程序外部调用加密函数
  Option Explicit
  ' Base64 Encoding/Decoding Algorithm
  ' By: David Midkiff (mznull@earthlink.net)
  '
  ' This algorithms encodes and decodes data into Base64
  ' format. This format is extremely more efficient than
  ' Hexadecimal encoding.
  Private m_bytIndex(0 To 63) As Byte
  Private m_bytReverseIndex(0 To 255) As Byte
  Private Const k_bytEqualSign As Byte = 61
  Private Const k_bytMask1 As Byte = 3
  Private Const k_bytMask2 As Byte = 15
  Private Const k_bytMask3 As Byte = 63
  Private Const k_bytMask4 As Byte = 192
  Private Const k_bytMask5 As Byte = 240
  Private Const k_bytMask6 As Byte = 252
  Private Const k_bytShift2 As Byte = 4
  Private Const k_bytShift4 As Byte = 16
  Private Const k_bytShift6 As Byte = 64
  Private Const k_lMaxBytesPerLine As Long = 152
  Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
  Public Function Decode64(sInput As String) As String
  If sInput = "" Then Exit Function
  Decode64 = StrConv(DecodeArray64(sInput), vbUnicode)
  End Function
  Private Function DecodeArray64(sInput As String) As Byte()
  Dim bytInput() As Byte
  Dim bytWorkspace() As Byte
  Dim bytResult() As Byte
  Dim lInputCounter As Long
  Dim lWorkspaceCounter As Long
  bytInput = Replace(Replace(sInput, vbCrLf, ""), "=", "")
  ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 2)) As Byte
  lWorkspaceCounter = LBound(bytWorkspace)
  For lInputCounter = LBound(bytInput) To UBound(bytInput)
  bytInput(lInputCounter) = m_bytReverseIndex(bytInput(lInputCounter))
  Next lInputCounter
  For lInputCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 8) + 8)) Step 8
  bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)
  bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytMask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)
  bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytMask1) * k_bytShift6) + bytInput(lInputCounter + 6)
  lWorkspaceCounter = lWorkspaceCounter + 3
  Next lInputCounter
  Select Case (UBound(bytInput) Mod 8):
  Case 3:
  bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)
  Case 5:
  bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)
  bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytMask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)
  lWorkspaceCounter = lWorkspaceCounter + 1
  Case 7:
  bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)
  bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytMask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)
  bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytMask1) * k_bytShift6) + bytInput(lInputCounter + 6)
  lWorkspaceCounter = lWorkspaceCounter + 2
  End Select
  ReDim bytResult(LBound(bytWorkspace) To lWorkspaceCounter) As Byte
  If LBound(bytWorkspace) = 0 Then lWorkspaceCounter = lWorkspaceCounter + 1
  CopyMemory VarPtr(bytResult(LBound(bytResult))), VarPtr(bytWorkspace(LBound(bytWorkspace))), lWorkspaceCounter
  DecodeArray64 = bytResult
  End Function
  Public Function Encode64(ByRef sInput As String) As String
  If sInput = "" Then Exit Function
  Dim bytTemp() As Byte
  bytTemp = StrConv(sInput, vbFromUnicode)
  Encode64 = EncodeArray64(bytTemp)
  End Function
  Private Function EncodeArray64(ByRef bytInput() As Byte) As String
  On Error GoTo ErrorHandler
  Dim bytWorkspace() As Byte, bytResult() As Byte
  Dim bytCrLf(0 To 3) As Byte, lCounter As Long
  Dim lWorkspaceCounter As Long, lLineCounter As Long
  Dim lCompleteLines As Long, lBytesRemaining As Long
  Dim lpWorkSpace As Long, lpResult As Long
  Dim lpCrLf As Long
  If UBound(bytInput)  0 Then CopyMemory lpResult, lpWorkSpace, lBytesRemaining
  EncodeArray64 = Left$(bytResult, InStr(1, bytResult, Chr$(0)) - 1)
  End If
  Exit Function
  ErrorHandler:
  Erase bytResult
  EncodeArray64 = bytResult
  End Function
  Private Sub Class_Initialize()
  m_bytIndex(0) = 65 'Asc("A")
  m_bytIndex(1) = 66 'Asc("B")
  m_bytIndex(2) = 67 'Asc("C")
  m_bytIndex(3) = 68 'Asc("D")
  m_bytIndex(4) = 69 'Asc("E")
  m_bytIndex(5) = 70 'Asc("F")
  m_bytIndex(6) = 71 'Asc("G")
  m_bytIndex(7) = 72 'Asc("H")
  m_bytIndex(8) = 73 'Asc("I")
  m_bytIndex(9) = 74 'Asc("J")
  m_bytIndex(10) = 75 'Asc("K")
  m_bytIndex(11) = 76 'Asc("L")
  m_bytIndex(12) = 77 'Asc("M")
  m_bytIndex(13) = 78 'Asc("N")
  m_bytIndex(14) = 79 'Asc("O")
  m_bytIndex(15) = 80 'Asc("P")
  m_bytIndex(16) = 81 'Asc("Q")
  m_bytIndex(17) = 82 'Asc("R")
  m_bytIndex(18) = 83 'Asc("S")
  m_bytIndex(19) = 84 'Asc("T")
  m_bytIndex(20) = 85 'Asc("U")
  m_bytIndex(21) = 86 'Asc("V")
  m_bytIndex(22) = 87 'Asc("W")
  m_bytIndex(23) = 88 'Asc("X")
  m_bytIndex(24) = 89 'Asc("Y")
  m_bytIndex(25) = 90 'Asc("Z")
  m_bytIndex(26) = 97 'Asc("a")
  m_bytIndex(27) = 98 'Asc("b")
  m_bytIndex(28) = 99 'Asc("c")
  m_bytIndex(29) = 100 'Asc("d")
  m_bytIndex(30) = 101 'Asc("e")
  m_bytIndex(31) = 102 'Asc("f")
  m_bytIndex(32) = 103 'Asc("g")
  m_bytIndex(33) = 104 'Asc("h")
  m_bytIndex(34) = 105 'Asc("i")
  m_bytIndex(35) = 106 'Asc("j")
  m_bytIndex(36) = 107 'Asc("k")
  m_bytIndex(37) = 108 'Asc("l")
  m_bytIndex(38) = 109 'Asc("m")
  m_bytIndex(39) = 110 'Asc("n")
  m_bytIndex(40) = 111 'Asc("o")
  m_bytIndex(41) = 112 'Asc("p")
  m_bytIndex(42) = 113 'Asc("q")
  m_bytIndex(43) = 114 'Asc("r")
  m_bytIndex(44) = 115 'Asc("s")
  m_bytIndex(45) = 116 'Asc("t")
  m_bytIndex(46) = 117 'Asc("u")
  m_bytIndex(47) = 118 'Asc("v")
  m_bytIndex(48) = 119 'Asc("w")
  m_bytIndex(49) = 120 'Asc("x")
  m_bytIndex(50) = 121 'Asc("y")
  m_bytIndex(51) = 122 'Asc("z")
  m_bytIndex(52) = 48 'Asc("0")
  m_bytIndex(53) = 49 'Asc("1")
  m_bytIndex(54) = 50 'Asc("2")
  m_bytIndex(55) = 51 'Asc("3")
  m_bytIndex(56) = 52 'Asc("4")
  m_bytIndex(57) = 53 'Asc("5")
  m_bytIndex(58) = 54 'Asc("6")
  m_bytIndex(59) = 55 'Asc("7")
  m_bytIndex(60) = 56 'Asc("8")
  m_bytIndex(61) = 57 'Asc("9")
  m_bytIndex(62) = 43 'Asc("+")
  m_bytIndex(63) = 47 'Asc("/")
  m_bytReverseIndex(65) = 0 'Asc("A")
  m_bytReverseIndex(66) = 1 'Asc("B")
  m_bytReverseIndex(67) = 2 'Asc("C")
  m_bytReverseIndex(68) = 3 'Asc("D")
  m_bytReverseIndex(69) = 4 'Asc("E")
  m_bytReverseIndex(70) = 5 'Asc("F")
  m_bytReverseIndex(71) = 6 'Asc("G")
  m_bytReverseIndex(72) = 7 'Asc("H")
  m_bytReverseIndex(73) = 8 'Asc("I")
  m_bytReverseIndex(74) = 9 'Asc("J")
  m_bytReverseIndex(75) = 10 'Asc("K")
  m_bytReverseIndex(76) = 11 'Asc("L")
  m_bytReverseIndex(77) = 12 'Asc("M")
  m_bytReverseIndex(78) = 13 'Asc("N")
  m_bytReverseIndex(79) = 14 'Asc("O")
  m_bytReverseIndex(80) = 15 'Asc("P")
  m_bytReverseIndex(81) = 16 'Asc("Q")
  m_bytReverseIndex(82) = 17 'Asc("R")
  m_bytReverseIndex(83) = 18 'Asc("S")
  m_bytReverseIndex(84) = 19 'Asc("T")
  m_bytReverseIndex(85) = 20 'Asc("U")
  m_bytReverseIndex(86) = 21 'Asc("V")
  m_bytReverseIndex(87) = 22 'Asc("W")
  m_bytReverseIndex(88) = 23 'Asc("X")
  m_bytReverseIndex(89) = 24 'Asc("Y")
  m_bytReverseIndex(90) = 25 'Asc("Z")
  m_bytReverseIndex(97) = 26 'Asc("a")
  m_bytReverseIndex(98) = 27 'Asc("b")
  m_bytReverseIndex(99) = 28 'Asc("c")
  m_bytReverseIndex(100) = 29 'Asc("d")
  m_bytReverseIndex(101) = 30 'Asc("e")
  m_bytReverseIndex(102) = 31 'Asc("f")
  m_bytReverseIndex(103) = 32 'Asc("g")
  m_bytReverseIndex(104) = 33 'Asc("h")
  m_bytReverseIndex(105) = 34 'Asc("i")
  m_bytReverseIndex(106) = 35 'Asc("j")
  m_bytReverseIndex(107) = 36 'Asc("k")
  m_bytReverseIndex(108) = 37 'Asc("l")
  m_bytReverseIndex(109) = 38 'Asc("m")
  m_bytReverseIndex(110) = 39 'Asc("n")
  m_bytReverseIndex(111) = 40 'Asc("o")
  m_bytReverseIndex(112) = 41 'Asc("p")
  m_bytReverseIndex(113) = 42 'Asc("q")
  m_bytReverseIndex(114) = 43 'Asc("r")
  m_bytReverseIndex(115) = 44 'Asc("s")
  m_bytReverseIndex(116) = 45 'Asc("t")
  m_bytReverseIndex(117) = 46 'Asc("u")
  m_bytReverseIndex(118) = 47 'Asc("v")
  m_bytReverseIndex(119) = 48 'Asc("w")
  m_bytReverseIndex(120) = 49 'Asc("x")
  m_bytReverseIndex(121) = 50 'Asc("y")
  m_bytReverseIndex(122) = 51 'Asc("z")
  m_bytReverseIndex(48) = 52 'Asc("0")
  m_bytReverseIndex(49) = 53 'Asc("1")
  m_bytReverseIndex(50) = 54 'Asc("2")
  m_bytReverseIndex(51) = 55 'Asc("3")
  m_bytReverseIndex(52) = 56 'Asc("4")
  m_bytReverseIndex(53) = 57 'Asc("5")
  m_bytReverseIndex(54) = 58 'Asc("6")
  m_bytReverseIndex(55) = 59 'Asc("7")
  m_bytReverseIndex(56) = 60 'Asc("8")
  m_bytReverseIndex(57) = 61 'Asc("9")
  m_bytReverseIndex(43) = 62 'Asc("+")
  m_bytReverseIndex(47) = 63 'Asc("/")
  End Sub

base64 参考资料

       

http://www.phplamps.cn/html/php_production/200811/25-923.html

 

附图

上传图片 

互动百科的词条(含所附图片)系由网友上传,如果涉嫌侵权,请与客服联系,我们将按照法律之相关规定及时进行处理。如需转载,请注明来源于www.hudong.com

被引用: 本词条已被如下媒体引用 我来补充
开放分类: 我来补充
通信技术

讨论区

更多>>

编辑者

共3人协作

相关词条

ABC
正则表达式
UNICODE
IPTV
数字电视
Internet协议
JDBC
java数据库连接
IPv6
SAN
更多

Copyright © 2005-2009 hudong.com Ltd. All Rights Reserved. 互动在线 版权所有