Base64编码解码算法 桃扇骨 2022-08-13 13:36 350阅读 0赞 Base64不是什么新奇的算法了,不过如果你没从事过页面开发(或者说动态页面开发,尤其是邮箱服务),你都不怎么了解过,只是听起来很熟悉。 对于黑客来说,Base64与MD5算法有着同样的位置,因为电子邮箱(e-mail)正文就是base64编码的。 那么,我们就一起来深入的探讨一下这个东东吧。 对于一种算法,与其问“它是什么?”,不如问“它实现了什么?” Base64实现了:**将任意字节转为可读字符的编码。** 我们知道,除了页面上的文本,计算机中的数据还有很多是不可见的。那么我们再扯一扯编码的问题吧。 通俗的说,编码就是**给某个文字符号边上一个数字序号**,计算机在现实这个文字符号(字符)的时候,根据这个序号到字库中查找对应的点阵或矢量数据, 在显示器上“画”出来。(关于点阵和矢量我们就不扯了,不然就真的太远了。) 起初的字符编码,没有把汉字、日文、朝鲜文和其他文字包括在内,只有26个英文字母的大小写和10个阿拉伯数字。加上一些控制字符和空格,用一个字节 就能够完全的编码了。(不要告诉我你不知道2的7次方和2的8次方是多少,一个技术人员为这样的问题困扰简直是一种耻辱。) 然而,世界上除了文字还有数据,比如图片、压缩文件、程序等等都是**二进制文件**,这些文件一样以**字节**为单位存储数据,这些字节往往不仅仅是2的7次方以内 的可显示的文字字符编码,还有可能是大于127(有符号数小于0)的字节,这些字节没办法用字符显示出来,Base64就是通过某种算法将他们显示出来。 \*那么,Base64加密是安全的吗? 没有绝对安全的加密,Base64不是为了安全,而是为了显示。而且Base64是可逆的,也就是说,通过简单的解密就能得到原文。其实即便是不可逆的MD5算法, 也可以通过明文数据库找出可能的原文(睡到知道e10adc3949ba59abbe56e057f20f883e的原文就是123456)。 \*那么,Base64是怎么实现的呢? 其实很简单,不过为了URL等特殊用处,Base64选择了以下64个字符作为密文显示,着64个字符都是可显示的,他们是: **ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/** 如果密文有不属于他们的字符,那么不是Base64编码或者是山寨版的。 一眼看去就知道是26个字母大小写和数字,加上“+”“/”两个符号,“?\*-”由于正则表达式的问题,没有选用,而空格和回车这些是不能显示的。 Base64处理的过程是,以3个字节为一组(3个字节就是24位嘛),每6位扩展成8位得到4个字节(就是32位): 11111111 11111111 11111111 -> 111111 111111 111111 111111 -> 00111111 00111111 00111111 00111111 那么,得到的每一个字节,最大也就是2的6次方。也许你说:哇,小于2的7次方,可以显示了。 其实不是,得到的这2的6次方式上面那一串字符的索引,也就是说每个字节的值只是代表它在密文表中的位置,比如 字符“a”的编码是97, 用16进制表示是0x61(VB表示为&H61),二进制:01100001,因为不足3位,补0得到 00011000 00010000 000…… 前两个字节是十进制的24 和 16,那么对应那一串字符中的第24个字符和第16个字符为:YQ(索引从0开始算),那么单独“a”的Base64编码为 YQ==(不足3为的每个字符直接转为“=”),简单吧! 有了算法,解码的过程就各位聪明特达的程序员取思考思考吧,最后**C/C++**版的**编码**和**解码**代码贴上! **\[cpp\]** [view plain][] [copy][view plain] 1. /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 2. Base64编码解码算法 C语言源代码 3. by 虎胆游侠 http://blog.csdn.net/prsniper 4. \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ 5. \#include <stdio.h> //注意哦,VC中""是当前路径,<>是系统路径 6. \#include <windows.h> 7. 8. **const** **char** BASE\_CODE\[\] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 9. 10. //编码,参数:要编码的字符串指针,解码后存放的位置(编码字串长度的4/3),要编码的字符串长度 ->返回结果长度 11. **int** fnBase64Encode(**char** \*lpString, **char** \*lpBuffer, **int** sLen) 12. \{ **register** **int** vLen = 0; //寄存器局部变量,提速 13. **while**(sLen > 0) //处理整个字符串 14. \{ \*lpBuffer++ = BASE\_CODE\[(lpString\[0\] >> 2 ) & 0x3F\]; //右移两位,与00111111是防止溢出,自加 15. **if**(sLen > 2) //够3个字符 16. \{ \*lpBuffer++ = BASE\_CODE\[((lpString\[0\] & 3) << 4) | (lpString\[1\] >> 4)\]; 17. \*lpBuffer++ = BASE\_CODE\[((lpString\[1\] & 0xF) << 2) | (lpString\[2\] >> 6)\]; 18. \*lpBuffer++ = BASE\_CODE\[lpString\[2\] & 0x3F\]; 19. \}**else** 20. \{ **switch**(sLen) //追加“=” 21. \{ **case** 1: 22. \*lpBuffer ++ = BASE\_CODE\[(lpString\[0\] & 3) << 4 \]; 23. \*lpBuffer ++ = '='; 24. \*lpBuffer ++ = '='; 25. **break**; 26. **case** 2: 27. \*lpBuffer ++ = BASE\_CODE\[((lpString\[0\] & 3) << 4) | (lpString\[1\] >> 4)\]; 28. \*lpBuffer ++ = BASE\_CODE\[((lpString\[1\] & 0x0F) << 2) | (lpString\[2\] >> 6)\]; 29. \*lpBuffer ++ = '='; 30. **break**; 31. \} 32. \} 33. lpString += 3; 34. sLen -= 3; 35. vLen +=4; 36. \} 37. \*lpBuffer = 0; 38. **return** vLen; 39. \} 40. 41. //子函数 - 取密文的索引 42. **inline** **char** GetCharIndex(**char** c) //内联函数可以省去函数调用过程,提速 43. \{ **if**((c >= 'A') && (c <= 'Z')) 44. \{ **return** c - 'A'; 45. \}**else** **if**((c >= 'a') && (c <= 'z')) 46. \{ **return** c - 'a' + 26; 47. \}**else** **if**((c >= '0') && (c <= '9')) 48. \{ **return** c - '0' + 52; 49. \}**else** **if**(c == '+') 50. \{ **return** 62; 51. \}**else** **if**(c == '/') 52. \{ **return** 63; 53. \}**else** **if**(c == '=') 54. \{ **return** 0; 55. \} 56. **return** 0; 57. \} 58. 59. //解码,参数:结果,密文,密文长度 60. **int** fnBase64Decode(**char** \*lpString, **char** \*lpSrc, **int** sLen) //解码函数 61. \{ **static** **char** lpCode\[4\]; 62. **register** **int** vLen = 0; 63. **if**(sLen % 4) //Base64编码长度必定是4的倍数,包括'=' 64. \{ lpString\[0\] = '\\0'; 65. **return** -1; 66. \} 67. **while**(sLen > 2) //不足三个字符,忽略 68. \{ lpCode\[0\] = GetCharIndex(lpSrc\[0\]); 69. lpCode\[1\] = GetCharIndex(lpSrc\[1\]); 70. lpCode\[2\] = GetCharIndex(lpSrc\[2\]); 71. lpCode\[3\] = GetCharIndex(lpSrc\[3\]); 72. 73. \*lpString++ = (lpCode\[0\] << 2) | (lpCode\[1\] >> 4); 74. \*lpString++ = (lpCode\[1\] << 4) | (lpCode\[2\] >> 2); 75. \*lpString++ = (lpCode\[2\] << 6) | (lpCode\[3\]); 76. 77. lpSrc += 4; 78. sLen -= 4; 79. vLen += 3; 80. \} 81. **return** vLen; 82. \} 83. 84. **void** main() //主函数,测试函数 85. \{ **char** s\[\] = "a", str\[32\]; 86. **int** l = strlen(s); 87. **int** i = fnBase64Encode(s, str, l); 88. printf("fnBase64Encode(\\"%s\\", str, %d) = \\"%s\\";\\n", s, l, str); 89. l = fnBase64Decode(s, str, i); 90. printf("fnBase64Decode(\\"%s\\", s, %d) = \\"%s\\";\\n", str, i, s); 91. \} 编译为控制台应用程序,运行如图: ![Base64编解码源码运行效果][Base64] 原文地址:[http://blog.csdn.net/prsniper/article/details/7097643][http_blog.csdn.net_prsniper_article_details_7097643] [view plain]: http://blog.csdn.net/prsniper/article/details/7097643# [Base64]: /images/20220810/85642508841d41c4a811a82abeec08e7.png [http_blog.csdn.net_prsniper_article_details_7097643]: http://blog.csdn.net/prsniper/article/details/7097643
还没有评论,来说两句吧...