找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 4508|回复: 0

[算法] Base64编解码规则及代码实现(原创,欢迎提意见和建议)

[复制链接]

1214

主题

352

回帖

11

精华

管理员

菜鸟

积分
93755

贡献奖关注奖人气王精英奖乐于助人勋章

发表于 2010-1-27 21:04:55 | 显示全部楼层 |阅读模式
  1. 编码规则
  2. Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。这样就把一个3字节为一组的数据重新编码成了4个字节。当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。这时在最后一组填充1到2个0字节。并在最后编码完成后在结尾替换1到2个“=”,即替换末尾的1~2个A,也就是补位。
  3. 例:将对ABC进行BASE64编码
  4. 首先取ABC对应的ASCII码值。A(65)B(66)C(67)。
  5. 再取二进制值A(01000001)B(01000010)C(01000011),然后把这三个字节的二进制码接起来(010000010100001001000011),再以6位为单位分成4个数据块并在最高位填充两个0后形成4个字节的编码后的值(00010000)(00010100)(00001001)(00000011)。蓝色部分为真实数据。再把这四个字节数据转化成10进制数得(16)(20)(9)(3)。最后根据BASE64给出的64个基本字符表,查出对应的ASCII码字符(Q)(U)(J)(D)。这里的值实际就是数据在字符表中的索引。
  6. 注BASE64字符表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

  7. 解码规则:根据编码的规则进行逆向解码

  8. 主题思想体现了 移位,& ,^ 操作 来控制2进制数据

  9. 代码实现:

  10. // Base64.cpp : Defines the entry point for the console application.
  11. //

  12. #include "stdafx.h"
  13. #include "wtypes.h"
  14. #include "string.h"

  15. typedef struct _ThreeBytes_
  16. {
  17. _ThreeBytes_()
  18. {
  19. memset((void*)&byte1,0,1);
  20. memset((void*)&byte2,0,1);
  21. memset((void*)&byte3,0,1);
  22. }
  23. BYTE byte1;
  24. BYTE byte2;
  25. BYTE byte3;

  26. }ThreeBytes,*LPThreeBytes;

  27. typedef struct _FourBytes_
  28. {
  29. _FourBytes_()
  30. {
  31. memset((void*)&byte1,0,1);
  32. memset((void*)&byte2,0,1);
  33. memset((void*)&byte3,0,1);
  34. memset((void*)&byte4,0,1);
  35. }
  36. BYTE byte1;
  37. BYTE byte2;
  38. BYTE byte3;
  39. BYTE byte4;

  40. }FourBytes,*LPFourBytes;

  41. char strBase64[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};

  42. int FindIndex(char c)
  43. {
  44. for (int i=0; i<64; i++)
  45. {
  46. if (strBase64[i] == c)
  47. {
  48. return i;
  49. }
  50. }
  51. return -1;
  52. }
  53. //规则转换函数1
  54. void Translate3To4(LPThreeBytes pThreeBytes,LPFourBytes pFourBytes)
  55. {
  56. pFourBytes->byte1 = (pThreeBytes->byte1>>2)&0x3F;
  57. pFourBytes->byte2 = ((pThreeBytes->byte2>>4)&0x0F)^((pThreeBytes->byte1<<4)&0x30);
  58. pFourBytes->byte3 = ((((pThreeBytes->byte2<<4)&0xF0)^((pThreeBytes->byte3>>4)&0x0C))>>2)&0x3F;
  59. pFourBytes->byte4 = pThreeBytes->byte3&0x3F;

  60. pFourBytes->byte1 = (BYTE)strBase64[pFourBytes->byte1];
  61. pFourBytes->byte2 = (BYTE)strBase64[pFourBytes->byte2];
  62. pFourBytes->byte3 = (BYTE)strBase64[pFourBytes->byte3];
  63. pFourBytes->byte4 = (BYTE)strBase64[pFourBytes->byte4];
  64. }
  65. //规则转换函数2
  66. void Translate4To3(LPFourBytes pFourBytes,LPThreeBytes pThreeBytes)
  67. {
  68. FourBytes tempFourBytes;
  69. //memcpy((void *)&tempFourBytes,pFourBytes,sizeof(FourBytes));
  70. tempFourBytes.byte1 = (BYTE)FindIndex(pFourBytes->byte1);
  71. tempFourBytes.byte2 = (BYTE)FindIndex(pFourBytes->byte2);
  72. tempFourBytes.byte3 = (BYTE)FindIndex(pFourBytes->byte3);
  73. tempFourBytes.byte4 = (BYTE)FindIndex(pFourBytes->byte4);

  74. pThreeBytes->byte1 = (tempFourBytes.byte1<<2&0xFC)^(tempFourBytes.byte2>>4&0x03);
  75. pThreeBytes->byte2 = (tempFourBytes.byte2<<4&0xF0)^(tempFourBytes.byte3>>2&0x0F);
  76. pThreeBytes->byte3 = (tempFourBytes.byte3<<6&0xC0)^(tempFourBytes.byte4&0x3F);
  77. }
  78. //编码函数
  79. void EncodeBase64(char *strSource, int nSourceLen, char *strDest)
  80. {

  81. if (strSource == NULL||nSourceLen<1)
  82. {
  83. return;
  84. }
  85. char *pSource = strSource;
  86. char *pDest = strDest;
  87. ThreeBytes tempThreeBytes;
  88. FourBytes tempFourBytes;
  89. int nPack = nSourceLen/3;
  90. int nRemainder = nSourceLen%3;

  91. for (int i=0; i<nPack; i++)
  92. {
  93. memset((void *)&tempThreeBytes,0,sizeof(tempThreeBytes));
  94. memset((void *)&tempFourBytes,0,sizeof(tempFourBytes));
  95. memcpy((void *)&tempThreeBytes,pSource,sizeof(tempThreeBytes));
  96. Translate3To4(&tempThreeBytes,&tempFourBytes);
  97. memcpy(pDest,(void *)&tempFourBytes,sizeof(tempFourBytes));
  98. pSource += sizeof(tempThreeBytes);
  99. pDest += sizeof(tempFourBytes);
  100. }

  101. if (nRemainder == 0)
  102. {
  103. return;
  104. }
  105. else if(nRemainder == 1)
  106. {
  107. memset((void *)&tempThreeBytes,0,sizeof(tempThreeBytes));
  108. memset((void *)&tempFourBytes,0,sizeof(tempFourBytes));
  109. tempThreeBytes.byte1 = strSource[nSourceLen - 1];
  110. tempThreeBytes.byte2 = 0;
  111. tempThreeBytes.byte3 = 0;
  112. Translate3To4(&tempThreeBytes,&tempFourBytes);
  113. memcpy(pDest,(void *)&tempFourBytes,sizeof(tempFourBytes));
  114. pDest += sizeof(tempFourBytes);
  115. pDest -=2;
  116. *pDest = '=';
  117. pDest++;
  118. *pDest = '=';
  119. }
  120. else
  121. {
  122. memset((void *)&tempThreeBytes,0,sizeof(tempThreeBytes));
  123. memset((void *)&tempFourBytes,0,sizeof(tempFourBytes));
  124. tempThreeBytes.byte1 = strSource[nSourceLen - 2];
  125. tempThreeBytes.byte2 = strSource[nSourceLen - 1];
  126. tempThreeBytes.byte3 = 0;
  127. Translate3To4(&tempThreeBytes,&tempFourBytes);
  128. memcpy(pDest,(void *)&tempFourBytes,sizeof(tempFourBytes));
  129. pDest += sizeof(tempFourBytes);
  130. pDest --;
  131. *pDest = '=';
  132. }

  133. }
  134. //解码函数
  135. void DecodeBase64(char *strSource, int nSourceLen, char *strDest)
  136. {
  137. if (strSource == NULL||nSourceLen<1)
  138. {
  139. return;
  140. }
  141. char *pSource = strSource;
  142. char *pDest = strDest;
  143. ThreeBytes tempThreeBytes;
  144. FourBytes tempFourBytes;
  145. int nPack = nSourceLen/4;
  146. for (int i=0; i<nPack-1; i++)
  147. {
  148. memset((void *)&tempThreeBytes,0,sizeof(tempThreeBytes));
  149. memset((void *)&tempFourBytes,0,sizeof(tempFourBytes));
  150. memcpy((void *)&tempFourBytes,pSource,sizeof(tempFourBytes));
  151. Translate4To3(&tempFourBytes,&tempThreeBytes);
  152. memcpy(pDest,(void *)&tempThreeBytes,sizeof(tempThreeBytes));
  153. pSource += sizeof(tempFourBytes);
  154. pDest += sizeof(tempThreeBytes);
  155. }
  156. //有2个等号
  157. if ((nSourceLen>1)&&(strSource[nSourceLen - 2]=='='))
  158. {
  159. memset((void *)&tempThreeBytes,0,sizeof(tempThreeBytes));
  160. memset((void *)&tempFourBytes,0,sizeof(tempFourBytes));
  161. memcpy((void *)&tempFourBytes,pSource,sizeof(tempFourBytes));

  162. tempThreeBytes.byte1 = ((BYTE)FindIndex(tempFourBytes.byte1)<<2&0xFC)^((BYTE)FindIndex(tempFourBytes.byte2)>>4&0x03);
  163. memcpy(pDest,(void *)&tempThreeBytes,1);
  164. return;
  165. }
  166. //有1个等号
  167. if (strSource[nSourceLen - 1] == '=')
  168. {
  169. memset((void *)&tempThreeBytes,0,sizeof(tempThreeBytes));
  170. memset((void *)&tempFourBytes,0,sizeof(tempFourBytes));
  171. memcpy((void *)&tempFourBytes,pSource,sizeof(tempFourBytes));

  172. tempThreeBytes.byte1 = ((BYTE)FindIndex(tempFourBytes.byte1)<<2&0xFC)^((BYTE)FindIndex(tempFourBytes.byte2)>>4&0x03);
  173. tempThreeBytes.byte2 = ((BYTE)FindIndex(tempFourBytes.byte2)<<4&0xF0)^((BYTE)FindIndex(tempFourBytes.byte3)>>2&0x0F);
  174. memcpy(pDest,(void *)&tempThreeBytes,2);
  175. return;
  176. }
  177. //没等号 此时少做了一次循环 再补上
  178. memset((void *)&tempThreeBytes,0,sizeof(tempThreeBytes));
  179. memset((void *)&tempFourBytes,0,sizeof(tempFourBytes));
  180. memcpy((void *)&tempFourBytes,pSource,sizeof(tempFourBytes));
  181. Translate4To3(&tempFourBytes,&tempThreeBytes);
  182. memcpy(pDest,(void *)&tempThreeBytes,sizeof(tempThreeBytes));
  183. // pSource += sizeof(tempFourBytes);
  184. // pDest += sizeof(tempThreeBytes);
  185. }
  186. int main(int argc, char* argv[])
  187. {
  188. printf("编码******************************************\n");
  189. char strInput[500] = {"娃哈哈"};
  190. printf(""%s" Base64编码为:",strInput);
  191. char strOutput[500] = {0};
  192. EncodeBase64(strInput,strlen(strInput),strOutput);
  193. printf("%s\n",strOutput);

  194. printf("解码******************************************\n");
  195. memset(strInput,0,sizeof(char)*500);
  196. printf(""%s" Base64解码为:",strOutput);
  197. DecodeBase64(strOutput,strlen(strOutput),strInput);
  198. printf("%s\n",strInput);
  199. return 0;
  200. }
复制代码


来源:http://hi.baidu.com/blueapple_c/ ... b6342ecffca38b.html
【VB】QQ群:1422505加的请打上VB好友
【易语言】QQ群:9531809  或 177048
【FOXPRO】QQ群:6580324  或 33659603
【C/C++/VC】QQ群:3777552
【NiceBasic】QQ群:3703755
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表