1、编码格式、编码标准Unicode、摘要MD、散列SHA、MAC、Base64、url encode、对称加密、非对称加密(公钥加密)

前言

体能状态先于精神状态,习惯先于决心,聚焦先于喜好

几个容易混淆的概念

编码标准 和 字符编码:编码标准是一种标准,字符编码是对标准的实现,有一些字符标准和字符编码名字一样,如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 等

字符编码是对字符标准的实现
常见的编码标准的实现有

字符标标准字符实现
GB18030GB18030
Big5Big5
GB2312GB2312
GBKGBK
ASCIIUS-ASCII
UnicodeUTF-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

非对称加密(公钥加密)

非对称加密 RSA、DES等

非对称签名算法(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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值