Base64编码
写在前面
今天在做一个Android app时遇到了一个问题:Android端采用ASE对称加密的数据在JavaWeb(jre1.8.0_7)后台解密时,居然解密失败了!经过测试后发现,对相同的数据,采用相同的密钥加密时,得到的密文是不同的,而加密的代码是完全一样的,只是在加密最后,对加密结果进行Base64编码时,API的调用略有不同。
在Android上,ASE加密是这样写的:
public static String aesEncrypt(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(encryptKey.getBytes()));
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
byte[] bs = cipher.doFinal(content.getBytes("utf-8"));
return Base64.encodeToString(bs, Base64.DEFAULT);
}
在普通JavaWeb上,ASE加密是这样写的:
public static String aesEncrypt(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(encryptKey.getBytes()));
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes("utf-8")));
}
最开始以为是二者Base64编码标准不同造成的,于是去了解了一下Base64编码的原理,但最终发现其实二者加密得到的byte数组就不同,估计是标准不同吧。
下面是对Base64编码的学习记录,以及用Java实现Base64编码,主要参考了程晓晖的博客。
什么是Base64编码
首先,我们知道,编码的目的一般是为了数据的压缩,再就是数据传输的需要。Base64编码的产生就是因为后者:有些网络传送渠道并不支持所有的字节的传输。Base64编码就是一种将二进制数据映射成一些可打印字符(或逆过来)的映射规则,具体的说是映射到[A-Za-z0-9+/]
上。比如将字符"中国"
映射成5Lit5Zu9
,当然也可将图片或其他文件编码成类似上述的字符。
Base64编码的原理
其次,我们需要知道的是,在计算机的世界里,一切都是由01011...这样的二进制数组成的,包括一个字符串,一张图片或一些其他类型的文件。比如对于一个字符串"中"
,在Java里,我们可以调用"中".getBytes()
来得到"中"
对应的字节数组:[-28, -72, -83]
,再将字节数组中的每个数转换为二进制,连接起来便是其二进制表示了:1110 0100_1011 1000_1010 1101
(为了便于阅读,用下滑线将每个字节分开。当然,采用不同的编码形式,得到的字节数组可能不同,此处采用的是utf-8编码)。对于文件,可以从其输入流读中取到。
因为字符集合[A-Za-z0-9+/]
长度是64,可以与所有6位长的二进制数一一对应 ,于是Base64编码的做法就是,将待编码的所有二进制位每6位分为一组,然后将每组二进制数映射到字符集合中的一个字符,最后将这些映射的字符依次排列起来便得到了编码结果。当然,待编码的二进制位可能不能被6整除,即最终可能会剩余2个或4个二进制位不能构成一组,这时我们可以在其后添加4或2个0来凑成一组。
比如对于上述的字符串"中"
,其二进制为:1110 0100_1011 1000_1010 1101
,我们每6位组成一组,得到:111001_001011_100010_101101
,每组转换为十进制就是:57_11_34_45
,在按顺序映射到字符集合[A-Za-z0-9+/]
上,便得到其Base64编码为:5Lit
。如果最后一组填充了0,则还需在编码后的字符串后加上=
符号。
解码的过程就是编码过程的逆过程,这里不再赘述。
Base64编码的实现
下面给出Base64编码的实现(末尾未加=
):
public static String base64Encode(String text) {
if (text == null) {
return null;
}
final String table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
byte[] textBytes = text.getBytes();
byte[] keyBytes = key.getBytes();
int remain = 0, remainBitCount = 0;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < textBytes.length; i++) {
int b = textBytes[i] & 0xFF;
// 获取b的高(6 - remainBitCount)位
int hight = b >>> (2 + remainBitCount) & 0xFF;
// 与上一轮的余留组合成一个字节
int curr = remain << (6 - remainBitCount) | hight;
// builder.append(table.charAt(curr));
builder.append(table.charAt(curr));
// 剩余b的低(2 + remainBitCount)位
remain = hight << (2 + remainBitCount) ^ b;
remainBitCount += 2;
// 若剩余的位刚好为6位,则进行编码
if (remainBitCount == 6) {
builder.append(table.charAt(remain));
remainBitCount = 0;
remain = 0;
}
}
if (remainBitCount != 0) {
// 多出的位到末尾补0凑够6位
builder.append(table.charAt(remain << (6 - remainBitCount)));
}
return builder.toString();
}
public static String base64Decode(String text) {
if (text == null) {
return text;
}
byte[] bs = new byte[text.length() * 6 / 8];
int pos = 0, remain = 0, remainBitCount = 0;
final String table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
for (int i = 0; i < text.length(); i++) {
int code = table.indexOf(text.charAt(i));
if (remainBitCount + 6 < 8) {
// 不足一个字节
remain = remain << 6 | code;
remainBitCount += 6;
} else {
// 足够一个字节,取code的高(8 - remainBitCount)位
int hight = code >>> (remainBitCount - 2) & 0xFF;
bs[pos] = (byte) (remain << (8 - remainBitCount) | hight);
pos++;
remainBitCount -= 2;
// 保留剩余的位
remain = hight << remainBitCount ^ code;
}
}
return new String(bs);
}
Base64编码的更多相关文章
- URL安全的Base64编码
Base64编码可用于在HTTP环境下传递较长的标识信息.在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式.此时,采用Base64编码不仅比较简短,同时也具有不可 ...
- Android数据加密之Base64编码算法
前言: 前面学习总结了平时开发中遇见的各种数据加密方式,最终都会对加密后的二进制数据进行Base64编码,起到一种二次加密的效果,其实呢Base64从严格意义上来说的话不是一种加密算法,而是一种编码算 ...
- 网络安全——Base64编码、MD5、SHA1-SHA512、HMAC(SHA1-SHA512)哈希
据说今天520是个好日子,为什么我想起的是502.500.404这些?还好服务器没事! 一.Base64编码 Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之 ...
- Base64编码【转】
转http://www.cnblogs.com/luguo3000/p/3940197.html 开发者对Base64编码肯定很熟悉,是否对它有很清晰的认识就不一定了.实际上Base64已经简单到不能 ...
- 【前端攻略】:玩转图片Base64编码
引言 图片处理在前端工作中可谓占据了很重要的一壁江山.而图片的 base64 编码可能相对一些人而言比较陌生,本文不是从纯技术的角度去讨论图片的 base64 编码.标题略大,不过只是希望通过一些浅显 ...
- 为什么要用base64编码
1.需求 了解为什么要使用base64对数据编码 2.理由 因为传输二进制数据的时候,网络中间的有些路由会把ascii码中的不可见字符删了,导致数据不一致.一般也会对url进行base64编码 Whe ...
- 图片Base64编码
我们经常在做Jquery插件的时候需要插入一些自定义的控件,比如说按钮,而我们自己又觉着button标签很丑,而且不同浏览器显示的效果还不一样,这个时候我们需要用到图片,当然,我们可以通过img标签添 ...
- 浅析用Base64编码的图片优化网页加载速度
想必大家都知道网页加载的过程,从开始请求,到加载页面,开始解析和显示网页,遇到图片就再次向服务器发送请求,加载图片.如果图片很多的话,就会产生大量的http请求,从而影响页面的加载速度.所以现在有一种 ...
- Base64编码原理分析
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,在了解Base64编码之前,先了解几个基本概念:位.字节. 位:"位(bit)"是计算机中最小的数据单位.每一位 ...
随机推荐
- 页面中多个script块之间的关系
一:函数声明与函数定义表达式在函数调用间的区别 <script type="text/javascript"> doA(); var doA = function(a ...
- angular2系列教程(六)两种pipe:函数式编程与面向对象编程
今天,我们要讲的是angualr2的pipe这个知识点. 例子
- Linux学习之探索文件系统
Linux,一起学习进步- ls With it, we can see directory contents and determine a variety of important file ...
- potrace源码分析一
1 简介 potrace是由Dalhousie University的Peter Selinger开发一款位图轮廓矢量化软件,该软件源码是可以公开下载的,详细见项目主页:http://potrace. ...
- WebApi返回Json格式字符串
WebApi返回json格式字符串, 在网上能找到好几种方法, 其中有三种普遍的方法, 但是感觉都不怎么好. 先贴一下, 网上给的常用方法吧. 方法一:(改配置法) 找到Global.asax文件,在 ...
- ASP.NET MVC一次删除多笔记录
批量删除数据记录,如下面的截屏: 先选中想删除的记录,然后点一下删除铵钮,系统将把选中的记录一次性删除.在此,Insus.NET不想每删除一笔记录连接一次数据库. 因此需要把选择的记录一次上传至服务器 ...
- Flexible 弹性盒子模型之CSS flex-basis 属性
实例 设置第二个弹性盒元素的初始长度为 80 像素: div:nth-of-type(2){flex-basis:80px;} 效果预览 浏览器支持 表格中的数字表示支持该属性的第一个浏览器的版本 ...
- Javascript高性能编程-提高Dom访问速度
在浏览器中对于Dom的操作和普通的脚本的操作处于两个不同的dll中,两个dll的交互是比较耗时的,优化对Dom的操作可以提高脚本的执行速度.下面是对如何优化的一些总结: 将需要多次操作的节点存储在一个 ...
- AEAI DP V3.7.0 发布,开源综合应用开发平台
1 升级说明 AEAI DP 3.7版本是AEAI DP一个里程碑版本,基于JDK1.7开发,在本版本中新增支持Rest服务开发机制(默认支持WebService服务开发机制),且支持WS服务.RS ...
- 手把手教你做个人 app
我们都知道,开发一个app很大程度依赖服务端:服务端提供接口数据,然后我们展示:另外,开发一个app,还需要美工协助切图.没了接口,没了美工,app似乎只能做成单机版或工具类app,真的是这样的吗?先 ...