什么是Base64?
按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)
Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:
BASE64编码表
索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 |
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 | ||
15 | P | 32 | g | 49 | x | ||
16 | Q | 33 | h | 50 | y |
转换例子:
C语言实现:
#include <stdio.h>
#include <string.h>typedef unsigned char BYTE;
/*====================================================================
Base64编码函数
btSrc指向被编码的数据缓冲区
iSrcLen被编码的数据的大小(字节)
btRet指向存放Base64编码的数据缓冲区
piRetLen指向存放Base64编码的数据缓冲区的长度
若btRet为NULL函数返回0,piRetLen传回btSrc的Base64编码所需缓冲区的大小
若btRet指向的缓冲区太小,函数返回-1
否则函数返回实际btSrc的Base64编码所需缓冲区的大小
=====================================================================*/
int EncodeBase64(BYTE *btSrc, int iSrcLen, BYTE *btRet, int *piRetLen) //Base64编码
{
int i = 0, j = 0, k = 0 ;
BYTE EncodeBase64Map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
i = (iSrcLen+2) / 3 * 4 ; //获取btSrc的Base64编码所需缓冲区的大小
if(btRet != NULL)
{
if(*piRetLen < i) //Base64编码所需缓冲区偏小
return -1 ;
*piRetLen = i ; //*piRetLen返回btSrc的Base64编码的缓冲区大小
}
else
{
*piRetLen = i ;
return 0 ;
}k = iSrcLen - iSrcLen % 3 ;
for(i=j=0; i<k; i+=3) //编码
{
btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
btRet[j++] = EncodeBase64Map[((btSrc[i]<<4) + (btSrc[i+1]>>4))&0x3F] ;
btRet[j++] = EncodeBase64Map[((btSrc[i+1]<<2) + (btSrc[i+2]>>6))&0x3F] ;
btRet[j++] = EncodeBase64Map[btSrc[i+2]&0x3F] ;
}
k = iSrcLen - k ;
if(1 == k)
{
btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
btRet[j++] = EncodeBase64Map[(btSrc[i]<<4)&0x3F] ;
btRet[j++] = btRet[j] = '=' ;
}
else if(2 == k)
{
btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
btRet[j++] = EncodeBase64Map[((btSrc[i]<<4) + (btSrc[i+1]>>4))&0x3F] ;
btRet[j++] = EncodeBase64Map[(btSrc[i+1]<<2)&0x3F] ;
btRet[j] = '=' ;
}return ++j ;
}/*====================================================================
Base64解码函数
btSrc指向被解码的数据缓冲区
iSrcLen被解码的数据的大小(字节)
btRet指向存放Base64解码的数据缓冲区
piRetLen指向存放Base64解码的数据缓冲区的长度
若btRet为NULL函数返回0,piRetLen传回btSrc的Base64解码所需缓冲区的大小
若btRet指向的缓冲区太小,函数返回-1
否则函数返回btSrc的Base64解码所需缓冲区的大小
=====================================================================*/
int DecodeBase64(BYTE *btSrc, int iSrcLen, BYTE *btRet, int *piRetLen) //Base64解码
{
int i = 0, j = 0 ;
BYTE EncodeBase64Map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
BYTE DecodeBase64Map[256] = {0} ;
for(j = iSrcLen; j>0 && '='==btSrc[j-1]; --j) ; //忽略=号
i = (j/4)*3+(j%4+1)/2; //计算解码后 字符串的长度
if(btRet != NULL)
{
if(*piRetLen < i) //Base64解码所需缓冲区偏小
return -1 ;
*piRetLen = i ; //*piRetLen返回btSrc的Base64解码的缓冲区大小
}
else
{
*piRetLen = i ;
return 0 ;
}j = sizeof(EncodeBase64Map) ;
for(i=0; i<j; ++i)
DecodeBase64Map[ EncodeBase64Map[i] ] = i ;
for(i=j=0; i<iSrcLen; i+=4)
{
btRet[j++] = DecodeBase64Map[btSrc[i ]] << 2 | DecodeBase64Map[btSrc[i+1]] >> 4 ;
btRet[j++] = DecodeBase64Map[btSrc[i+1]] << 4 | DecodeBase64Map[btSrc[i+2]] >> 2 ;
btRet[j++] = DecodeBase64Map[btSrc[i+2]] << 6 | DecodeBase64Map[btSrc[i+3]] ;
}return *piRetLen ;
}int main(void)
{
char str[128]={0} ;
char szTemp[128] = {0} ;
int iRetLen, i ;
printf("Base64编码:\n") ;
scanf("%s", str) ;
iRetLen = sizeof(szTemp) ;
EncodeBase64(str, strlen(str), szTemp, &iRetLen) ;
szTemp[iRetLen] = '\0' ;
printf("%s\n", szTemp) ;
printf("Base64解码:\n") ;
iRetLen = sizeof(szTemp) ;
scanf("%s", szTemp) ;
DecodeBase64(szTemp, strlen(szTemp), str, &iRetLen) ;
str[iRetLen] = '\0' ;
printf("%s\n", str) ;
for(i=0; i<iRetLen; ++i)
printf("%0x ", (unsigned char)(str[i])) ;
return 0 ;
}
已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/decryption/158.html 欢迎订阅Eddy Blog。