关于base64:传参base64时的号变空格问题

原创:扣钉日记(微信公众号ID:codelogs),欢送分享,非公众号转载保留此申明。问题产生上上周,看到一位老哥找咱们组共事联调接口,不晓得是什么问题,两人坐一起搞了快1个小时,看起来如同有点简单。 忽然,老哥收回一声卧槽,"我传参里的+号,到你这怎么变成了空格!",这个声音很大,我显著的听到了,很快,我就大略Get到了他们的问题点。 我猜想他们遇到的问题大略如下: 咱们的接口协议上,都会将申请数据做一次base64编码,而后放到data参数上。而后某些数据做base64编码后有+,如{"notes":"代码"}base64编码为eyJub3RlcyI6IuS7o+eggSJ9Cg==。而后间接拼到data参数上,即data=eyJub3RlcyI6IuS7o+eggSJ9Cg==,组织成http申请收回。如果写成等价的curl,就是这样: $ curl http://localhost:8080/send -d 'data=eyJub3RlcyI6IuS7o+eggSJ9Cg=='写个测试接口调试下看看,如下: 这就是他们遇到的问题,+会变成空格,这个坑其实蛮容易踩到,我本人刚工作时就踩到过这个坑,也屡次看到或听到他人同踩此坑 问题起因这个问题和urlencode编码无关,urlencode编码,一般来说,除字母、数字和*,.,-和_这些字节原样输入外,其它字节都会编码为%XX(16进制)的模式。 但有一个特例,如下: String enc = URLEncoder.encode(" ", "UTF-8");System.out.println(enc); // 输入+号String dec = URLDecoder.decode("+", "UTF-8");System.out.println(dec); // 输入空格特例就是空格会被编码为+号,反之,+号会被解码为空格! 注:在新的RFC 2396标准中,空格其实也能够编码成%20,而解码时,+号与%20都会被解码为空格。回忆下面的场景,如果将带有+号的base64字符串,一成不变的封装到data=中,再发送给Tomcat等Web服务器,若Tomcat侧做一次urldecode解码,+是不是就变成空格了 而Tomcat的确会做urldecode解码这样的操作,当调用方的Content-Type为application/x-www-form-urlencoded时,这里晓得有这种操作即可,想理解细节可看看我写的这篇文章 由x-www-form-urlencoded引发的接口对接失败 解决问题解决这种问题,次要有两种办法,如下: 调用方对参数做urlencode编码。按标准来看,当Content-Type为application/x-www-form-urlencoded时,调用方是必须对参数名与参数值做urlencode的,java实现如下: String base64Str = Base64.getEncoder().encodeToString(data);String requestStr = "data=" + URLEncoder.encode(base64Str, "UTF-8");这里做了urlencode后,+会被编码为%2B,再由服务端解码,就会变成原样的+号。 注:如果是应用apache的HttpClient,可思考应用UrlEncodedFormEntity,它会主动做这个事件。应用urlsafe版本的base64。一般的base64不能间接作为参数值,因为它可能蕴含+、/这两个url不平安的字符,所以base64有个变种叫urlBase64,它将+、/替换成了url平安的-、_,java实现如下: String urlBase64Str = Base64.getUrlEncoder().encodeToString(data);String requestStr = "data=" + urlBase64Str;对于base64、urlencode编码,之前也专门写过一篇文章,感兴趣可进一步浏览 hex,base64,urlencode编码方案比照

March 25, 2023 · 1 min · jiezi

关于base64:base64原理

什么是base64?依据维基百科,base64是一种编码方式,将二进制数据表示为ASCII纯文本模式。(留神:base64不是加密算法,只是一种编码方式!)如果用base64加密: 作用电子邮件刚问世的时候,只能传输英文,但起初随着用户的减少,中文、日文等文字的用户也有需要,但这些字符并不能被服务器或网关无效解决,因而base64就退场了,base64能够在任何反对ASCII的中央传输文件,不必放心文件应为编解码的问题而损坏。 原理base64选区了64个ASCII可见字符作为底(64的由来)将二进制数据映射到这64个字符上。例如:原数据:abcabc对应的ASCII地位就是97,98,99。示意位二进制模式就是:01100001 01100010 01100010再将二进制数据以每6位一组:011000 010110 001001 100010对应的10进制别离为:24 22 9 34依据下面的base64表查表的YWJi至此,就实现了对 abc 的base64编码 解码的过程齐全就是将编码过程反过来,不过多赘述。 附上简略的cpp实现: #include <iostream>#include <string>using namespace std;class Base64{private: static constexpr const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static uint8_t index_of (char encoded_char) { for (int i = 0; i < 64; i++) { if (encoded_char == base64_chars[i]) return i; } return 64; }public: static string encode (string origin) { int buf = 0; int buf_size = 0; string result; for (int origin_char : origin) { buf = (buf << 8) + origin_char; buf_size += 8; while (buf_size >= 6) { uint8_t base64_index = (buf >> (buf_size - 6)); buf = buf ^ ((buf >> (buf_size - 6)) << (buf_size - 6)); buf_size -= 6; result.push_back(base64_chars[base64_index]); } } if (buf_size > 0 && buf_size < 6) { uint8_t base64_index_offset = buf << (6 - buf_size); result.push_back(base64_chars[base64_index_offset]); } return result; } static string decode (string encoded) { unsigned buf = 0; unsigned buf_size = 0; string result; for (char encoded_char : encoded) { if (encoded_char == '=') break; uint8_t index = index_of(encoded_char); buf = (buf << 6) + index; buf_size += 6; while (buf_size >= 8) { result.push_back((char) (buf >> (buf_size - 8))); buf_size -= 8; } } return result; }};int main () { Base64 base64; string o = "zixiao is handsome"; string encoded = base64.encode(o); string decoded = base64.decode(encoded); cout << decoded << endl; return 0;}

February 2, 2022 · 2 min · jiezi

关于base64:在线图片转base64工具

在线图片转base64工具在线图片转base64工具 本工具反对将图片转成Base64编码或将Base64编码还原成图片文件,方便快捷。 数据仅在客户端计算解决,不会上传到网络服务器中,请放心使用。 本工具目前仅反对较新的浏览器版本,如果未失常运行,请尝试更换Chrome,Firefox等较新版本的浏览器。 https://tooltt.com/img2base64/

October 11, 2021 · 1 min · jiezi

关于base64:Base64编码对照表

Base64编码对照表Base64编码对照表 在WEB开发Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来示意二进制数据的办法。可查看RFC2045~RFC2049,下面有MIME的具体标准或者客户端开发时候,常常须要用到键盘按键的ASCII简码值,通常这些值无需记忆,须要用到的时候间接查表即可。 https://tooltt.com/base64-table/

September 26, 2021 · 1 min · jiezi

关于base64:Base64加解密实现

一、阐明1、base64Base64是一种基于64个可打印字符来示意二进制数据的编码方式,是从二进制数据到字符的过程。罕用于数据存储、或者传输,与其说是加解密办法,编码方法更适宜形容base64。 2、转换的思路加密思路1)base64的编码都是按字符串长度,以每3个8bit的字符为一组2)针对每组,获取每个字符的ASCII编码3)将ASCII编码转成8bit的二进制4)划分为每6bit一组,默认最高2位为00,这样就能38转成465)将4*6的每一组转为10进制,对照Base64表失去最终的编码后果6)每76个字符加一个换行符7)最初的结束符须要解决一下 解密思路1)对照Base64表将对应字符转为码值2)将码值转为二进制,每8bit示意一个字符3)将8bit转为16进制4)对照ASCII表,获取值 二、术语和参考资料ASCII对照表 Base64表 三、整体设计 1、类接口#pragma onceclass CBase64Code{public: CBase64Code(); ~CBase64Code();public: //获取base64加密后的内容 std::string GetBase64Code(const void* pData, int nLen); //对内容进行解密 BOOL DecodeBase64Data(const std::string& strDecodeData, int nDataSize, void** ppData);private: //base64编码 int _Base64Encode(const char *pcszIn, int nInSize, char *pszOut, int nOutSizeMax, int *pnReturnSize, int nNeedCRLF); //base64解码 int _Base64Decode(const char *pcszIn, int nInSize, char *pszOut, int nOutSizeMax, int *pnReturnSize);};四、示例1、对字符'j'进行加密1)查看ASCII表,失去二进制为011010102)Base64每3个8bit一组,补全为01101010 00000000 000000003)划分为4*6,失去011010 100000 000000 0000004)转为10进制26 32 0 05)对照Base64表,失去编码后的数据为a g = =6)所以"j"通过Base64编码后的数据为ag== 2、对"ag=="进行解密1)对照Base64表,失去26 32 0 02)转为二进制011010 100000 000000 0000003)转为3*801101010 00000000 000000004)转为10进制106 0 05)对照ASCII表j ...

April 26, 2021 · 1 min · jiezi

关于base64:一文带你读懂base64编码

hi,大家好,我是开发者FTD。置信很多同学在工作中,常常会用到Base64编码,那大家晓得为什么会有Base64编码吗?咱们为什么要应用它呢,它又是怎么实现的呢?上面就让咱们来一起深刻探索一下Base64编码吧。 Base 家族在开始之前,咱们先给大家介绍一下Base家族。尽管咱们在工作中应用最多的是Base64,然而Base家族可不止是只有Base64,除了Base64之外,Base家族还有Base32和Base16。 咱们都晓得ASCII 编码,ASCII 编码是用256(2的8次方)个字符,对二进制数据进行编码的形式,同样的 Base64 编码是用64(2的6次方)个字符,对二进制数据进行编码的形式Base32 编码是用32(2的5次方)个字符,对二进制数据进行编码的形式Base16 编码是用16(2的4次方)个字符,对二进制数据进行编码的形式那Base家族有这么多编码模式,为什么偏偏应用Base64呢? Base64 编码是用64(2的6次方)个特定的ASCII字符来示意256(2的8次方)个ASCII字符,也就是说三个ASCII字符通过Base64编码后变为四个的ASCII字符显示(公约数为24),编码后数据长度比原来减少1/3,有余3n用“=”补足。Base32 编码就是用32(2的5次方)个特定的ASCII字符来示意256(2的8次方)个ASCII码,也就是说五个ASCII字符通过Base32编码后会变为八个ASCII字符显示(公约数为40),编码后数据长度比原来减少3/5,有余8n用“=”补足。Base16 编码就是用16(2的4次方)个特定的ASCII字符示意256(2的8次方)个ASCII字符,也就是说一个ASCII字符通过Base16编码后会变为两个ASCII字符显示,编码后数据长度比原来增加一倍,有余2n用“=”补足。从下面能够看出Base64编码后,长度减少是起码的,这也是咱们选用Base64的一个重要起因。 Base64 简介Base64顾名思义,就是基于64个可打印字符来示意二进制数据的一种办法,留神它并不是一种加密算法。对于64个打印字符,咱们只须要6个二进制位就能够齐全示意了。那么咱们如何利用8个二进制位来示意只须要6个二进制位就能够齐全示意的可打印字符呢?因为2的6次方等于64,所以咱们能够将每6个位元为一个单元,对应某个可打印字符。三个字节有24个位元,对应于4个Base64单元,即3个字节须要用4个可打印字符来示意。 Base64是从二进制数据到字符的过程。所以计算机中所有的内容,包含文本、图片、音频、视频等等都能够应用Base64编码来示意。 Base64 编码原理Base64编码就是应用64个字符作为一个根本字符集: 小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是65个字符)而后,所有其余符号都依据肯定规定转换成这个字符集中的字符。 具体来说,Base64编码的转换形式能够分为以下四步: 第一步,将每三个字节作为一组,一共是24个二进制位第二步,将这24个二进制位分为四组,每个组有6个二进制位第三步,在每组后面加两个00,扩大成32个二进制位,即四个字节第四步,依据下表,失去扩大后的每个字节的对应符号,这就是Base64的编码值Base64 编码的字符索引表如下所示: 数值字符数值字符数值字符数值字符0A16Q32g48w1B17R33h49x2C18S34i50y3D19T35j51z4E20U36k5205F21V37l5316G22W38m5427H23X39n5538I24Y40o5649J25Z41p57510K26a42q58611L27b43r59712M28c44s60813N29d45t61914O30e46u62+15P31f47v63/有了这个字符索引表,咱们就能够把任意的二进制转换成Base64的编码了,上面咱们通过几个例子,给大家展现一下转换的过程。 1,假如当初有字符串 FTD 须要转换成base64的编码格局 第一步:“F”、“T”、"D" 字符对应的ASCII码值别离为70,84,68,对应的二进制值是01000110、01010100、01000100。如图第二三行所示,由此组成一个24位的二进制字符串。第二步:将24位二进制依照每6位二进制位一组分成四组。第三步:在下面每一组后面补两个0,扩大成32个二进制位,此时变为四个字节:00010001、00100101、00010001、00000100。别离对应的值(Base64编码索引)为:17、37、17、4。第四步:用下面的值在Base64 字符索引表中进行查找,别离对应:R、I、R、E。因而字符串 “FTD” 通过Base64 编码之后就变为:RIRE 。 2,下面的例子中的字符正好是三个字节,如果字节数有余三个时该如何解决呢?上面咱们以 F 和 FT 别离举例说明如下: 如上表所示,因为字符F的二进制为01000110,依照每6位进行分组,此时只能分成一组,第二组短少4位,如果位数有余时,用0补齐;第三组和第四组齐全没有数据,则用=补上。因而,字符F通过Base64编码后失去的数值为Rg==。 3,上面咱们再看一下如果只有两个字符的状况: 如上表所示,这个也属于位数有余,须要补位的状况。第一组和第二组依照失常的分组计算,第三组因为有余位数,最初两位补0,第四组齐全没有数据,用=补上。因而,字符FT通过Base64编码后失去的数值为RlQ=。 对于中文的Base64编码大家都晓得中文编码有很多种,例如GB2312、GBK、GB18030,不同的汉字应用不同的编码格局进行编码后,它的二进制是不同的,所以在进行Base64编码后,他们的Base64编码的值也是不同的。这就要求咱们在解码的时候须要留神原文的字符集格局,肯定要保持一致能力正确解码。 例如: 中文 “【我是开发者FTD】公众号” UTF-8 格局的Base64 编码后的值是:44CQ5oiR5piv5byA5Y+R6ICFRlRE44CR5YWs5LyX5Y+3中文 “【我是开发者FTD】公众号” GB2312 格局的Base64 编码后的值是:ob7O0srHv6q3otXfRlREob+5q9bausU= Base64 是加密算法吗?Base64 次要不是用来加密的,它次要的用处是把一些二进制数转成一般字符用于网络传输,这是因为一些二进制字符在传输协定中属于控制字符,不能间接在网络上传输。另外,还有一些零碎中只能应用ASCII字符。Base64 编码就是用来将非ASCII字符的数据转换成ASCII字符的一种办法。Base64 并不是平安畛域下的加密解密算法,尽管有时候也会常常看到所谓的Base64加密解密算法。其实Base64只能算是一个编码算法,对数据内容进行编码来适宜网络传输。尽管Base64编码过后原文也变成无奈间接了解的字符格局,然而这种编码方式比拟高级,很简略,很容易就能够被还原成原文,所以如果有比拟重要的信息须要加密,肯定要应用咱们之前文章中介绍的那些加密算法进行数据的平安爱护。 Base64 编码实现Java语言中有多个库实现了Base64编码,不论哪一个库,最终的后果都是一样的。 JDK 提供的 Base64 编码实现: public static String encode(String data) { return Base64.getEncoder().encodeToString(data.getBytes());}public static String decode(String base64Data) { return new String(Base64.getDecoder().decode(base64Data));}Bouncy Castle 提供的 Base64 编码实现: ...

March 5, 2021 · 1 min · jiezi

关于base64:详述图片base64加密的原理告诉你什么是9j

 欢送大家搜寻“小猴子的技术笔记”关注我的公众号,有问题能够及时和我交换。 在日常的生存中,咱们必定都经验过相似这样的场景:报名考试上传图片,网站要求的是上传的照片不能大于多少,而且要求是“.jpg”的格局。 于是你高高兴兴的把本人最丑陋的照片上传上去了,然而网站却提醒你照片格局不正确,让你从新上传。这个时候心田不晓得有多少纳闷涌上心头(其实是草泥马在奔流)我的照片明明就是“.jpg”结尾的,而且大小也符合规范,为啥就不行呢? 咱们通常的会认为(Windows电脑状况下,Mac不晓得,毕竟我没有图片)“.jpg”图片结尾的就肯定是符合规范的“JPG”文件类型。其实一开始我也是这样认为的,直到前几天,我在对接我的项目的时候踩了一个大坑,很大的坑! 我对接的我的项目要求的是图片是“JPG”类型的文件,并且通过base64进行编码之后要以"/9j"结尾的文件。于是我就把我电脑上保留的看似符合规范的图片上传上去了,后果就是一堆报错信息。于是我再次尝试,换一些其余的图片进行测试,发现有的就好使,有的就不好使。说实话,我的心田解体了!那种感觉你懂得图片 回到家之后我思来想去就是不晓得为什么要求什么"/9j"结尾的?我关上了百度,输出了关键词“/9j”之后,呵呵!我笑了,都是些什么?齐全跟我的问题不着边! 什么玩意?这到底是什么玩意?居然连弱小的百度都没有给出后果!就这样,我搜寻到了凌晨12点...... 扛不住了,我就去睡觉了。然而躺在床上我辗转难眠,关上手机持续各种搜寻着......忽然!我看了一个对于电脑图片文件头信息解析的文章!一道灵光从我脑门上闪过。于是我起床,默默关上了电脑,关上了百度...... 原来电脑在存储的时候是存储了图片的根本信息的,比方图片是什么类型的,图片的宽低等根本信息,这些个根本信息叫做图片头信息。好吧!原谅我的无知,已经的我天真的认为是依照文件后缀名辨别的呢。 咱们应晓得,图片在计算机中存储是一个一个的像素点,最底层也是二进制文件,所以须要文件头来保留文件信息。经查找材料,我找到如下对图片不同格局的文件头标识信息(16进制标识): 1.BMP 文件头标识 (2 bytes) 42 4D 2.PNG 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A 3.GIF 文件头标识 (6 bytes) 47 49 46 38 39(37) 61 4.JPEG/JPG 文件头标识 (2 bytes): FF D8 (SOI) (JPEG 文件标识) 于是我在电脑上保留了一个为“.jpg”后缀结尾的图片,而后应用UE这个弱小的工具关上,果然不出我所料,看看这个文件的内容信息。 不出意外的话,你必定看不懂这些货色,因为这些是16进制文件。然而重要的我曾经给你标注进去了,那就是“FF D8”。 在这里我给大家略微简略科普下base64的编码规定:如果咱们有个“hello”这样的关键字进行base64编码,须要先把“hello”转换成二进制,也就是"110100011001011101100110 11001101111"。我这里给了一个ASCII表,这里对应的是10进制的,须要把十进制转化成2进制的。 对于base64 有个规定就是,一个字符转换之后如果位数不为8位,须要在高位补0,而后再6位截取,最初不够6位的,低位补0。而后把宰割后的2进制转换成10进制并对照base64编码表进行解析。那么上述的“hello”的解析过程就如下: 所以“hello”base64编码之后的最终后果就是“aGVsbG8=”。兴许你会纳闷,为什么多了个“=” 这个其实是base64的规定,编码结束之后主动增加一个或两个“=”。 ...

January 18, 2021 · 1 min · jiezi

关于base64:翻译-RFC-4648-Base16Base32-和-Base64-数据编码

每年都会有人尝试翻译 RFC 系列文档,为了能更好地迭代和组织所翻译的内容,我建设了一个 GitHub 仓库,心愿有趣味的人能够参加进来。翻译是个既耗时又费劲的事件,因而我冀望的是一种细水长流的模式,即便是几句话的翻译或调整,都能够通过 PR 或邮件的形式提交,缓缓地积攒来实现这一我的项目。 https://github.com/dianbo-rfc/dianbo-rfc 另外,为了不便 RFC 文档的浏览,我试着建设了一个网站。网站的视觉效果应该会好些,应用了等宽字体,并且有中英对照;但毕竟是第一次进行网站开发,且应用的是最低配的服务器,响应工夫、页面布局会有很多问题。 https://dianbo-rfc.cn/progress 上面的译文是公布此文章时的版本,将来可能更新的译文须要到 GitHub 或网站上浏览: Network Working Group S. JosefssonRequest for Comments: 4648 SJDObsoletes: 3548 October 2006Category: Standards Track Base16、Base32 和 Base64 数据编码Status of This Memo This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited.Copyright Notice Copyright (C) The Internet Society (2006).摘要 此文档形容了常常应用的 base 64、base 32 和 base 16 编码方案。此外, 它 还探讨了以下内容: 在编码数据中应用换行符、在编码数据中应用填充符、在 编码数据中应用非字母表中的字符、不同编码字母表的应用、及标准编码。Josefsson Standards Track [Page 1]RFC 4648 Base-N Encodings October 2006目录 1. 导言 ............................................................3 2. 此文档中应用的约定 ..............................................3 3. 各实现间的差别 ..................................................3 3.1. 编码数据中的换行符 .........................................3 3.2. 编码数据中的填充符 .........................................4 3.3. 编码数据中非字母表中字符的解释 .............................4 3.4. 字母表的抉择 ...............................................4 3.5. 标准编码 (Canonical Encoding) ..............................5 4. Base 64 编码 ....................................................5 5. 具备 "对 URL 和文件名平安的字母表" 的 Base 64 编码 ..............7 6. Base 32 编码 ....................................................8 7. 具备 "扩大十六进制的字母表" 的 Base 32 编码 ....................10 8. Base 16 编码 ...................................................10 9. 图解和示例 .....................................................11 10. 测试样例 ......................................................12 11. ISO C99 中的 Base64 编码的实现 ................................14 12. 平安注意事项 ..................................................14 13. 自 RFC 3548 以来的批改 ........................................15 14. 致谢 ..........................................................15 15. Copying Conditions ............................................15 16. 参考文献 ......................................................16 16.1. 前提类参考文献 ...........................................16 16.2. 信息类参考文献 ...........................................16Josefsson Standards Track [Page 2]RFC 4648 Base-N Encodings October 20061. 导言 因为历史遗留起因, 有些环境只能应用 US-ASCII [1] 示意的数据, 而数据的 Base 编码 (Base encoding) 常常被用在这种状况中。Base 编码也能够被用于 不受历史遗留起因所限度的新利用中, 仅仅是因为它使得 "通过文本编辑器来 操作对象" 成为可能。 过来, 不同的应用程序具备不同的需要, 因而它们有时会以稍微不同的形式来 实现 Base 编码。现在, 有些协定标准有时会广泛地应用 Base 编码, 尤其是 "base64", 然而却没有该编码的精确形容或参考文献。多用途互联网邮件扩大 (MIME, Multipurpose Internet Mail Extensions) 常常被用作是 base64 的 参考文献, 然而它没有思考到换行符 (line-wrapping) 或非字母表中字符所造 成的后果。此标准的目标是建设起通用的字母表及编码时的注意事项。这将有 望缩小其它文档中的歧义性, 从而实现更好的互操作性。2. 此文档中应用的约定 在此文档中, 对于关键词【必须】、【禁止】、【必要的】、【该当】、 【不应】、【举荐的】、【能够】与【可选的】的解释, 见 [2] 中的描 述。3. 各实现间的差别 这里, 咱们将探讨过来的各 Base 编码实现之间的差别, 并在适当时, 规定了 用于未来的具体的举荐行为。3.1. 编码数据中的换行符 MIME [4] 常常被用作是 base 64 编码的参考文献。然而, MIME 并没有定义 "base 64" 自身, 而是定义了被用于 MIME 中的 "base 64 内容传输编码" ("base 64 Content-Transfer-Encoding")。其中, MIME 强制性限度了: 应用 base 64 编码的数据, 其每行长度为 76 个字符。MIME 继承了隐衷加强邮件 (PEM, Privacy Enhanced Mail) [3] 中的编码, 并指出它 "实际上是雷同的"; 然而, PEM 应用的每行长度为 64 个字符。MIME 和 PEM 的限度都是因为 SMTP 中存在的限度所造成的。 程序实现【禁止】向应用 base 编码的数据中增加换行符, 除非参考了此文档 的其它标准, 有明确地批示 base 编码器: 在特定数量的字符后增加换行符。Josefsson Standards Track [Page 3]RFC 4648 Base-N Encodings October 20063.2. 编码数据中的填充符 在某些状况下, 不须要或不必在 base 编码的数据中应用填充符 ("=")。在一 般状况下, 当无奈假如传输数据的大小时, 须要应用填充符来产生正确的编码 数据。 程序实现【必须】在编码数据的开端蕴含适当的填充字符, 除非参考了此文档 的其它标准另有明确规定。 base64 和 base32 编码中的字母表应用了填充符, 见上面第 4 节和第 6 节的 形容, 然而 base16 编码中的字母表不须要它, 见第 8 节。3.3. 编码数据中非字母表中字符的解释 Base 编码应用了一个非凡的、删减版的字母表来编码二进制数据。因为数据损 坏或设计起因, base 编码的数据中可能存在非字母表中的字符。非字母表中的 字符可能被用作 "荫蔽信道" ("covert channel"), 其中非协定的数据可能出 于歹意目标而被发送。此外, 为了摸索实现中的谬误 (例如, 可能导致内存溢 出攻打), 非字母表中的字符也可能会被发送。 当程序实现在解释 base 编码的数据时, 若发现数据中蕴含 base 字母表外的 字符, 程序实现【必须】回绝编码数据, 除非参考了此文档的其它标准另有明 确规定。这些标准可能会同 MIME 一样规定: 在解释数据时, 该当简略地疏忽 掉在 base 编码字母表以外的字符 ("在承受的内容上要放宽")。留神, 这象征 着: 任何相邻的回车/换行 (CRLF) 均形成 "非字母表中字符", 并被疏忽掉。 此外, 这类标准【能够】将呈现在编码数据开端的填充符 "=" 认作是非字母表 中的字符, 并将其疏忽掉。如果在字符串的开端发现了超出容许数量的填充字 符 (例如, 一个 base 64 字符串以 "===" 完结), 则超出的填充字符【能够】 被疏忽。3.4. 字母表的抉择 不同的利用对字母表中的字符有不同的需要。以下是一些需要, 用于确定该当 应用哪个字母表:Josefsson Standards Track [Page 4]RFC 4648 Base-N Encodings October 2006 o 由人类解决。字符 "0" 和 "O" 很容易混同, 字符 "1"、"l" 和 "I" 也很 容易混同。在上面的 base32 字母表中, 没有字符 "0" (零) 和 "1" (一), 依据状况, 一个解码器可能将 0 解释为 O, 并将 1 解释为 I 或 L 。(但 是, 在默认状况下, 不应如此; 见后面的章节。) o 编码后的数据, 其构造要满足其它要求。对于 base 16 和 base 32 编码, 这确定了应用大写或小写的字母表。对于 base 64 编码, 非字母表中的字 符 (特地是 "/") 可能会在文件名和 URL 中呈现问题。 o 用作标识符。一些字符, 特地是 base 64 字母表中的 "+" 和 "/", 会被传 统的文本搜寻/索引工具视为分词符。 没有可能满足所有的需要、被广泛承受的字母表。一个对于高度专业化变体的 示例, 见 IMAP [8]。在此文档中, 咱们记录并命名了一些以后正在被应用的字 母表。3.5. 标准编码 (Canonical Encoding) base 64 和 base 32 编码中的填充步骤, 如果没有被正确地实现, 将会导致编 码后的数据呈现不易觉察的扭转。例如, 对于 base 64 编码, 如果它的输出仅 为一个八位字节, 则应用到了第一个符号中所有 6 个比特位, 然而只应用了下 一个符号中前 2 个比特位。遵循协定的编码器【必须】将裁减的比特地位零, 这将在下文形容填充符时提高一阐明。如果不保留这一个性, 则不存在对 base 编码的标准示意, 且会呈现: 多个 base 编码字符串被解码为雷同的二进制数 据。如果保留这一个性, 则可能保障标准编码。 在一些环境中, 对于数据中的变动十分严格, 因而: 如果未将填充比特地位为 零, 则编码器【能够】抉择回绝编码数据。与此相关的标准可能规定一个非凡 的行为。4. Base 64 编码 下文中对 base 64 编码的形容来自于 [3], [4], [5] 与 [6]。能够应用 "base64" 来代称此编码方案。 Base 64 编码被设计成: 在容许应用辨别大小写的示意模式时, 它可能示意任 意的八字节序列, 然而并不需要被人类可读。Josefsson Standards Track [Page 5]RFC 4648 Base-N Encodings October 2006 编码应用了一个蕴含 US-ASCII 中的 65 个字符的字符子集, 其中的每个可打 印字符可能示意 6 比特的数据。(额定的第 65 个字符是 "=", 其被用于示意 须要非凡的解决)。 编码的过程是将 "24 位组" 的多组输出比特, 示意为多个 "由 4 个编码字符 形成" 的多个字符串。依照从左至右的解决程序, 每 3 个 "8 位组" 的原始输 入形成一个 "24 位组" 的编码输出。这些 "24 位组" 的输出将被视作由 4 个 "6 位组" 的数据形成, 每一组都会被编码为 base 64 字母表中的单个字符。 每个 6 位组的数据被用作 "64 个可打印字符的数组" 的索引。被索引所援用 的字符置于输入字符串中。 表 1: Base 64 编码的字母表 值 编码 值 编码 值 编码 值 编码 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 如果在数据的开端, 可用于编码的数据少于 24 比特, 则需进行非凡的解决。 使得在对数据的开端编码时, 总是可能以残缺的 "24 位组" 的编码方式完结。 当输出比特组中的位数少于 24 比特时, 会在输出的右侧增加值为 0 的比特, 以形成一个残缺的 "6 位组"。接着应用字符 "=" 对数据的开端进行填充。因 为, 所有 base 64 编码的输出都是整数个八位字节, 所以只会呈现一下状况: (1) 如果编码输出的最初局部的比特位数是 24 的整数倍; 则编码输入的最初 局部的字符个数是 4 的整数倍, 且没有用字符 "=" 填充。Josefsson Standards Track [Page 6]RFC 4648 Base-N Encodings October 2006 (2) 如果编码输出的最初局部的比特位数刚好是 8 位; 则编码输入的最初局部 将会是: 2 个编码字符, 再后跟 2 个 "=" 填充符。 (3) 如果编码输出的最初局部的比特位数刚好是 16 位; 则编码输入的最初部 分将会是: 3 个编码字符, 再后跟 1 个 "=" 填充符。5. 具备 "对 URL 和文件名平安的字母表" 的 Base 64 编码 具备 "对 URL 和文件名平安的字母表" 的 Base 64 编码, 曾经被用于 [12]。 有些替换用的字母表, 倡议应用 "~" 作为第 63 个字符。因为, 在一些文件系 统的环境中, 字符 "~" 具备非凡的含意, 所以倡议还是应用本节所形容的编码 计划。残余的未被 URI 所保留的字符是 ".", 然而在一些文件系统的环境中, 不容许在一个文件名中应用多个 ".", 因而使得字符 "." 也没有吸引力。 当在 URI [9] 中应用时, 填充字符 "=" 通常是被百分号编码的 (percent- encoded), 然而如果隐士地晓得数据的长度, 则能够通过跳过填充符来防止这 一状况; 见第 3.2 节。 这里给出的编码方案可用 "base64url" 来代称。不应认为此编码与 "base64" 编码雷同, 且不应仅用 "base64" 来指代此编码。除非另有阐明, 否则 "base64" 指代的是后面章节中的 base 64 编码。 此编码方案, 除了在第 62 个和第 63 个字符上有所区别, 从技术上而言与之 前的雷同, 如表 2 所示。Josefsson Standards Track [Page 7]RFC 4648 Base-N Encodings October 2006 表 2: "对 URL 和文件名平安的" Base 64 编码的字母表 值 编码 值 编码 值 编码 值 编码 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 (填充符) =6. Base 32 编码 下文中对 base 32 编码的形容来自于 (更正后的) [11]。能够应用 "base32" 来代称此编码方案。 Base 32 编码被设计成: 在须要应用不辨别大小写的示意模式时, 它可能示意 任意的八字节序列, 然而并不需要被人类可读。 编码应用了一个蕴含 US-ASCII 中的 33 个字符的字符子集, 其中的每个可打 印字符可能示意 5 比特的数据。(额定的第 33 个字符是 "=", 其被用于示意 须要非凡的解决)。 编码的过程是将 "40 位组" 的多组输出比特, 示意为多个 "由 8 个编码字符 形成" 的多个字符串。依照从左至右的解决程序, 每 5 个 "8 位组" 的原始输 入形成一个 "40 位组" 的编码输出。这些 "40 位组" 的输出将被视作由 8 个 "5 位组" 的数据形成, 每一组都会被编码为 base 32 字母表中的单个字符。 当一个比特流通过 base 32 编码方式进行编码时, 必须假设该比特流的位序满 足最高位优先。因而, 在比特流的第一个 8 位字节中, 第一个比特是最高位, 第八个比特是最低位, 依此类推。Josefsson Standards Track [Page 8]RFC 4648 Base-N Encodings October 2006 每个 5 位组的数据被用作 "32 个可打印字符的数组" 的索引。被索引所援用 的字符置于输入字符串中。这些字符是从 US-ASCII 的数字和大写字母中选出, 如下表 3 所示: 表 3: Base 32 编码的字母表 值 编码 值 编码 值 编码 值 编码 0 A 9 J 18 S 27 3 1 B 10 K 19 T 28 4 2 C 11 L 20 U 29 5 3 D 12 M 21 V 30 6 4 E 13 N 22 W 31 7 5 F 14 O 23 X 6 G 15 P 24 Y (填充符) = 7 H 16 Q 25 Z 8 I 17 R 26 2 如果在数据的开端, 可用于编码的数据少于 40 比特, 则需进行非凡的解决。 使得在对数据的开端编码时, 总是可能以残缺的 "40 位组" 的编码方式完结。 当输出比特组中的位数少于 40 比特时, 会在输出的右侧增加值为 0 的比特, 以形成一个残缺的 "5 位组"。接着应用字符 "=" 对数据的开端进行填充。因 为, 所有 base 32 编码的输出都是整数个八位字节, 所以只会呈现一下状况: (1) 如果编码输出的最初局部的比特位数是 40 的整数倍; 则编码输入的最初 局部的字符个数是 8 的整数倍, 且没有用字符 "=" 填充。 (2) 如果编码输出的最初局部的比特位数刚好是 8 位; 则编码输入的最初局部 将会是: 2 个编码字符, 再后跟 6 个 "=" 填充符。 (3) 如果编码输出的最初局部的比特位数刚好是 16 位; 则编码输入的最初部 分将会是: 4 个编码字符, 再后跟 4 个 "=" 填充符。 (4) 如果编码输出的最初局部的比特位数刚好是 24 位; 则编码输入的最初部 分将会是: 5 个编码字符, 再后跟 3 个 "=" 填充符。 (5) 如果编码输出的最初局部的比特位数刚好是 32 位; 则编码输入的最初部 分将会是: 7 个编码字符, 再后跟 1 个 "=" 填充符。Josefsson Standards Track [Page 9]RFC 4648 Base-N Encodings October 20067. 具备 "扩大十六进制的字母表" 的 Base 32 编码 下文中对 base 32 编码的形容来自于 [7]。能够应用 "base32hex" 来代称此 编码方案。不应认为此编码与 "base32" 编码雷同, 且不应仅用 "base32" 来 指代此编码。此编码有被用于 NextSECure3 (NSEC3) [10]。 此字母表具备一个 base64 和 base32 的字母表所短少的个性, 即: 当对数据 通过按位比拟的形式进行排序时, 该字母表能保障编码后的数据具备同原始数 据雷同的排序程序。 此编码方案, 除了在字母表上有所区别, 其它方面与之前的雷同。新的字母表 如表 4 所示。 表 4: "扩大十六进制的" Base 32 编码的字母表 值 编码 值 编码 值 编码 值 编码 0 0 9 9 18 I 27 R 1 1 10 A 19 J 28 S 2 2 11 B 20 K 29 T 3 3 12 C 21 L 30 U 4 4 13 D 22 M 31 V 5 5 14 E 23 N 6 6 15 F 24 O (填充符) = 7 7 16 G 25 P 8 8 17 H 26 Q8. Base 16 编码 下文中的形容是原始的, 然而与先前的形容相似。实质上, Base 16 编码是标 准的不辨别大小写的十六进制编码, 且能够应用 "base16" 或 "hex" 来代称此 编码方案。 编码应用了一个蕴含 US-ASCII 中的 16 个字符的字符子集, 其中的每个可打 印字符可能示意 4 比特的数据。 编码的过程是将 "8 位组" (即八位字节) 的多组输出比特, 示意为多个 "由 2 个编码字符形成" 的多个字符串。依照从左至右的解决程序, 从原始输出中取 出 "8 位组" 作为编码输出。这些 "8 位组" 的输出将被视作由 2 个 "4 位 组" 的数据形成, 每一组都会被编码为 base 16 字母表中的单个字符。 每个 4 位组的数据被用作 "16 个可打印字符的数组" 的索引。被索引所援用 的字符置于输入字符串中。Josefsson Standards Track [Page 10]RFC 4648 Base-N Encodings October 2006 表 5: Base 16 编码的字母表 值 编码 值 编码 值 编码 值 编码 0 0 4 4 8 8 12 C 1 1 5 5 9 9 13 D 2 2 6 6 10 A 14 E 3 3 7 7 11 B 15 F 不同于 base 32 和 base 64 编码, 这里不须要非凡的填充符; 因为 base 16 编码的最小单元是八位字节, 这在所有的数据中都能失去保障。9. 图解和示例 为了在二进制和 base 编码之间进行转换, 须要将输出存储在某一构造中, 并 从中提取所需的输入。下图中所展现的 base 64 编码的例子, 来自于 [5]。 +--first octet--+-second octet--+--third octet--+ |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| +-----------+---+-------+-------+---+-----------+ |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0| +--1.index--+--2.index--+--3.index--+--4.index--+ 下图所展现的 base 32 编码的例子, 来自于 [7]。在 base-32 编码后的值中, 每个间断的字符都示意: 原始的八位字节序列中的 5 个间断比特。因而, 每组 "由 8 个编码字符形成" 字符串示意一个 "由 5 个八位字节形成" (40 比特) 的序列。 1 2 3 01234567 89012345 67890123 45678901 23456789 +--------+--------+--------+--------+--------+ |< 1 >< 2| >< 3 ><|.4 >< 5.|>< 6 ><.|7 >< 8 >| +--------+--------+--------+--------+--------+ <===> 8th character <====> 7th character <===> 6th character <====> 5th character <====> 4th character <===> 3rd character <====> 2nd character <===> 1st characterJosefsson Standards Track [Page 11]RFC 4648 Base-N Encodings October 2006 上面无关 Base64 数据编码的示例来自于 [5] (已更正)。 Input data: 0x14fb9c03d97e Hex: 1 4 f b 9 c | 0 3 d 9 7 e 8-bit: 00010100 11111011 10011100 | 00000011 11011001 01111110 6-bit: 000101 001111 101110 011100 | 000000 111101 100101 111110 Decimal: 5 15 46 28 0 61 37 62 Output: F P u c A 9 l + Input data: 0x14fb9c03d9 Hex: 1 4 f b 9 c | 0 3 d 9 8-bit: 00010100 11111011 10011100 | 00000011 11011001 pad with 00 6-bit: 000101 001111 101110 011100 | 000000 111101 100100 Decimal: 5 15 46 28 0 61 36 pad with = Output: F P u c A 9 k = Input data: 0x14fb9c03 Hex: 1 4 f b 9 c | 0 3 8-bit: 00010100 11111011 10011100 | 00000011 pad with 0000 6-bit: 000101 001111 101110 011100 | 000000 110000 Decimal: 5 15 46 28 0 48 pad with = = Output: F P u c A w = =10. 测试样例 BASE64("") = "" BASE64("f") = "Zg==" BASE64("fo") = "Zm8=" BASE64("foo") = "Zm9v" BASE64("foob") = "Zm9vYg==" BASE64("fooba") = "Zm9vYmE=" BASE64("foobar") = "Zm9vYmFy" BASE32("") = "" BASE32("f") = "MY======" BASE32("fo") = "MZXQ===="Josefsson Standards Track [Page 12]RFC 4648 Base-N Encodings October 2006 BASE32("foo") = "MZXW6===" BASE32("foob") = "MZXW6YQ=" BASE32("fooba") = "MZXW6YTB" BASE32("foobar") = "MZXW6YTBOI======" BASE32-HEX("") = "" BASE32-HEX("f") = "CO======" BASE32-HEX("fo") = "CPNG====" BASE32-HEX("foo") = "CPNMU===" BASE32-HEX("foob") = "CPNMUOG=" BASE32-HEX("fooba") = "CPNMUOJ1" BASE32-HEX("foobar") = "CPNMUOJ1E8======" BASE16("") = "" BASE16("f") = "66" BASE16("fo") = "666F" BASE16("foo") = "666F6F" BASE16("foob") = "666F6F62" BASE16("fooba") = "666F6F6261" BASE16("foobar") = "666F6F626172"Josefsson Standards Track [Page 13]RFC 4648 Base-N Encodings October 200611. ISO C99 中的 Base64 编码的实现 在 ISO C99 中有 Base64 编码与解码的实现, 该实现被认为是遵循了此 RFC 中的所有倡议, 能够从这里获取: http://josefsson.org/base-encoding/ 其中给出的代码不是必须的。 因为工作流程相干的起因, 不能在此 RFC 中蕴含该代码 (见 RFC 3978 中第 5.4 节)。12. 平安注意事项 在实现 base 编码与解码时, 须要留神: 不要引入会造成内存溢出攻打、或其 它攻打的破绽。解码器不应因有效输出而解体, 例如遇到了嵌入在数据中的字 符 NUL (ASCII 0). 在解码过程中, 如果抉择疏忽掉非字母表中的字符, 且没有 (依照倡议) 回绝 掉整个编码数据, 则可能产生成一个导致信息 "泄露" 的荫蔽信道 (covert channel)。被疏忽的字符也能够被用于其它的歹意目标, 例如: 躲避字符串的 判等、或登程实现中的 bug。未遵循举荐做法的利用, 该当弄清: 疏忽非字母 表中的字符, 这一行为背地的含意。相似的, 当以不辨别大小写的形式来解决 base 16 和 base 32 的字母表时, 字母大小写的变动可能被用于泄露信息、或 导致字符串的判等失败。 当应用填充符时, 须要思考一些非无效比特位的安全性, 因为它们可能被滥用 来泄露信息、或绕过字符串的判等、或触发实现中存在的问题。 Base 编码从视觉上暗藏了那些的易被辨认的信息, 例如明码, 然而它实际上并 未提供任何的计算保密性。而这有可能会导致安全事故, 例如: 当用户在报告 网络协议所替换的详细信息时 (可能是为了阐明其它问题), 会意外地将明码泄 露, 因为她并没有意识到 base 编码不能爱护明码。 Base 编码不会使文本熵增, 然而它的确减少了文本的长度, 并以特色概率分布 (characteristic probability distribution) 的模式为明码剖析过程 (cryptanalysis) 提供了签名。Josefsson Standards Track [Page 14]RFC 4648 Base-N Encodings October 200613. 自 RFC 3548 以来的批改 增加了 "应用扩大十六进制字母表的 base32" 的内容, 该编码被用于保留编码 数据的排序程序。 参考了 IMAP, 以阐明其中用到的非凡的 Base64 编码。 修复了从 RFC 2440 复制过去的示例。 增加了无关 "提供明码剖析签名" 的平安注意事项。 增加了测试样例。 修复了笔误。14. 致谢 Several people offered comments and/or suggestions, including John E. Hadstate, Tony Hansen, Gordon Mohr, John Myers, Chris Newman, and Andrew Sieber. Text used in this document are based on earlier RFCs describing specific uses of various base encodings. The author acknowledges the RSA Laboratories for supporting the work that led to this document. This revised version is based in parts on comments and/or suggestions made by Roy Arends, Eric Blake, Brian E Carpenter, Elwyn Davies, Bill Fenner, Sam Hartman, Ted Hardie, Per Hygum, Jelte Jansen, Clement Kent, Tero Kivinen, Paul Kwiatkowski, and Ben Laurie.15. Copying Conditions Copyright (c) 2000-2006 Simon Josefsson Regarding the abstract and sections 1, 3, 8, 10, 12, 13, and 14 of this document, that were written by Simon Josefsson ("the author", for the remainder of this section), the author makes no guarantees and is not responsible for any damage resulting from its use. The author grants irrevocable permission to anyone to use, modify, and distribute it in any way that does not diminish the rights of anyone else to use, modify, and distribute it, provided that redistributed derivative works do not contain misleading author or version information and do not falsely purport to be IETF RFC documents. Derivative works need not be licensed under similar terms.Josefsson Standards Track [Page 15]RFC 4648 Base-N Encodings October 200616. 参考文献16.1. 前提类参考文献 [1] Cerf, V., "ASCII format for network interchange", RFC 20, October 1969. [2] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.16.2. 信息类参考文献 [3] Linn, J., "Privacy Enhancement for Internet Electronic Mail: Part I: Message Encryption and Authentication Procedures", RFC 1421, February 1993. [4] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996. [5] Callas, J., Donnerhacke, L., Finney, H., and R. Thayer, "OpenPGP Message Format", RFC 2440, November 1998. [6] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, "DNS Security Introduction and Requirements", RFC 4033, March 2005. [7] Klyne, G. and L. Masinter, "Identifying Composite Media Features", RFC 2938, September 2000. [8] Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1", RFC 3501, March 2003. [9] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005. [10] Laurie, B., Sisson, G., Arends, R., and D. Blacka, "DNSSEC Hash Authenticated Denial of Existence", Work in Progress, June 2006. [11] Myers, J., "SASL GSSAPI mechanisms", Work in Progress, May 2000. [12] Wilcox-O'Hearn, B., "Post to P2P-hackers mailing list", http://zgp.org/pipermail/p2p-hackers/2001-September/ 000315.html, September 2001.Josefsson Standards Track [Page 16]RFC 4648 Base-N Encodings October 2006作者地址 Simon Josefsson SJD EMail: simon@josefsson.orgJosefsson Standards Track [Page 17]RFC 4648 Base-N Encodings October 2006Full Copyright Statement Copyright (C) The Internet Society (2006). This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights. This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.Intellectual Property The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79. Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr. The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.Acknowledgement Funding for the RFC Editor function is provided by the IETF Administrative Support Activity (IASA).Josefsson Standards Track [Page 18]

August 3, 2020 · 14 min · jiezi

关于base64:翻译-RFC-4648-Base16Base32-和-Base64-数据编码

每年都会有人尝试翻译 RFC 系列文档,为了能更好地迭代和组织所翻译的内容,我建设了一个 GitHub 仓库,心愿有趣味的人能够参加进来。翻译是个既耗时又费劲的事件,因而我冀望的是一种细水长流的模式,即便是几句话的翻译或调整,都能够通过 PR 或邮件的形式提交,缓缓地积攒来实现这一我的项目。 https://github.com/dianbo-rfc/dianbo-rfc 另外,为了不便 RFC 文档的浏览,我试着建设了一个网站。网站的视觉效果应该会好些,应用了等宽字体,并且有中英对照;但毕竟是第一次进行网站开发,且应用的是最低配的服务器,响应工夫、页面布局会有很多问题。 https://dianbo-rfc.cn/progress 上面的译文是公布此文章时的版本,将来可能更新的译文须要到 GitHub 或网站上浏览: Network Working Group S. JosefssonRequest for Comments: 4648 SJDObsoletes: 3548 October 2006Category: Standards Track Base16、Base32 和 Base64 数据编码Status of This Memo This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited.Copyright Notice Copyright (C) The Internet Society (2006).摘要 此文档形容了常常应用的 base 64、base 32 和 base 16 编码方案。此外, 它 还探讨了以下内容: 在编码数据中应用换行符、在编码数据中应用填充符、在 编码数据中应用非字母表中的字符、不同编码字母表的应用、及标准编码。Josefsson Standards Track [Page 1]RFC 4648 Base-N Encodings October 2006目录 1. 导言 ............................................................3 2. 此文档中应用的约定 ..............................................3 3. 各实现间的差别 ..................................................3 3.1. 编码数据中的换行符 .........................................3 3.2. 编码数据中的填充符 .........................................4 3.3. 编码数据中非字母表中字符的解释 .............................4 3.4. 字母表的抉择 ...............................................4 3.5. 标准编码 (Canonical Encoding) ..............................5 4. Base 64 编码 ....................................................5 5. 具备 "对 URL 和文件名平安的字母表" 的 Base 64 编码 ..............7 6. Base 32 编码 ....................................................8 7. 具备 "扩大十六进制的字母表" 的 Base 32 编码 ....................10 8. Base 16 编码 ...................................................10 9. 图解和示例 .....................................................11 10. 测试样例 ......................................................12 11. ISO C99 中的 Base64 编码的实现 ................................14 12. 平安注意事项 ..................................................14 13. 自 RFC 3548 以来的批改 ........................................15 14. 致谢 ..........................................................15 15. Copying Conditions ............................................15 16. 参考文献 ......................................................16 16.1. 前提类参考文献 ...........................................16 16.2. 信息类参考文献 ...........................................16Josefsson Standards Track [Page 2]RFC 4648 Base-N Encodings October 20061. 导言 因为历史遗留起因, 有些环境只能应用 US-ASCII [1] 示意的数据, 而数据的 Base 编码 (Base encoding) 常常被用在这种状况中。Base 编码也能够被用于 不受历史遗留起因所限度的新利用中, 仅仅是因为它使得 "通过文本编辑器来 操作对象" 成为可能。 过来, 不同的应用程序具备不同的需要, 因而它们有时会以稍微不同的形式来 实现 Base 编码。现在, 有些协定标准有时会广泛地应用 Base 编码, 尤其是 "base64", 然而却没有该编码的精确形容或参考文献。多用途互联网邮件扩大 (MIME, Multipurpose Internet Mail Extensions) 常常被用作是 base64 的 参考文献, 然而它没有思考到换行符 (line-wrapping) 或非字母表中字符所造 成的后果。此标准的目标是建设起通用的字母表及编码时的注意事项。这将有 望缩小其它文档中的歧义性, 从而实现更好的互操作性。2. 此文档中应用的约定 在此文档中, 对于关键词【必须】、【禁止】、【必要的】、【该当】、 【不应】、【举荐的】、【能够】与【可选的】的解释, 见 [2] 中的描 述。3. 各实现间的差别 这里, 咱们将探讨过来的各 Base 编码实现之间的差别, 并在适当时, 规定了 用于未来的具体的举荐行为。3.1. 编码数据中的换行符 MIME [4] 常常被用作是 base 64 编码的参考文献。然而, MIME 并没有定义 "base 64" 自身, 而是定义了被用于 MIME 中的 "base 64 内容传输编码" ("base 64 Content-Transfer-Encoding")。其中, MIME 强制性限度了: 应用 base 64 编码的数据, 其每行长度为 76 个字符。MIME 继承了隐衷加强邮件 (PEM, Privacy Enhanced Mail) [3] 中的编码, 并指出它 "实际上是雷同的"; 然而, PEM 应用的每行长度为 64 个字符。MIME 和 PEM 的限度都是因为 SMTP 中存在的限度所造成的。 程序实现【禁止】向应用 base 编码的数据中增加换行符, 除非参考了此文档 的其它标准, 有明确地批示 base 编码器: 在特定数量的字符后增加换行符。Josefsson Standards Track [Page 3]RFC 4648 Base-N Encodings October 20063.2. 编码数据中的填充符 在某些状况下, 不须要或不必在 base 编码的数据中应用填充符 ("=")。在一 般状况下, 当无奈假如传输数据的大小时, 须要应用填充符来产生正确的编码 数据。 程序实现【必须】在编码数据的开端蕴含适当的填充字符, 除非参考了此文档 的其它标准另有明确规定。 base64 和 base32 编码中的字母表应用了填充符, 见上面第 4 节和第 6 节的 形容, 然而 base16 编码中的字母表不须要它, 见第 8 节。3.3. 编码数据中非字母表中字符的解释 Base 编码应用了一个非凡的、删减版的字母表来编码二进制数据。因为数据损 坏或设计起因, base 编码的数据中可能存在非字母表中的字符。非字母表中的 字符可能被用作 "荫蔽信道" ("covert channel"), 其中非协定的数据可能出 于歹意目标而被发送。此外, 为了摸索实现中的谬误 (例如, 可能导致内存溢 出攻打), 非字母表中的字符也可能会被发送。 当程序实现在解释 base 编码的数据时, 若发现数据中蕴含 base 字母表外的 字符, 程序实现【必须】回绝编码数据, 除非参考了此文档的其它标准另有明 确规定。这些标准可能会同 MIME 一样规定: 在解释数据时, 该当简略地疏忽 掉在 base 编码字母表以外的字符 ("在承受的内容上要放宽")。留神, 这象征 着: 任何相邻的回车/换行 (CRLF) 均形成 "非字母表中字符", 并被疏忽掉。 此外, 这类标准【能够】将呈现在编码数据开端的填充符 "=" 认作是非字母表 中的字符, 并将其疏忽掉。如果在字符串的开端发现了超出容许数量的填充字 符 (例如, 一个 base 64 字符串以 "===" 完结), 则超出的填充字符【能够】 被疏忽。3.4. 字母表的抉择 不同的利用对字母表中的字符有不同的需要。以下是一些需要, 用于确定该当 应用哪个字母表:Josefsson Standards Track [Page 4]RFC 4648 Base-N Encodings October 2006 o 由人类解决。字符 "0" 和 "O" 很容易混同, 字符 "1"、"l" 和 "I" 也很 容易混同。在上面的 base32 字母表中, 没有字符 "0" (零) 和 "1" (一), 依据状况, 一个解码器可能将 0 解释为 O, 并将 1 解释为 I 或 L 。(但 是, 在默认状况下, 不应如此; 见后面的章节。) o 编码后的数据, 其构造要满足其它要求。对于 base 16 和 base 32 编码, 这确定了应用大写或小写的字母表。对于 base 64 编码, 非字母表中的字 符 (特地是 "/") 可能会在文件名和 URL 中呈现问题。 o 用作标识符。一些字符, 特地是 base 64 字母表中的 "+" 和 "/", 会被传 统的文本搜寻/索引工具视为分词符。 没有可能满足所有的需要、被广泛承受的字母表。一个对于高度专业化变体的 示例, 见 IMAP [8]。在此文档中, 咱们记录并命名了一些以后正在被应用的字 母表。3.5. 标准编码 (Canonical Encoding) base 64 和 base 32 编码中的填充步骤, 如果没有被正确地实现, 将会导致编 码后的数据呈现不易觉察的扭转。例如, 对于 base 64 编码, 如果它的输出仅 为一个八位字节, 则应用到了第一个符号中所有 6 个比特位, 然而只应用了下 一个符号中前 2 个比特位。遵循协定的编码器【必须】将裁减的比特地位零, 这将在下文形容填充符时提高一阐明。如果不保留这一个性, 则不存在对 base 编码的标准示意, 且会呈现: 多个 base 编码字符串被解码为雷同的二进制数 据。如果保留这一个性, 则可能保障标准编码。 在一些环境中, 对于数据中的变动十分严格, 因而: 如果未将填充比特地位为 零, 则编码器【能够】抉择回绝编码数据。与此相关的标准可能规定一个非凡 的行为。4. Base 64 编码 下文中对 base 64 编码的形容来自于 [3], [4], [5] 与 [6]。能够应用 "base64" 来代称此编码方案。 Base 64 编码被设计成: 在容许应用辨别大小写的示意模式时, 它可能示意任 意的八字节序列, 然而并不需要被人类可读。Josefsson Standards Track [Page 5]RFC 4648 Base-N Encodings October 2006 编码应用了一个蕴含 US-ASCII 中的 65 个字符的字符子集, 其中的每个可打 印字符可能示意 6 比特的数据。(额定的第 65 个字符是 "=", 其被用于示意 须要非凡的解决)。 编码的过程是将 "24 位组" 的多组输出比特, 示意为多个 "由 4 个编码字符 形成" 的多个字符串。依照从左至右的解决程序, 每 3 个 "8 位组" 的原始输 入形成一个 "24 位组" 的编码输出。这些 "24 位组" 的输出将被视作由 4 个 "6 位组" 的数据形成, 每一组都会被编码为 base 64 字母表中的单个字符。 每个 6 位组的数据被用作 "64 个可打印字符的数组" 的索引。被索引所援用 的字符置于输入字符串中。 表 1: Base 64 编码的字母表 值 编码 值 编码 值 编码 值 编码 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 如果在数据的开端, 可用于编码的数据少于 24 比特, 则需进行非凡的解决。 使得在对数据的开端编码时, 总是可能以残缺的 "24 位组" 的编码方式完结。 当输出比特组中的位数少于 24 比特时, 会在输出的右侧增加值为 0 的比特, 以形成一个残缺的 "6 位组"。接着应用字符 "=" 对数据的开端进行填充。因 为, 所有 base 64 编码的输出都是整数个八位字节, 所以只会呈现一下状况: (1) 如果编码输出的最初局部的比特位数是 24 的整数倍; 则编码输入的最初 局部的字符个数是 4 的整数倍, 且没有用字符 "=" 填充。Josefsson Standards Track [Page 6]RFC 4648 Base-N Encodings October 2006 (2) 如果编码输出的最初局部的比特位数刚好是 8 位; 则编码输入的最初局部 将会是: 2 个编码字符, 再后跟 2 个 "=" 填充符。 (3) 如果编码输出的最初局部的比特位数刚好是 16 位; 则编码输入的最初部 分将会是: 3 个编码字符, 再后跟 1 个 "=" 填充符。5. 具备 "对 URL 和文件名平安的字母表" 的 Base 64 编码 具备 "对 URL 和文件名平安的字母表" 的 Base 64 编码, 曾经被用于 [12]。 有些替换用的字母表, 倡议应用 "~" 作为第 63 个字符。因为, 在一些文件系 统的环境中, 字符 "~" 具备非凡的含意, 所以倡议还是应用本节所形容的编码 计划。残余的未被 URI 所保留的字符是 ".", 然而在一些文件系统的环境中, 不容许在一个文件名中应用多个 ".", 因而使得字符 "." 也没有吸引力。 当在 URI [9] 中应用时, 填充字符 "=" 通常是被百分号编码的 (percent- encoded), 然而如果隐士地晓得数据的长度, 则能够通过跳过填充符来防止这 一状况; 见第 3.2 节。 这里给出的编码方案可用 "base64url" 来代称。不应认为此编码与 "base64" 编码雷同, 且不应仅用 "base64" 来指代此编码。除非另有阐明, 否则 "base64" 指代的是后面章节中的 base 64 编码。 此编码方案, 除了在第 62 个和第 63 个字符上有所区别, 从技术上而言与之 前的雷同, 如表 2 所示。Josefsson Standards Track [Page 7]RFC 4648 Base-N Encodings October 2006 表 2: "对 URL 和文件名平安的" Base 64 编码的字母表 值 编码 值 编码 值 编码 值 编码 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 (填充符) =6. Base 32 编码 下文中对 base 32 编码的形容来自于 (更正后的) [11]。能够应用 "base32" 来代称此编码方案。 Base 32 编码被设计成: 在须要应用不辨别大小写的示意模式时, 它可能示意 任意的八字节序列, 然而并不需要被人类可读。 编码应用了一个蕴含 US-ASCII 中的 33 个字符的字符子集, 其中的每个可打 印字符可能示意 5 比特的数据。(额定的第 33 个字符是 "=", 其被用于示意 须要非凡的解决)。 编码的过程是将 "40 位组" 的多组输出比特, 示意为多个 "由 8 个编码字符 形成" 的多个字符串。依照从左至右的解决程序, 每 5 个 "8 位组" 的原始输 入形成一个 "40 位组" 的编码输出。这些 "40 位组" 的输出将被视作由 8 个 "5 位组" 的数据形成, 每一组都会被编码为 base 32 字母表中的单个字符。 当一个比特流通过 base 32 编码方式进行编码时, 必须假设该比特流的位序满 足最高位优先。因而, 在比特流的第一个 8 位字节中, 第一个比特是最高位, 第八个比特是最低位, 依此类推。Josefsson Standards Track [Page 8]RFC 4648 Base-N Encodings October 2006 每个 5 位组的数据被用作 "32 个可打印字符的数组" 的索引。被索引所援用 的字符置于输入字符串中。这些字符是从 US-ASCII 的数字和大写字母中选出, 如下表 3 所示: 表 3: Base 32 编码的字母表 值 编码 值 编码 值 编码 值 编码 0 A 9 J 18 S 27 3 1 B 10 K 19 T 28 4 2 C 11 L 20 U 29 5 3 D 12 M 21 V 30 6 4 E 13 N 22 W 31 7 5 F 14 O 23 X 6 G 15 P 24 Y (填充符) = 7 H 16 Q 25 Z 8 I 17 R 26 2 如果在数据的开端, 可用于编码的数据少于 40 比特, 则需进行非凡的解决。 使得在对数据的开端编码时, 总是可能以残缺的 "40 位组" 的编码方式完结。 当输出比特组中的位数少于 40 比特时, 会在输出的右侧增加值为 0 的比特, 以形成一个残缺的 "5 位组"。接着应用字符 "=" 对数据的开端进行填充。因 为, 所有 base 32 编码的输出都是整数个八位字节, 所以只会呈现一下状况: (1) 如果编码输出的最初局部的比特位数是 40 的整数倍; 则编码输入的最初 局部的字符个数是 8 的整数倍, 且没有用字符 "=" 填充。 (2) 如果编码输出的最初局部的比特位数刚好是 8 位; 则编码输入的最初局部 将会是: 2 个编码字符, 再后跟 6 个 "=" 填充符。 (3) 如果编码输出的最初局部的比特位数刚好是 16 位; 则编码输入的最初部 分将会是: 4 个编码字符, 再后跟 4 个 "=" 填充符。 (4) 如果编码输出的最初局部的比特位数刚好是 24 位; 则编码输入的最初部 分将会是: 5 个编码字符, 再后跟 3 个 "=" 填充符。 (5) 如果编码输出的最初局部的比特位数刚好是 32 位; 则编码输入的最初部 分将会是: 7 个编码字符, 再后跟 1 个 "=" 填充符。Josefsson Standards Track [Page 9]RFC 4648 Base-N Encodings October 20067. 具备 "扩大十六进制的字母表" 的 Base 32 编码 下文中对 base 32 编码的形容来自于 [7]。能够应用 "base32hex" 来代称此 编码方案。不应认为此编码与 "base32" 编码雷同, 且不应仅用 "base32" 来 指代此编码。此编码有被用于 NextSECure3 (NSEC3) [10]。 此字母表具备一个 base64 和 base32 的字母表所短少的个性, 即: 当对数据 通过按位比拟的形式进行排序时, 该字母表能保障编码后的数据具备同原始数 据雷同的排序程序。 此编码方案, 除了在字母表上有所区别, 其它方面与之前的雷同。新的字母表 如表 4 所示。 表 4: "扩大十六进制的" Base 32 编码的字母表 值 编码 值 编码 值 编码 值 编码 0 0 9 9 18 I 27 R 1 1 10 A 19 J 28 S 2 2 11 B 20 K 29 T 3 3 12 C 21 L 30 U 4 4 13 D 22 M 31 V 5 5 14 E 23 N 6 6 15 F 24 O (填充符) = 7 7 16 G 25 P 8 8 17 H 26 Q8. Base 16 编码 下文中的形容是原始的, 然而与先前的形容相似。实质上, Base 16 编码是标 准的不辨别大小写的十六进制编码, 且能够应用 "base16" 或 "hex" 来代称此 编码方案。 编码应用了一个蕴含 US-ASCII 中的 16 个字符的字符子集, 其中的每个可打 印字符可能示意 4 比特的数据。 编码的过程是将 "8 位组" (即八位字节) 的多组输出比特, 示意为多个 "由 2 个编码字符形成" 的多个字符串。依照从左至右的解决程序, 从原始输出中取 出 "8 位组" 作为编码输出。这些 "8 位组" 的输出将被视作由 2 个 "4 位 组" 的数据形成, 每一组都会被编码为 base 16 字母表中的单个字符。 每个 4 位组的数据被用作 "16 个可打印字符的数组" 的索引。被索引所援用 的字符置于输入字符串中。Josefsson Standards Track [Page 10]RFC 4648 Base-N Encodings October 2006 表 5: Base 16 编码的字母表 值 编码 值 编码 值 编码 值 编码 0 0 4 4 8 8 12 C 1 1 5 5 9 9 13 D 2 2 6 6 10 A 14 E 3 3 7 7 11 B 15 F 不同于 base 32 和 base 64 编码, 这里不须要非凡的填充符; 因为 base 16 编码的最小单元是八位字节, 这在所有的数据中都能失去保障。9. 图解和示例 为了在二进制和 base 编码之间进行转换, 须要将输出存储在某一构造中, 并 从中提取所需的输入。下图中所展现的 base 64 编码的例子, 来自于 [5]。 +--first octet--+-second octet--+--third octet--+ |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| +-----------+---+-------+-------+---+-----------+ |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0| +--1.index--+--2.index--+--3.index--+--4.index--+ 下图所展现的 base 32 编码的例子, 来自于 [7]。在 base-32 编码后的值中, 每个间断的字符都示意: 原始的八位字节序列中的 5 个间断比特。因而, 每组 "由 8 个编码字符形成" 字符串示意一个 "由 5 个八位字节形成" (40 比特) 的序列。 1 2 3 01234567 89012345 67890123 45678901 23456789 +--------+--------+--------+--------+--------+ |< 1 >< 2| >< 3 ><|.4 >< 5.|>< 6 ><.|7 >< 8 >| +--------+--------+--------+--------+--------+ <===> 8th character <====> 7th character <===> 6th character <====> 5th character <====> 4th character <===> 3rd character <====> 2nd character <===> 1st characterJosefsson Standards Track [Page 11]RFC 4648 Base-N Encodings October 2006 上面无关 Base64 数据编码的示例来自于 [5] (已更正)。 Input data: 0x14fb9c03d97e Hex: 1 4 f b 9 c | 0 3 d 9 7 e 8-bit: 00010100 11111011 10011100 | 00000011 11011001 01111110 6-bit: 000101 001111 101110 011100 | 000000 111101 100101 111110 Decimal: 5 15 46 28 0 61 37 62 Output: F P u c A 9 l + Input data: 0x14fb9c03d9 Hex: 1 4 f b 9 c | 0 3 d 9 8-bit: 00010100 11111011 10011100 | 00000011 11011001 pad with 00 6-bit: 000101 001111 101110 011100 | 000000 111101 100100 Decimal: 5 15 46 28 0 61 36 pad with = Output: F P u c A 9 k = Input data: 0x14fb9c03 Hex: 1 4 f b 9 c | 0 3 8-bit: 00010100 11111011 10011100 | 00000011 pad with 0000 6-bit: 000101 001111 101110 011100 | 000000 110000 Decimal: 5 15 46 28 0 48 pad with = = Output: F P u c A w = =10. 测试样例 BASE64("") = "" BASE64("f") = "Zg==" BASE64("fo") = "Zm8=" BASE64("foo") = "Zm9v" BASE64("foob") = "Zm9vYg==" BASE64("fooba") = "Zm9vYmE=" BASE64("foobar") = "Zm9vYmFy" BASE32("") = "" BASE32("f") = "MY======" BASE32("fo") = "MZXQ===="Josefsson Standards Track [Page 12]RFC 4648 Base-N Encodings October 2006 BASE32("foo") = "MZXW6===" BASE32("foob") = "MZXW6YQ=" BASE32("fooba") = "MZXW6YTB" BASE32("foobar") = "MZXW6YTBOI======" BASE32-HEX("") = "" BASE32-HEX("f") = "CO======" BASE32-HEX("fo") = "CPNG====" BASE32-HEX("foo") = "CPNMU===" BASE32-HEX("foob") = "CPNMUOG=" BASE32-HEX("fooba") = "CPNMUOJ1" BASE32-HEX("foobar") = "CPNMUOJ1E8======" BASE16("") = "" BASE16("f") = "66" BASE16("fo") = "666F" BASE16("foo") = "666F6F" BASE16("foob") = "666F6F62" BASE16("fooba") = "666F6F6261" BASE16("foobar") = "666F6F626172"Josefsson Standards Track [Page 13]RFC 4648 Base-N Encodings October 200611. ISO C99 中的 Base64 编码的实现 在 ISO C99 中有 Base64 编码与解码的实现, 该实现被认为是遵循了此 RFC 中的所有倡议, 能够从这里获取: http://josefsson.org/base-encoding/ 其中给出的代码不是必须的。 因为工作流程相干的起因, 不能在此 RFC 中蕴含该代码 (见 RFC 3978 中第 5.4 节)。12. 平安注意事项 在实现 base 编码与解码时, 须要留神: 不要引入会造成内存溢出攻打、或其 它攻打的破绽。解码器不应因有效输出而解体, 例如遇到了嵌入在数据中的字 符 NUL (ASCII 0). 在解码过程中, 如果抉择疏忽掉非字母表中的字符, 且没有 (依照倡议) 回绝 掉整个编码数据, 则可能产生成一个导致信息 "泄露" 的荫蔽信道 (covert channel)。被疏忽的字符也能够被用于其它的歹意目标, 例如: 躲避字符串的 判等、或登程实现中的 bug。未遵循举荐做法的利用, 该当弄清: 疏忽非字母 表中的字符, 这一行为背地的含意。相似的, 当以不辨别大小写的形式来解决 base 16 和 base 32 的字母表时, 字母大小写的变动可能被用于泄露信息、或 导致字符串的判等失败。 当应用填充符时, 须要思考一些非无效比特位的安全性, 因为它们可能被滥用 来泄露信息、或绕过字符串的判等、或触发实现中存在的问题。 Base 编码从视觉上暗藏了那些的易被辨认的信息, 例如明码, 然而它实际上并 未提供任何的计算保密性。而这有可能会导致安全事故, 例如: 当用户在报告 网络协议所替换的详细信息时 (可能是为了阐明其它问题), 会意外地将明码泄 露, 因为她并没有意识到 base 编码不能爱护明码。 Base 编码不会使文本熵增, 然而它的确减少了文本的长度, 并以特色概率分布 (characteristic probability distribution) 的模式为明码剖析过程 (cryptanalysis) 提供了签名。Josefsson Standards Track [Page 14]RFC 4648 Base-N Encodings October 200613. 自 RFC 3548 以来的批改 增加了 "应用扩大十六进制字母表的 base32" 的内容, 该编码被用于保留编码 数据的排序程序。 参考了 IMAP, 以阐明其中用到的非凡的 Base64 编码。 修复了从 RFC 2440 复制过去的示例。 增加了无关 "提供明码剖析签名" 的平安注意事项。 增加了测试样例。 修复了笔误。14. 致谢 Several people offered comments and/or suggestions, including John E. Hadstate, Tony Hansen, Gordon Mohr, John Myers, Chris Newman, and Andrew Sieber. Text used in this document are based on earlier RFCs describing specific uses of various base encodings. The author acknowledges the RSA Laboratories for supporting the work that led to this document. This revised version is based in parts on comments and/or suggestions made by Roy Arends, Eric Blake, Brian E Carpenter, Elwyn Davies, Bill Fenner, Sam Hartman, Ted Hardie, Per Hygum, Jelte Jansen, Clement Kent, Tero Kivinen, Paul Kwiatkowski, and Ben Laurie.15. Copying Conditions Copyright (c) 2000-2006 Simon Josefsson Regarding the abstract and sections 1, 3, 8, 10, 12, 13, and 14 of this document, that were written by Simon Josefsson ("the author", for the remainder of this section), the author makes no guarantees and is not responsible for any damage resulting from its use. The author grants irrevocable permission to anyone to use, modify, and distribute it in any way that does not diminish the rights of anyone else to use, modify, and distribute it, provided that redistributed derivative works do not contain misleading author or version information and do not falsely purport to be IETF RFC documents. Derivative works need not be licensed under similar terms.Josefsson Standards Track [Page 15]RFC 4648 Base-N Encodings October 200616. 参考文献16.1. 前提类参考文献 [1] Cerf, V., "ASCII format for network interchange", RFC 20, October 1969. [2] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.16.2. 信息类参考文献 [3] Linn, J., "Privacy Enhancement for Internet Electronic Mail: Part I: Message Encryption and Authentication Procedures", RFC 1421, February 1993. [4] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996. [5] Callas, J., Donnerhacke, L., Finney, H., and R. Thayer, "OpenPGP Message Format", RFC 2440, November 1998. [6] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, "DNS Security Introduction and Requirements", RFC 4033, March 2005. [7] Klyne, G. and L. Masinter, "Identifying Composite Media Features", RFC 2938, September 2000. [8] Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1", RFC 3501, March 2003. [9] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005. [10] Laurie, B., Sisson, G., Arends, R., and D. Blacka, "DNSSEC Hash Authenticated Denial of Existence", Work in Progress, June 2006. [11] Myers, J., "SASL GSSAPI mechanisms", Work in Progress, May 2000. [12] Wilcox-O'Hearn, B., "Post to P2P-hackers mailing list", http://zgp.org/pipermail/p2p-hackers/2001-September/ 000315.html, September 2001.Josefsson Standards Track [Page 16]RFC 4648 Base-N Encodings October 2006作者地址 Simon Josefsson SJD EMail: simon@josefsson.orgJosefsson Standards Track [Page 17]RFC 4648 Base-N Encodings October 2006Full Copyright Statement Copyright (C) The Internet Society (2006). This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights. This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.Intellectual Property The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79. Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr. The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.Acknowledgement Funding for the RFC Editor function is provided by the IETF Administrative Support Activity (IASA).Josefsson Standards Track [Page 18]

August 3, 2020 · 14 min · jiezi

最常见的OpenSSL命令

https://www.sslshopper.com/ar... 最通用的SSL工具之一是OpenSSL,它是SSL协议的开源实现。几乎每个平台都有OpenSSL版本,包括Windows,Linux和Mac OS X.OpenSSL通常用于为许多不同平台(包括Apache)创建CSR和私钥。但是,它还有数百种不同的功能,允许您查看CSR或证书的详细信息,比较证书的MD5哈希和私钥(以确保它们匹配),验证证书是否在任何网站上正确安装,并将证书转换为其他格式。可以在此处找到OpenSSL for Windows的编译版本。 如果您不想打扰OpenSSL,可以使用我们的SSL证书工具执行许多相同的操作。下面,我们列出了最常见的OpenSSL命令及其用法: 常规OpenSSL命令这些命令允许您生成CSR,证书,私钥以及执行其他其他任务。 Base64编解码编码: echo "我是一片云 天空是我家\n朝迎旭日升 暮送夕阳下" | openssl enc -base64输出: 5oiR5piv5LiA54mH5LqRIOWkqeepuuaYr+aIkeWutlxu5pyd6L+O5pet5pel5Y2H44CA5pqu6YCB5aSV6Ziz5LiLCg== 对上面的字符串解码 echo '5oiR5piv5LiA54mH5LqRIOWkqeepuuaYr+aIkeWutlxu5pyd6L+O5pet5pel5Y2H44CA5pqu6YCB5aSV6Ziz5LiLCg==' |openssl enc -base64 -d输出: 我是一片云 天空是我家\n朝迎旭日升 暮送夕阳下注意:这里编码和解码都是用的 enc 命令,只是解码加了-d参数。md5摘要形成摘要: echo "我是一片云 天空是我家 朝迎旭日升 暮送夕阳下" | openssl md5输出 (stdin)= 2418617a0586d93db1db5e43260a43bb校验摘要:再生成一次,对比生成的字符串。 生成服务器端 web 服务器密码用于基本验证访问的服务器密码, 密码只能是8位, 多了会有警告。 openssl passwd -crypt yourpass会生成 U0tfb.p0Pit5I重复执行上面的指令时密码会有变化。所以密码是有随机变量在里面。 保存到 ·/etc/nginx/conf.d/pass`文件中 $ cat /etc/nginx/conf.d/passyouradmin:U0tfb.p0Pit5I密码文件是 用户名:加密密码 的格式存储的。 Nginx服务器的配置 server { server_name yourserver.cn; root /var/www/webapps/; index index.html index.htm; location / { auth_basic "server login auth"; auth_basic_user_file conf.d/pass;...这样就能通过基本验证, 保护服务器的内容只能在输入密码的情况下进行访问。 ...

October 18, 2019 · 2 min · jiezi

golang基础学习base64使用

在近期的项目开发中对图片进行base64编码,简单使用了golang的base64包。 1.使用方法1.1 引入包import "encoding/base64" 1.2 base64使用这里所有的例子都是官网上的范例;code: msg := "Hello, 世界"encoded := base64.StdEncoding.EncodeToString([]byte(msg))fmt.Println(encoded)decoded, err := base64.StdEncoding.DecodeString(encoded)if err != nil { fmt.Println("decode error:", err) return}fmt.Println(string(decoded))Output: SGVsbG8sIOS4lueVjA==Hello, 世界2. 包详解2.1包详解bash64包详解 上面途中的Constants: const ( StdPadding rune = '=' // Standard padding character NoPadding rune = -1 // No padding)上面途中的Variables: var RawStdEncoding = StdEncoding.WithPadding(NoPadding)var RawURLEncoding = URLEncoding.WithPadding(NoPadding)var StdEncoding = NewEncoding(encodeStd) 案例中使用的是该变量var URLEncoding = NewEncoding(encodeURL) 以2.2节案例中详解:base64加密:base64.StdEncoding 如上面变量所解释,接收了“NewEncoding(encodeStd)”返回的结果“*Encoding”;根据返回结果 再执行EncodeToString(str []byte) string 这个方法;在源码中,EncodeToString 其实执行中的方法Encode(dst, src []byte),把结果string了一下。 当然秉着我省事的原则,我一直比较习惯用EncodeToString打印“encoded := base64.StdEncoding.EncodeToString([]byte(msg))”后生成: SGVsbG8sIOS4lueVjA== ...

August 21, 2019 · 1 min · jiezi

Base64-编码与解码详解

Base64 是基于 64 个可打印字符 A-Z、a-z、0-9、+、/ 来表示二进制数据的表示方法,常用于数据在网络中的传输。本篇将分别介绍其编码、解码以及实际运用。 Base64 编码Base64 本质是一种将二进制转为文本的方案。基本规则如下: 编码时候选用 64 (大小写英文字母,数字,+ /)个字符以及用作补位的=来表示在编码的时候,将3个字节变为4个字节,4个字节的高两位都用 00 来填充,后 6 位来表示 64 个字符。以一个实际的例子 "YOU" 为例,其编码过程如下: 由上表格可知 "YOU"对应的 Base64 编码为:"WU9V"。 对于要待编码的字符数如果不是 3 的倍数时候,会用 0 去填充,编码出来后用 = 号表示,如: "ME" 其编码如下: Base64 解码将 4 个字节变为 3 个字节; 将 24 bit 左移 16 位,与 255 进行与操作,获得第一个字符,将 24 bit 左移 8 位,与 255 进行与操作,获得第二个字符,将 24 bit 与 255 进行与操作,获取第三个字符Base64 实现与运用场景在 Node 中提供 Buffer 模块,可以进行二进制或者字符与 Base64 的想换转换,其代码如下: ...

June 15, 2019 · 1 min · jiezi

前端bug录移动端下载图片

前天,快下班的时候,一朋友发来一个战绩图。这是要约我上分?(这兄弟一手 C 位吊打亲友)。我果断拒绝三连。结果,小韭菜问我,右边那个图怎么做?那好了,事情从这里开始 分析一下需求这个图好像叫雷达图,那我们先去看 echarts,简直不要太像好吗? 小韭菜没给我反应的机会提出了另一个想法:简单一点简单一点,我又想起了 Vue官网 有这个东西。 小韭菜看都没看就说:不用 VueWhat?我只是让你看看原理啊。那好吧,我看了一眼,就是 svg 实现 SVG 实现雷达图jsrun测试地址,如果 jsrun 挂了,可以去我个人网站上看测试地址。 <svg width="200" height="200" class="demo-svg warp"> <polygon points="100,10.899999999999991 175.32367609057616,75.52585404550416 145.49457852743743,162.61791536462093 71.43363673858582,139.31822592662246 41.795341202736594,81.08815994425322" class="demo-polygon" style="fill: #41B883;"></polygon> </svg>SVG 的 polygon<polygon> 标签用来创建含有不少于三个边的图形。points 属性定义多边形每个角的 x 和 y 坐标 那我们来看上面的图片,正好五个角,那我们就可以动手改改。简单的一匹 100,10.899999999999991175.32367609057616,75.52585404550416145.49457852743743,162.6179153646209371.43363673858582,139.3182259266224641.795341202736594,81.08815994425322实现下载雷达图因为快下班了,小韭菜看了一眼说搞定。然后又提出了一个需求,下载这个图片。我一想简单的一匹啊。我前两天才写了文章的 前端培训-初级阶段-场景实战(2019-06-06)-下载文件&下载进度 小韭菜之前用过 html2canvas 还是啥来着。直接这样搞download 直接下载(svgToDataurl)svgToCanvas 然后下载 canvas 的图片canvas 的 toBlob 结合 URL.createObjectURL 和 downloadcanvas 的 toDataUrl 结合 download为啥我上面写了这么多的方法。因为移动端不好使。不好使的原因就是 DataURL 和 BlobURL 在移动端(微信、QQ、QQ浏览器)无法下载。 SVG 怎么用 img 显示这个还是当时在张鑫旭张大师哪里看到的方法。SVGTODataURL data:image/svg+xml,%3Csvg xmlns='http://w这样我们就可以显示了。 download 直接下载上面我们显示了出来,直接下载吧。nonono,因为上面的 Dataurl 是 svg 格式的,下载也是 SVG 格式的。所以我们需要用 img 读取 svgurl。然后 canvas 读取 img 。然后 canvas 输出想要的图片格式。然后再下载。 ...

June 6, 2019 · 1 min · jiezi

angular使用md5CryptoJS-des加密

在业务系统中,通常需要对用户的密码进行加密,再时行http的请求。加强系统登录的安全验证。 常用的加密方式有MD5, Base64, CryptoJS的 AES DES等。下面介绍我常用的几种加密方法的使用: MD5加密1. 安装模块 ts-md5$ npm install ts-md5 --save2. 使用md5进行加密import { Md5 } from 'ts-md5';// ...// 密码password: string = "12345";// 加密方法 - md5加密decode() { const passwordMd5 = Md5.hashStr(this.password).toString(); // 结果:827ccb0eea8a706c4c34a16891f84e7b}Base64加密1.安装模块 js-base64$ npm install js-base64 --save2.使用md5进行加密import { Base64 } from 'js-base64';// ...// 密码password: string = "12345";// 加密方法 - Base64加密decode() { const passwordBase64 = Base64.encode(password); // 结果:MTIzNDU=}DES加密DES对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥key,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码),是一种对称加密算法。crypto-js Github: https://github.com/brix/crypt... 1.安装模块 crypto-js$ npm install crypto-js --save2.使用DES进行加密import CryptoJS from 'crypto-js';// ...// 密钥key: string = "abcdefg";// 密码password: string = "12345";// 加密方法 - des加密decode() { // key编码 const keyHex = CryptoJS.enc.Utf8.parse(this.key); console.log(keyHex.toString()); // 结果:61626364656667 // 加密 const passwordDES = CryptoJS.DES.encrypt(this.password, keyHex, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }).toString(); console.log(passwordDES); // 结果:zYGeIdaZpEM=}3. 使用AES进行加密加密用法基本与des一致。 ...

June 3, 2019 · 1 min · jiezi

「 加密 」Base64

一. 简介首先有个小Tips,1个字母字符 = 1个字节(byte) = 8位(bit),这是表示单位.Base64是网络上最常见的用于传输 8bit 的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。在一些网络传送渠道,有时候有些的字节字符不能被支持.比如图片的二进制流的每个字节不可能全部是可见字符,这种情况下传送不了.而Base64的机制就能很好解决这种问题,它不改变原来的协议,在原来的基础做一种扩展,基于64个可打印字符来表示二进制.再者,有时候我们通过记事本去打开一些图片或者应用程序,会得到一大堆看不懂的乱码,因为二进制文件里面有很多无法显示和打印的字符.所以如果要让记事本能够处理二进制数据,就可以使用Base64来进行转码,将不可见的转成可见的.二. 算法原理我们拿到一串字符,比如 abcdef.先按ASCII码编码.它会将字符串按字节数分开,每三个字节为一组. 3 byte * 8 bit === 24bit.在这组中,将24位数据按照每6位为一组,再次分成4组.然后将这四组的6位数的高位各补两个0,将其转为十进制数.进行查表,得到对应的字符,就是对应的Base64转化的字符.那么有个问题来了,如果原始数据的位数不是3的整数倍怎么办,Base会在不足的后面用"=“补足,所以这个”=“只会存在在Base64码的最后,并且只会有1或者2个,不可能出现在中间.// javaScript实现if (!Shotgun) var Shotgun = {};if (!Shotgun.Js) Shotgun.Js = {};Shotgun.Js.Base64 = { _table: [ ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’, ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’, ‘Y’, ‘Z’, ‘a’, ‘b’, ‘c’, ’d’, ’e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ’l’, ’m’, ’n’, ‘o’, ‘p’, ‘q’, ‘r’, ’s’, ’t’, ‘u’, ‘v’, ‘w’, ‘x’, ‘y’, ‘z’, ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘+’, ‘/’ ], encode: function (bin) { var codes = []; var un = 0; un = bin.length % 3; if (un == 1) bin.push(0, 0); else if (un == 2) bin.push(0); for (var i = 2; i < bin.length; i += 3) { var c = bin[i - 2] << 16; c |= bin[i - 1] << 8; c |= bin[i]; codes.push(this._table[c >> 18 & 0x3f]); codes.push(this._table[c >> 12 & 0x3f]); codes.push(this._table[c >> 6 & 0x3f]); codes.push(this._table[c & 0x3f]); } if (un >= 1) { codes[codes.length - 1] = “=”; bin.pop(); } if (un == 1) { codes[codes.length - 2] = “=”; bin.pop(); } return codes.join(”"); }, decode: function (base64Str) { var i = 0; var bin = []; var x = 0, code = 0, eq = 0; while (i < base64Str.length) { var c = base64Str.charAt(i++); var idx = this._table.indexOf(c); if (idx == -1) { switch (c) { case ‘=’: idx = 0; eq++; break; case ’ ‘: case ‘\n’: case “\r”: case ‘\t’: continue; default: throw { “message”: “\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u65E0\u6548\u7F16\u7801\uFF1A” + c }; } } if (eq > 0 && idx != 0) throw { “message”: “\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u683C\u5F0F\u9519\u8BEF\uFF01” }; code = code << 6 | idx; if (++x != 4) continue; bin.push(code >> 16); bin.push(code >> 8 & 0xff); bin.push(code & 0xff) code = x = 0; } if (code != 0) throw { “message”: “\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u6570\u636E\u957F\u5EA6\u9519\u8BEF” }; if (eq == 1) bin.pop(); else if (eq == 2) { bin.pop(); bin.pop(); } else if (eq > 2) throw { “message”: “\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u683C\u5F0F\u9519\u8BEF\uFF01” }; return bin; }};三. 应用Base64编码可用于在HTTP环境下传递较长的标识信息.电子邮件:有些文本协议不支持不可见字符的传递,只能用大于32的可见字符来传递信息Base64 也会经常用作一个简单的“加密”来保护某些数据,而真正的加密通常都比较繁琐.垃圾讯息传播者用Base64来避过反垃圾邮件工具,因为那些工具通常都不会翻译Base64的讯息.前端在实现页面一些比较小的图片,通常会选择将图片内容直接内嵌在页面中,避免不必要的外部资源加载,增大页面加载时间,但是图片数据是二进制数据,该怎么嵌入呢?绝大多数现代浏览器都支持一种名为 Data URLs 的特性,允许使用Base64对图片或其他文件的二进制数据进行编码,将其作为文本字符串嵌入网页中。比如webpack工具中的url-loader默认将8kb以下的图片编译成Base64码嵌在引用文件中.四. 前端应用crypto-js 功能强大,不止处理Base64,支持的模块非常多,star数目前6k+,前后端可用//后端 npm包管理npm install crypto-jsimport sha256 from ‘crypto-js/sha256’;import hmacSHA512 from ‘crypto-js/hmac-sha512’;import Base64 from ‘crypto-js/enc-base64’;const message, nonce, path, privateKey; // …const hashDigest = sha256(nonce + message);const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey));//前端 Brower管理bower install crypto-jsjs-Base64专门处理Base64,目前star数2k+,前后端均可用//安装$ npm install –save js-base64//如果你使用的es6语法,需要转载这个进行语法转换$ npm install –save babel-preset-env//node.jsvar Base64 = require(‘js-base64’).Base64;//es6+import { Base64 } from ‘js-base64’;//非常轻快的使用体验Base64.encode(‘dankogai’); // ZGFua29nYWk=Base64.encode(‘小飼弾’); // 5bCP6aO85by+Base64.encodeURI(‘小飼弾’); // 5bCP6aO85by五. 解密如果你看懂了以上的算法原理,那么解密其实不是太大的问题,只要你遵循这个规则进行逆推运算,就可以得到原始数据.所以严格上说Base64并不是什么加密,只是编译过后的并不是明文而已 ...

April 18, 2019 · 2 min · jiezi

乐字节-Java8新特性之Base64和重复注解与类型注解

上一篇小乐给大家说了《乐字节-Java8新特性之Date API》,接下来小乐继续给大家说一说Java8新特性之Base64和重复注解与类型注解。一、Base64在Java 8中,内置了Base64编解码相关的特性。Java 8中使用三种类型的Base64编解码:简易模式:输出是完全按照A-Za-z0-9+/字符集映射的。编码不会自己增加输出行,解码器也不会接受任何超出A-Za-z0-9+/范围的内容。URL模式:输出基于A-Za-z0-9+/的映射,但对于URL和文件名是安全的。MIME模式:输出对于MIME类型的内容是友好的。如果超过76个字符,则会换行输出。,并且换行符n之后会自动添加一个r。如果某行没有r则说明输出的内容已经结束。1、Base64 内部类与方法Base64相关的内部类:Base64.Encoder:这是一个静态类。实现了Base64的编码功能,格式遵循了RFC 4648和RFC 2045标准。Base64.Decoder:也是一个静态类。实现了Base64的解码功能。相关的方法:getEncoder():该方法返回一个使用基本Base64编码格式的Encoder对象。相反的解码方法是getDecoder()。getUrlEncoder():该方法返回一个使用URL类型的Base64编码格式的Encoder对象。相反的解码方法是getUrlDecoder()。getMimeEncoder():该方法返回一个使用MIME类型的Base64编码格式的Encoder对象。相反的解码方法是getMimeDecoder()。2、Base64 使用对于Base64应用场景 无论是传统软件还是互联网项目开发都是比较常见的,比如传统的邮件,Http Url 地址通常都会应用Base64 来对协议内容或Url 地址信息进行编解码操作。public static void main(String[] args) throws Exception { // 使用基本的Base64编码 String base64encodedString = Base64.getEncoder() .encodeToString(“java8 is so Easy!!!".getBytes(“utf-8”)); System.out.println(“Basic base64 encoding:” + base64encodedString); // 解码并输出结果 byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString); System.out.println(“Original content: " + new String(base64decodedBytes, “utf-8”)); // 使用URL类型的Base64编码 base64encodedString = Base64.getUrlEncoder().encodeToString(“https://www.sina.com”.getBytes(“utf-8”)); System.out.println(“URL base64 encoding:” + base64encodedString); // MIME类型的Base64编码 StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < 10; ++i) { stringBuilder.append(UUID.randomUUID().toString()); } byte[] mimeBytes = stringBuilder.toString().getBytes(“utf-8”); String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes); System.out.println(“MIME base64 encoding:” + mimeEncodedString); }二、重复注解与类型注解Java5引入了注解特性,使得开发更加的灵活,特别是现在很多的应用都是基于注解零配置开发,都是建立在Annotation基础之上,同时使得开发变得简单,Java 8对注解处理提供了两点改进:可重复的注解及可用于类型的注解。 通常用于框架底层代码开发1、可重复注解定义与使用/** * 定义可重复注解 /@Repeatable(MyParams.class)@Target({ ElementType.FIELD, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface MyParam { String value() default “”;}@Target({ ElementType.FIELD, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface MyParams { MyParam[] value();}// 使用注解 方法上标注重复注解@MyParam(“hello”)@MyParam(“java8”)public void testAnnotation(){ System.out.println(“可重复注解测试…”);}/* 查找指定方法级别注解 遍历输出注解value 值*/public static void main(String[] args) throws Exception{ Class<TestAnnotation> clazz = TestAnnotation.class; Method method = clazz.getMethod(“testAnnotation”); MyParam[] params = method.getAnnotationsByType(MyParam.class); for (MyParam param : params) { System.out.println(param.value()); }}2、用于类型的注解@Repeatable(MyParams.class)@Target({ ElementType.FIELD, ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface MyParam { String value() default “”;}//使用public class TestAnnotation { private MyParam param;// 定义成员变量param 类型为MyParam 注解类型 public static void main(String[] args) throws Exception{ // 获取成员变量 并输出变量类型 Field field= clazz.getDeclaredField(“param”); System.out.println(field); System.out.println(field.getType()); }} ...

April 15, 2019 · 1 min · jiezi