文章目录
前言
体能状态先于精神状态,习惯先于决心,聚焦先于喜好
几个容易混淆的概念
编码标准 和 字符编码:编码标准是一种标准,字符编码是对标准的实现,有一些字符标准和字符编码名字一样,如GB2312,有一些则不同,如 Unicode标准的实现有UTF-8、UTF-16等
Unicode 是一种标准规范,其实现有 使用8位、16位和32位编码单元,分别为UTF-8、UTF-16、UTF-32
摘要算法比如MD5,是不可逆的,常用语检测数据完整性
二进制转化法 Base64是一种基于64个可打印字符来表示二进制数据的方法,可以讲字符串和二进制自由转化,强调这不是加密方法
url encode,用于对url中特殊字符和中文进行转义,便于浏览器正常处理
对称加密算法,比如 DES、AES,特点是对一段数据加密,加密和解密的key一样
非对称加密算法,比如RSA,特点是需要两个key,一般叫做 public key 和 private key,使用其中一个key加密,另一个key可以解密。
从0和1到编码标准
在计算机的世界中,0和1是最基本的数据单位,在数据的传输过程中,于是人们用0和1的组合表示各种其他的情况,比如我自己规定 01 表示“!”,02表示“你”,03表示“换行”,但是这个标准只有我自己知道肯定是不行的,所以就出现了标准化的工作,即编码标准
再比如,西方国家和亚洲国家字符差别很大,所以就存在很多种不同的编码标准了
常见的编码标准 ASCII、Unicode、GBK等
常见的编码标准有 ASCII、Unicode、GB2312-80、GBK、GB18030-2000等
需要注意的是,编码标准不同于字符编码,字符编码是对字符标准的实现
再一个,编码标准的实现可以和编码标准有不同的名字,比如Unicode的实现有UTF-8、UTF-16等
常见的字符编码 ASCII、UTF8、GBK、gb2312 等
字符编码是对字符标准的实现
常见的编码标准的实现有
字符标标准 | 字符实现 |
---|---|
GB18030 | GB18030 |
Big5 | Big5 |
GB2312 | GB2312 |
GBK | GBK |
ASCII | US-ASCII |
Unicode | UTF-16、UTF-16BE、UTF-16LE、UTF-32、UTF-32BE、UTF-32LE、UTF-8 |
对于 Java 开发人员,可以在 Jdk 提供的字符集合
public static void main(String [] args){
SortedMap<String,Charset> map= Charset.availableCharsets();
Collection<Charset> c=map.values();
Iterator iterator=c.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
最早出现的字符编码 ACSII
ASCII 是最早出现的字符编码
其他字符编码对ACSII都是兼容的,即在0-127 数值上的二进制编码含义一致
ASCII 使用7位来约定编码,但是一般一个字节是8位,所以最高位设置为0
ASCII 共包含128个编码,分别对应0-32、33-126、127的十进制值,其中0-32和127为语义,33-126 对应可打印符号
查看 ASCII 字符编码规则
下面图片来自 http://tool.oschina.net/commons?type=4
在 Java 中利用 char 和 byte 的转化感受 ASCII
在 Java 中 char 和 byte 之间可以通过强制转化进行转化,这样你可以在 char中看到字符,在byte看到其对应的十进制数字
@Test
public void test3() {
for(int i=0;i<128;i++) {
System.out.println(i+":"+(char)i);
}
}
Base64 简介
Base64就是一种基于64个可打印字符来表示二进制数据的方法。
可查看RFC2045~RFC2049
其实从某种程度来说,Base64 更像是和UTF8 、GBK 一样的一种编码格式,不同之处在于,Base64 仅仅是为了将字节数组转化为字符串——看起来乱糟糟的,所以你又无法将其认定为一种字符编码格式,比如UTF8或GBK,你可以认识他们是一种文字或者符号.
Base64 提供了字节数据和字符串之间的转化能力
Base64 提供了这样的能力:
1、将字节数组转化为 Base64 编码的字符串-看起来像乱码
2、将Base64 字符串转化为字节数组
至于字符组数,其可能来自于UTF8编码格式的字符串,也可能来自GBK编码的字符串,但是不管怎样,在使用Base64编码的字符串时你是不需要关心编码格式问题的
Base64 的标准编码规则-基本单位为6个byte位
本质来说,Base64 是一种将字节转化为字符的规则和实现.
Base64 使用64个基本可打印符号
10个数字:0-9
26个小写字母:a-z
26个大写字母:A-Z
2个符号:+,/
每一个Base64字符正好对应一个十进制数字,从0-63,二进制表达就是 000000-111111
Base64 的编码规则
原8位字节按照3个字节为一组,划分为6位一个单位,6位分组后前面补2个零恢复为8位一个字节,这样3个字节就变为了4个字节
如果有多余的位数不够6位按照补0处理
如果原字节不够3个字节,不够的字节用=表示一个字节,在解码时不做转化
简答说就是以24位为基本单位,不够24位的用0补足24位
- 比如:
字节数组的二进制表示为: 11111111 11111111 11111111 11
以6位为一个基本单位进行划分
分为(4*6=24位) 111111 111111 111111 111111 和(2位) 11
对 111111 111111 111111 111111 的处理
在6位前补两个0补够8位:00111111 00111111 00111111 00111111
对11的处理
不足6位的以0补足6位,不够三个字节以0填充,转化为字符用=表示一个字节
前面加俩0补足,
00110000 ==
将所有的字节转化为 Base64 编码的字符
将二进制数变为Base64对应的编码格式
Base 64 不是加密算法
Base64 最常见的误解就是任务其是一种加密方法,这是大大的错误.
从其使用来看一般是 encode-编码和decode-解码
其主要是为了解决不同字符编码之间的通用表达的问题
Base64的使用场景
由于Base64 看起来是乱码一般,所以可以作为数据处理的一部分
Base64 可以用于不同系统之间的数据交换——其没有字符编码属性,不会出现所谓的乱码问题——当然,在你将Base64还原为原字符编码格式对应的字符串时依旧要注意.
Base64 在 Java 中的使用
建议使用 jdk1.8 提供的方法,或者 Apache Commons Codec 提供的方法.
请移步:Base64 在 Java 中的几个实现方式
url encode和decode
url 中仅可以传递 ASCII 的字符
除此以外的字符如果需要被传递就需要做一些处理
而且对于url中的一些保留字符,比如 &,也需要做一些处理才可以被作为参数传递
对于空格也需要转义
这就 encode 方法和decode 方法,例子请看下面
Java 中的 url encode 和 decode举例
@Test
public void test2() throws UnsupportedEncodingException {
String url="http://localhost:8080/demo/name=你好&age=12&sign=你好 ,. []_=-+";
String encoder=URLEncoder.encode(url,"utf-8");
String decoder=URLDecoder.decode(encoder, "utf-8");
System.out.println("url:"+url);
System.out.println("encoder:"+encoder);
System.out.println("decoder:"+decoder);
}
url:http://localhost:8080/demo/name=你好&age=12&sign=你好 ,. []_=-+
encoder:http%3A%2F%2Flocalhost%3A8080%2Fdemo%2Fname%3D%E4%BD%A0%E5%A5%BD%26age%3D12%26sign%3D%E4%BD%A0%E5%A5%BD+%2C.+%5B%5D_%3D-%2B
decoder:http://localhost:8080/demo/name=你好&age=12&sign=你好 ,. []_=-+
MD5 摘要算法(Message Digest)
MD 系列的算法有三种 MD2、MD4、MD5,前两种都不应被破解了,不安全
MD5的简述
对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
可以认为,任何一个数据经过MD5计算后可以得到唯一的,且不可逆的 128 的散列,转化为10进制就是16个字节,用16进制展示就是32个字节
MD5 展示32个10进制字符或者32位的16进制字符
128位散列正好是16个字节,通常来说,我们一般会使用32位记录MD5结果
Hex.encodeHexString(byte[] byte);
MD5的用途
由于MD5 对源数据对敏感、计算结果的相对唯一、不可逆等特性,其可以用作数字签名(验证数据是否被篡改-核身)、数据保密(存数据不要存明文)、摘要算法(确保数据没有被篡改-数据完整性)
MD5 在 Java 中的使用
Jdk 自带了MD2 和 MD5
apache 提供 commons-codec
/**
* jdk 自带的摘要算法工具类
* java.security.MessageDigest
//查看需要的
Provider[] pArray=Security.getProviders();
* @throws NoSuchAlgorithmException
*/
@Test
public void test1() throws NoSuchAlgorithmException {
MessageDigest m=MessageDigest.getInstance("MD5");
//m=MessageDigest.getInstance("MD2");
//结果16个字节-16进制展示
System.out.println(Hex.encodeHexString(m.digest("A".getBytes())));
}
/**
* commons-codec 的摘要算法工具类-线程安全的
* org.apache.commons.codec.digest.DigestUtils
*/
@Test
public void test2() {
//DigestUtils.md2Hex("A");
//结果16位-10进制
//System.out.println(DigestUtils.md5("A"));
byte[] bytes=DigestUtils.md5("A");
System.out.println("字节数组长度:"+bytes.length);
for(byte b:bytes) {
System.out.println("10进制打印:"+b);
}
//结果32位-16进制
System.out.println("16进制打印:"+DigestUtils.md5Hex("A"));
}
MD5 的16位和32位
使用 16进制 得到的 MD5 结果就是32位的
16位的结果其实只是对 32位 MD5 结果进行了截取 str.substring(8, 24);
为什么用 16进制?
看下用10进制和16进制打印的数据结果
字节数组长度:16
10进制打印:127
10进制打印:-59
10进制打印:98
10进制打印:112
10进制打印:-25
10进制打印:-89
10进制打印:15
10进制打印:-88
10进制打印:26
10进制打印:89
10进制打印:53
10进制打印:-73
10进制打印:46
10进制打印:-84
10进制打印:-66
10进制打印:41
16进制打印:7fc56270e7a70fa81a5935b72eacbe29
32位MD5 16位打印:e7a70fa81a5935b7
MD5 安全吗?
MD5 作为散列算法,其本身是不可逆的,但是单纯的使用MD5 存在一定的风险,因为目前有人将MD5计算前结果进行了统计,提供了暴力查询字典,所以对于密码存储类的使用MD5就显的不那么安全了
但是在数据完整性校验方面,MD5 的运算效率还是比较高的.相比于 SHA系列的摘要算法.
SHA安全散列(Secure Hash Algorithm)
请移步 安全散列算法
MAC 消息认证码(Message Authentication Code)
对称加密
AES,RC4,3DES
非对称加密(公钥加密)
非对称签名算法(SHA1withRSA)
比如 SHA1withRSA、SHA256withRSA、SHA1withDSA
基于 SHA和非对称算法
请移步 非对称签名算法
一个包含多个加密算法的jar包
目前还没用到
<!-- https://www.bouncycastle.org/latest_releases.html
https://blog.youkuaiyun.com/andychuen/article/details/86748255 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
</dependency>
参考资料
[1]、https://www.cnblogs.com/sunxuchu/p/5483956.html
[2]、https://www.jianshu.com/p/a8070920810d
[3]、https://www.cnblogs.com/sunxuchu/p/5483956.html
[4]、https://baike.baidu.com/item/base64/8545775?fr=aladdin
[5]、https://blog.youkuaiyun.com/qq_20545367/article/details/79538530
[6]、https://blog.youkuaiyun.com/qq_15437667/article/details/80349169
[7]、http://tool.oschina.net/commons?type=4
[8]、https://blog.youkuaiyun.com/k3108001263/article/details/87158765
[9]、https://blog.youkuaiyun.com/weixin_38638777/article/details/79608356