java_security之base64原理解析以及三种代码的实现方式
一. Base64编码由来
为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送。这样用途就受到了很大的限制,比如图片二进制流的每个字节不可能全部是可见字符,所以就传送不了。最好的方法就是在不改变传统协议的情 况下,做一种扩展方案来支持二进制文件的传送。把不可打印的字符也能用可打印字符来表示,问题就解决了。Base64编码应运而生,Base64就是一种 基于64个可打印字符来表示二进制数据的表示方法。
二. Base64编码原理
看一下Base64的索引表,字符选用了"A-Z、a-z、0-9、+、/" 64个可打印字符。数值代表字符的索引,这个是标准Base64协议规定的,不能更改。64个字符用6个bit位就可以全部表示,一个字节有8个bit 位,剩下两个bit就浪费掉了,这样就不得不牺牲一部分空间了。这里需要弄明白的就是一个Base64字符是8个bit,但是有效部分只有右边的6个 bit,左边两个永远是0。
那么怎么用6个有效bit来表示传统字符的8个bit呢?8和6的最小公倍数 是24,也就是说3个传统字节可以由4个Base64字符来表示,保证有效位数是一样的,这样就多了1/3的字节数来弥补Base64只有6个有效bit 的不足。你也可以说用两个Base64字符也能表示一个传统字符,但是采用最小公倍数的方案其实是最减少浪费的。结合下边的图比较容易理解。Man是三个 字符,一共24个有效bit,只好用4个Base64字符来凑齐24个有效位。红框表示的是对应的Base64,6个有效位转化成相应的索引值再对应 Base64字符表,查出"Man"对应的Base64字符是"TWFU"。说到这里有个原则不知道你发现了没有,要转换成Base64的最小单位就是三个字节,对一个字符串来说每次都是三个字节三个字节的转换,对应的是Base64的四个字节。这个搞清楚了其实就差不多了。
但是转换到最后你发现不够三个字节了怎么办呢?愿望终于实现了,我们可以用两 个Base64来表示一个字符或用三个Base64表示两个字符,像下图的A对应的第二个Base64的二进制位只有两个,把后边的四个补0就是了。所以 A对应的Base64字符就是QQ。上边已经说过了,原则是Base64字符的最小单位是四个字符一组,那这才两个字 符,后边补两个"="吧。其实不用"="也不耽误解码,之所以用"=",可能是考虑到多段编码后的Base64字符串拼起来也不会引起混淆。由此可见 Base64字符串只可能最后出现一个或两个"=",中间是不可能出现"="的。下图中字符"BC"的编码过程也是一样的。
三:base64的三种实现方式:
方式一:jdk方式实现
// 用jdk实现public static void jdkBase64(){try {BASE64Encoder encoder = new BASE64Encoder();String encode = encoder.encode(src.getBytes());System.out.println("encode:" + encode);BASE64Decoder decoder = new BASE64Decoder();System.out.println("decode:" + new String(decoder.decodeBuffer(encode)));} catch (Exception e) {e.printStackTrace();}}
方式二:用Apache的common codes实现
// 用Apache的common codes实现public static void commonsCodesBase64(){byte[] encodeBytes = Base64.encodeBase64(src.getBytes());System.out.println("common codes encode:" + new String(encodeBytes));byte[] dencodeBytes = Base64.decodeBase64(encodeBytes);System.out.println("common codes decode:" + new String(dencodeBytes));}
方式三:用bouncy castle实现
// 用bouncy castle实现public static void bouncyCastleBase64(){byte[] encodeBytes = org.bouncycastle.util.encoders.Base64.encode(src.getBytes());System.out.println("bouncy castle encode:" + new String(encodeBytes));byte[] dencodeBytes = org.bouncycastle.util.encoders.Base64.decode(encodeBytes);System.out.println("bouncy castle decode:" + new String(dencodeBytes));}
总结
说起Base64编码可能有些奇怪,因为大多数的编码都是由字符转化成二进制的过程,而从二进制转成字符的过程称为解码。而Base64的概念就恰好反了,由二进制转到字符称为编码,由字符到二进制称为解码。
Base64编码主要用在传输、存储、表示二进制等领域,还可以用来加密,但是这种加密比较简单,只是一眼看上去不知道什么内容罢了,当然也可以对Base64的字符序列进行定制来进行加密。
Base64编码是从二进制到字符的过程,像一些中文字符用不同的编码转为二 进制时,产生的二进制是不一样的,所以最终产生的Base64字符也不一样。例如"上网"对应utf-8格式的Base64编码是"5LiK572R", 对应GB2312格式的Base64编码是"yc/N+A=="。
好了,已经理解了什么是base64,相信大家最关心的还是base64的实现方式,下面我就对base64的3中实现方式一一实现给出具体的代码实现:
java_security之base64原理解析以及三种代码的实现方式相关推荐
- JSON数据解析的三种情况+pjson的方式
直接解析JavaScript中的json字符串 <!-- 解析页面内的字符串 --> <div align="center"><table class ...
- SSO单点登录三种情况的实现方式详解
SSO单点登录三种情况的实现方式详解 单点登录(SSO--Single Sign On)对于我们来说已经不陌生了.对于大型系统来说使用单点登录可以减少用户很多的麻烦.就拿百度来说吧,百度下面有很多的子 ...
- (转)Spring的三种实例化Bean的方式
http://blog.csdn.net/yerenyuan_pku/article/details/52832793 Spring提供了三种实例化Bean的方式. 使用类构造器实例化. <be ...
- SpringBoot 三种拦截http请求方式Filter,interceptor和aop
SpringBoot 三种拦截http请求方式Filter,interceptor和aop. 这三种拦截方式的拦截顺序是:filter->Interceptor-->ControllerA ...
- zynq学习03 zynq中三种实现GPIO的方式
http://m.blog.csdn.net/article/details?id=52123465 http://blog.chinaaet.com/songhuangong/p/43084 本文介 ...
- Objective-C:三种文件导入的方式以及atomic和nonatomic的区别
一.三种文件导入的方式比较: 类的前项声明@class.import.include: 1.采用@class 类名的方式,它会告诉编译器有这么一个类,目前不需要知道它内部的实例变量和方法是如何定义 ...
- 浅淡Webservice、WSDL三种服务访问的方式(附案例)
Webservice Webservice是使应用程序以与平台和编程语言无关的方式进行相互通信技术. eg:站点提供访问的数据接口:新浪微博.淘宝. 官方解释:它是一种构建应用程序的普遍模型,可以在任 ...
- Python中的urllib,urllib三种不同的请求方式
1.urllib获取服务器的资源 自定义爬虫的重要组件 获取百度首页的资源: #3.x的标准写法 import urllib.request import urllib.parse#百度的首页 fro ...
- JAVA 三种线程实现创建方式
JAVA 三种线程实现/创建方式 方式一:继承Thread类 通过继承Thread类来创建一个自定义线程类.Thread类本质上就继承了Runable接口,代表一个线程类.启动线程的唯一办法就是通过T ...
最新文章
- Linux 的多线程编程的高效开发经验
- ubutnu16.04搭建LAMP环境(搭建wordpress博客)
- WLAN高密无线网络部署的信道问题
- SAP Fiori应用里日期格式的显示奥秘
- java 上传文件编码_(java)有什么办法把MultipartFile上传的文件转为utf-8的编码吗
- ios把数据传递到另一个页面_IOS 应用之间的跳转和数据传递详解
- 关于html标签元素的data-*属性
- linux git ssh_Git年满13岁,可以了解Linux和SSH命令,Python编程等等
- SpringBoot 阶段总结
- Exchange 日志/存储路径
- 当下流行的语音识别技术是不是发展错了方向?
- Kontakt 6 for Mac(强大的音频采样器软件)
- CC***的解决方案
- 开发技巧 | Python极简实现滑动平均滤波(基于Numpy.convolve)
- Jmeter二次开发实现rsa加密
- error: crosses initialization of
- 【产品经理】003-梁宁·产品思维30讲-机会判断(未完待续)
- SQL Server 2008 中文企业版下载
- Ubuntu18.04安装灭霸SLAM:ORBSLAM3
- C# 添加Word页眉、页脚和页码
热门文章
- 面试造飞机,工作拧螺丝。
- Databricks文档03----Azure Databricks 创建
- Python3 爬虫(一)-- 简单网页抓取
- 投资大佬段永平:抄底腾讯,不等了!
- 一加手机史上超大购机优惠 以旧换新至高补贴3800元
- 格力电器成为银隆新能源股东 持股30.47%
- 供应商禁止供货后,这个城市行动了:社区团购不得低价倾销、排挤对手
- 华为高管预告手机鸿蒙OS下月上线,华为手机部:我们没说过
- “常程跳槽小米”裁决出炉:常程继续履行竞业限制,还要赔500多万...
- 10月23日见?疑似魅族16T预热海报曝光:定位大屏娱乐旗舰