C语言实现Base64编码转码
关于Base64的介绍有两篇文章已经做得非常好了:一篇是维基百科Base64的词条,如果被Q可以看本文👇摘录维基百科Base64;另一篇是阮一峰的Base64笔记.
说一说C语言的实现吧,其实维基百科给出了C语言的实现了,但是它用以处理File,当然原理都是一样的,File的处理其实可以放在外面做好.
另外,根据Base64介绍可以看出来它以6比特为一个单元,而常规1字节为8比特,所以Base64编码的核心其实是位操作的过程.
好了,可以放代码了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
|
在调用的时候一定要注意malloc的大小.
这个Base64其实我们经常在用,只是没有留意而已.比如P2P下载工具*雷就用Base64编码了很多资源,我这里找了一个电影<独立日:卷土重来.BD1280高清国英双语特效中英双字>下载链接是这样的: thu*der://QUFlZDJrOi8vfGZpbGV8JUU3JThCJUFDJUU3JUFCJThCJUU2JTk3JUE1JUVGJUJDJTlBJUU1JThEJUI3JUU1JTlDJTlGJUU5JTg3JThEJUU2JTlEJUE1LkJEMTI4MCVFOSVBQiU5OCVFNiVCOCU4NSVFNSU5QiVCRCVFOCU4QiVCMSVFNSU4RiU4QyVFOCVBRiVBRCVFNyU4OSVCOSVFNiU5NSU4OCVFNCVCOCVBRCVFOCU4QiVCMSVFNSU4RiU4QyVFNSVBRCU5Ny5tcDR8MTY4MzQwNTM1NXxGRjRGNDc2MzE4REVEMzg3MEQxRkJGNENCOTU5MEE0NHxoPTdFU1BGTEpKQ1ZZWkE3UUU0R0JERkpOVUozU1pWRDNZfC9aWg== 看似挺聪明的做法,自定义了协议头,后面一大串晕晕乎乎的不知道是什么东西,一般的资源都是带文件名至少能看到后缀名啥的,不过看到最后又两个 '=' 字符,这个就很明显是这边文章的主题Base64,在看这里面的字符都在Base64定义的字符内 就可以认定这个是Base64编码后的链接.如果你恰好没装*雷,也不想装*雷(这货会偷偷上传文件,别问我怎么知道的,亲手抓到的),就可以把协议头后面的一大串字符串拷贝出来,decode一下可以得到 AAed2k://|file|%E7%8B%AC%E7%AB%8B%E6%97%A5%EF%BC%9A%E5%8D%B7%E5%9C%9F%E9%87%8D%E6%9D%A5.BD1280%E9%AB%98%E6%B8%85%E5%9B%BD%E8%8B%B1%E5%8F%8C%E8%AF%AD%E7%89%B9%E6%95%88%E4%B8%AD%E8%8B%B1%E5%8F%8C%E5%AD%97.mp4|1683405355|FF4F476318DED3870D1FBF4CB9590A44|h=7ESPFLJJCVYZA7QE4GBDFJNUJ3SZVD3Y|/ZZ 去掉 AA 剩下 ed2k://|file|%E7%8B%AC%E7%AB%8B%E6%97%A5%EF%BC%9A%E5%8D%B7%E5%9C%9F%E9%87%8D%E6%9D%A5.BD1280%E9%AB%98%E6%B8%85%E5%9B%BD%E8%8B%B1%E5%8F%8C%E8%AF%AD%E7%89%B9%E6%95%88%E4%B8%AD%E8%8B%B1%E5%8F%8C%E5%AD%97.mp4|1683405355|FF4F476318DED3870D1FBF4CB9590A44|h=7ESPFLJJCVYZA7QE4GBDFJNUJ3SZVD3Y|/ZZ 这下认得了吧.用想用的下载工具下载吧.当然也可以用在线的base64 转码工具.
以下内容摘自维基百科
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。三个字节有24个比特,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后binhex的版本使用不同的64字符集来代表6个二进制数字,但是它们不叫Base64。
Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email、在XML中存储复杂数据。
目录
[隐藏]
MIME[编辑]
在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。使用时,在传输编码方式中指定base64。使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符,等号“=”用来作为后缀用途。
完整的base64定义可见RFC 1421和RFC 2045。编码后的数据比原始数据略长,为原来的43。在电子邮件中,根据RFC 822规定,每76个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的135.1%。
转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲器中剩下的bit用0补足。然后,每次取出6(因为26=64)个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。
当原数据长度不是3的整数倍时, 如果最后剩下一个输入数据,在编码结果后加2个“=”;如果最后剩下两个输入数据,编码结果后加1个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证数据还原的正确性。
- 编码“Man”
文本 | M | a | n | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ASCII编码 | 77 | 97 | 110 | |||||||||||||||||||||
二进制位 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 |
索引 | 19 | 22 | 5 | 46 | ||||||||||||||||||||
Base64编码 | T | W | F | u |
在此例中,Base64算法将三个字符编码为4个字符
Base64索引表:
数值 | 字符 | 数值 | 字符 | 数值 | 字符 | 数值 | 字符 | |||
---|---|---|---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w | |||
1 | B | 17 | R | 33 | h | 49 | x | |||
2 | C | 18 | S | 34 | i | 50 | y | |||
3 | D | 19 | T | 35 | j | 51 | z | |||
4 | E | 20 | U | 36 | k | 52 | 0 | |||
5 | F | 21 | V | 37 | l | 53 | 1 | |||
6 | G | 22 | W | 38 | m | 54 | 2 | |||
7 | H | 23 | X | 39 | n | 55 | 3 | |||
8 | I | 24 | Y | 40 | o | 56 | 4 | |||
9 | J | 25 | Z | 41 | p | 57 | 5 | |||
10 | K | 26 | a | 42 | q | 58 | 6 | |||
11 | L | 27 | b | 43 | r | 59 | 7 | |||
12 | M | 28 | c | 44 | s | 60 | 8 | |||
13 | N | 29 | d | 45 | t | 61 | 9 | |||
14 | O | 30 | e | 46 | u | 62 | + | |||
15 | P | 31 | f | 47 | v | 63 | / |
如果要编码的字节数不能被3整除,最后会多出1个或2个字节,那么可以使用下面的方法进行处理:先使用0字节值在末尾补足,使其能够被3整除,然后再进行base64的编码。在编码后的base64文本后加上一个或两个'='号,代表补足的字节数。也就是说,当最后剩余一个八位字节(一个byte)时,最后一个6位的base64字节块有四位是0值,最后附加上两个等号;如果最后剩余两个八位字节(2个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。 参考下表:
文本(1 Byte) | A | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
二进制位 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | ||||||||||||||||
二进制位(补0) | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | ||||||||||||
Base64编码 | Q | Q | ||||||||||||||||||||||
文本(2 Byte) | B | C | ||||||||||||||||||||||
二进制位 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | x | x | x | x | x | x | ||
二进制位(补0) | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | x | x | x | x | x | x |
Base64编码 | Q | k | M |
UTF-7[编辑]
UTF-7是一个修改的Base64(Modified Base64)。主要是将UTF-16的数据,用Base64的方法编码为可打印的ASCII字符序列。目的是传输Unicode数据。主要的区别在于不用等号"="补余,因为该字符通常需要大量的转译。
标准可见RFC 2152,《A Mail-Safe Transformation Format of Unicode》。
IRCu[编辑]
在IRCu等软件所使用的P10 IRC服务器间协议中,对客户与服务器的消息类型号(client/server numerics)和二进制IP地址采用了base64编码。消息类型号的长度固定为3字节,故可直接编码为4个字节而不需要加填充。对IP地址进行编码时,则需要在地址前添加一些0比特,使之可以编码为整数个字节。这里所用的符号集与前述MIME的也有所不同,将+/改成了[]。
在URL中的应用[编辑]
Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java持久化系统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)。