关于Base64编码(转载)

关于Base64 编码( 转载)
 
feijunjun(军仔)  2002-05-02 15:16:52发表.
把一三个字符的24位码转换成四个高两位为0的ASCII码,其实也就是四个字母[取自于码表: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/]
如 10101101 10111010                    01110110
   -----------------                    --------
   这里是一个中文字[8位高一位不为0]       这是一个英文字母[高一位为0]
可以转成
00101011 00011011 00101001 00110110
  ------   ------   ------   ------ =>这里正好是上面的 那27位值  
  2B       1B       2A       36
 
以下是 10 进制码表中的索引
  43       27       42       54
对应码表中的值
  r        b        q        2
 
所以上面的24位编码,编码后值为 rbq2
 
解码同理把rbq2的二进制位连接上再重组得到三个 8位值,得出原码
很明白了吧,呵呵
 
====================================================================
soundbug(兼职乞丐)  2002-03-22 09:42:53发表
我收藏的一篇文章:
-------------------------------------------------------------------
一般大多数包含"="的不是"Base64"编码格式,只有"quoted-printable"编码格式才会经
常出现"="虽然都是MIME编码,但是算法不一样
,"quoted-printable"的我不太清楚.讲一下Base64的吧.
 
Base64算法是把3个8位字符(24)转换成4个6位字符(32),因此编码后的长度会扩大1/3,
进行编码转换时需要用到一张Base64的编码表:
                            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
在VB中可以简单的将其保存为一个常量:
Private Const Base64Table =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
 
编码过程是这样的,第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据
这个数值取到表上相应的字符,就是第一个目标字符
,然后将第一个字符左移6位加上第二个字符右移4位,即获得第二个目标字符,再将第二
个字符左移4位加上第三个字符右移6位,获得第三个
目标字符,最后取第三个字符的右6位即获得第四个目标字符.
 
例如我们取一个简单的字符串"TEST..."
将其用SourceByte = StrConv(SourceText, vbFromUnicode)转换后获得二进制数组:
T         E         S         T            ...
84        69        83        84           ...
01010100  01000101  01010011  01010100     ...
01010100/01000101/01010011/01010100
01010100010001010101001101010100
转换后:
01010100010001010101001101010100
010101/000100/010101/010011/010101/00
010101    000100    010101    010011    010101    00....
21        4         21        19        21        ...
V         E         V         T         V         ...
最后得到的就是"VEVTV..."
 
对于第一个目标字符我们可以这样做:
(SourceByte(1) and 252)/4
第二个:
(SourceByte(1) and 3)*64 + (SourceByte(2) and 240)/16
第三个:
(SourceByte(2) and 15)*16 + (SourceByte(3) and 48)/64
第四个:
(SourceByte(3) and 63)
 
Base64解码过程正好相反,我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详
细情况请自己查找,我上面那张表就摘自
<RFC1521#
MIME (Multipurpose Internet Mail Extensions)
Part One: Mechanisms for Specifying and Describing the Format of Internet
Message Bodies>
 
====================================================================
xuying()         2002-08-21 12:10:55发表
MIME/BASE64 的算法很简单,它将字符流顺序放入一个 24 位的缓冲区,缺字符的地方补零。然后将缓冲区截断成为 4 个部分,高位在先,每个部分 6 位,用下面的 64 个字符重新表示:“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop qrstuvwxyz0123456789+/”。如果输入只有一个或两个字节,那么输出将用等号“=”补足。这可以隔断附加的信息造成编码的混乱。这就是BASE64。
 
UEsDBBQAAgAIAEapPiS/mrkHoQEAAEECAAAMAAAAYWNhZDd+dWUudHh0dVFRb5swGHyPlP9Q5Iet
TUICzCUJASTiFuIQhwbHRJnUqmRsndqmVQO0CsK/fXbRVvVh+AV9vrvv7txunYiPV8rAW3n33w5B
R9FAN3ld34Axr9OHIjtkt7wC3bmKHD+zznjteTGvjBnVFGCdxz265XW7dfI+ZVFyRjegO3hix8nl
fGcdjeLqy/rGTp0Sj+Jp8Djho9oIWRSX0IYIwwmWbF4RHKYK0ByCaI9u4u3HukYZIvE32+fZyz7L
 
BASE64编码转换原理
 
Base64编码其实是将3个8位字节转换为4个6位字节,( 3*8 = 4*6 = 24 ) 这4个六位字节
其实仍然是8位,只不过高两位被设置为0. 当一个字节只有6位有效时,它的取值空间为0
到 2的6次方减1 即63,也就是说被转换的Base64编码的每一个编码的取值空间为(0~63)
事实上,0~63之间的ASCII码有许多不可见字符,所以应该再做一个映射,映射表为
‘A‘ ~ ‘Z‘ ? ASCII(0 ~ 25)
‘a’ ~ ‘z‘ ? ASCII(26 ~ 51)
‘0’ ~ ‘9‘ ? ASCII(52 ~ 61)
‘+‘ ? ASCII(62)
‘/‘ ? ASCII(63)
这样就可以将3个8位字节,转换为4个可见字符。
具体的字节拆分方法为:(图(画得不好,领会精神 :-))
aaaaaabb ccccdddd eeffffff
~~~~~~~~ ~~~~~~~~ ~~~~~~~~
字节 1 字节 2 字节 3
||
//
00aaaaaa 00bbcccc 00ddddee 00ffffff
 
注:上面的三个字节位原文,下面四个字节为Base64编码,其前两位均为0。
这样拆分的时候,原文的字节数量应该是3的倍数,当这个条件不能满足时,用全零字节
补足,转化时Base64编码用=号代替,这就是为什么有些Base64编码以一个或两个等号结
束的原因,但等号最多有两个,因为:如果F(origin)代表原文的字节数,F(remain)代
表余数,则
F(remain) = F(origin) MOD 3 成立。
所以F(remain)的可能取值为0,1,2.
如果设 n = [F(origin) – F(remain)] / 3
当F(remain) = 0 时,恰好转换为4*n个字节的Base64编码。
当F(remain) = 1 时,由于一个原文字节可以拆分为属于两个Base64编码的字节,为了
让Base64编码是4的倍数,所以应该为补2个等号。
当F(remain) = 2 时,由于两个原文字节可以拆分为属于3个Base64编码的字节,同理,
应该补上一个等号。
 
 
====================================================================
duz()         2001-04-14 01:05:00 发表
#include <windows.h>
 
#define BaseCode64Size(nInputSize)       ((nInputSize+2)/3*4)
#define DeBaseCod64Size(nInputSize)       ((nInputSize/4)*3)
BOOL DecodeBase64(const char *pszIn, BYTE *pszOut, int *nOutLen);
BOOL EncodeBase64(const BYTE* pszIn, int nInLen, char* pszOut);
int CodeFromChar(char x);
 
const char m_base64tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                     "abcdefghijklmnopqrstuvwxyz0123456789+/";
 
int CodeFromChar(char x)
{
       if('A'<=x&&x<='Z')
              return x-'A';
       if('a'<=x&&x<='z')
              return x-'a'+26;
       if('0'<=x&&x<='9')
              return x-'0'+52;
       if(x=='+')
              return 62;
       if(x=='/')
              return 63;
       if(x=='='||x=='/r'||x=='/n')
              return 64;
       return -1;
}
 
int sizeofstr(const char *str)
{
       int i=0;
       while(str[i++]);
       return i-1;
}
 
BOOL DecodeBase64(const char *pszIn, BYTE *pszOut, int *nOutLen)
{
       if(IsBadStringPtr(pszIn,0xFFFFFFFF))
              return FALSE;
      
       int len=sizeofstr(pszIn);
       int OutSize=DeBaseCod64Size(len);
       if(IsBadWritePtr(pszOut,OutSize))
              return FALSE;
       int nInPos=0;
       int nOutPos=0;
       for(int i=0;pszIn[nInPos]!='/0';i++)
       {
              int c1,c2,c3,c4;
              if((c1=CodeFromChar(pszIn[nInPos++]))==-1)
                     return FALSE;
              if(c1==64)
                     continue;
              if((c2=CodeFromChar(pszIn[nInPos++]))==-1)
                     return FALSE;
              if(c2==64)
                     return FALSE;
              if((c3=CodeFromChar(pszIn[nInPos++]))==-1)
                     return FALSE;
              if(c3==64)
                     return FALSE;
              if((c4=CodeFromChar(pszIn[nInPos++]))==-1)
                     return FALSE;
              if(c4==64)
                     return FALSE;
              if(c1==-1||c2==-1||c3==-1||c4==-1)
              {
                     return FALSE;
              }
              if(c1==64||c2==64||c3==64||c4==64)
              {
                     nInPos-=3;
                     return FALSE;
              }
              pszOut[nOutPos++]=(BYTE)((c1<<2)|(c2>>4));
              pszOut[nOutPos++]=(BYTE)((c2<<4)|(c3>>2));
              pszOut[nOutPos++]=(BYTE)((c3<<6)|(c4));
       }
       *nOutLen=nOutPos;
       return TRUE;
}
 
BOOL EncodeBase64(const BYTE* pszIn, int nInLen, char* pszOut)
{
       int nOutLen;
       if(IsBadReadPtr(pszIn,nInLen))
              return FALSE;
       nOutLen=BaseCode64Size(nInLen)+1;
       if(IsBadWritePtr(pszOut,nOutLen))
              return FALSE;
       int nInPos=0;
       int nOutPos=0;
       for (int i=0; i<nInLen/3; ++i)
       {
              //Get the next 2 characters
              int c1 = (int)pszIn[nInPos++];
              int c2 = (int)pszIn[nInPos++];
              int c3 = (int)pszIn[nInPos++];
 
              //Encode into the 4 6 bit characters
              pszOut[nOutPos++] = m_base64tab[(c1 & 0xFC) >> 2];
              pszOut[nOutPos++] = m_base64tab[((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4)];
              pszOut[nOutPos++] = m_base64tab[((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6)];
              pszOut[nOutPos++] = m_base64tab[c3 & 0x3F];
       }
       switch (nInLen % 3)
       {
              case 0:
              {
                     pszOut[nOutPos++]='/0';
                     break;
              }
              case 1:
              {
                     int c1 = pszIn[nInPos];
                     pszOut[nOutPos++] = m_base64tab[(c1 & 0xFC) >> 2];
                     pszOut[nOutPos++] = m_base64tab[((c1 & 0x03) << 4)];
                     pszOut[nOutPos++] = '=';
                     pszOut[nOutPos++] = '=';
                     pszOut[nOutPos++] = '/0';
                     break;
              }
              case 2:
              {
                     int c1 = pszIn[nInPos++] ;
                     int c2 = pszIn[nInPos] ;
                     pszOut[nOutPos++] = m_base64tab[(c1 & 0xFC) >> 2];
                     pszOut[nOutPos++] = m_base64tab[((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4)];
                     pszOut[nOutPos++] = m_base64tab[((c2 & 0x0F) << 2)];
                     pszOut[nOutPos++] = '=';
                     pszOut[nOutPos++] = '/0';
                     break;
              }
              default:
              {
                     //This is impossible, so release memory is not needed
                     return FALSE;
              }
       }
       return TRUE;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值