1. 编码解码(Encoding&Decoding)
1. Base64
将二进制数据转换成由64个字符组成的字符串的编码算法;需要明确的是,Base64并不是一个加密算法,因为它的码表是明文的,而且不高效,转换后增大数据体积,并且还要前后做两次转码操作(它的作用主要是价将字节型数据转换为字符型数据,比如图片传输,当然这是不规范的用法);
如下图,base64将每6个字符生成一个0~63的数,再根据编码得到相应字符,可以参考wiki百科,查看相应内容;
2. 加密解密
现代密码学不仅可以对文字进行加密,也可以对各种二进制文件进行加密
1. 对称加密
使用秘钥和加密算法对数据进行转换,得到的无意义数据即为密文;使用秘钥和解密算法对密文进行逆向转换,得到原数据;同一个秘钥,不同的算法;
- 经典算法:DES(56位,秘钥过短,基本弃用),AES(128位)
- 缺点:秘钥传输会有泄密的风险
2. 非对称加密
使用公钥对数据进行加密得到密文;使用私钥对数据进行解密得到原数据;一样的算法,不同的秘钥
客户端生成一对秘钥,将加密秘钥传输到另一端进行数据加密,加密数据在传输回来,这样中间者只能拿到一个加密秘钥与一段密文,无法进行解密;(公钥可能是可以被私钥计算出来的)比如:比特币的椭圆曲线算法;
- 经典算法:RSA(加密和签名),DSA(只用来签名,速度快,例如椭圆曲线算法);
- 缺点:相比于对称加密,会非常耗性能
用公钥来加密的数据可以用私钥来进行解密,那么使用私钥进行加密的数据可以用公钥解密;(理解数字签名的基础)
举个例子:就类似与原数据是1,使用公钥4加密后变成了5,再使用私钥6解密变成了11,丢弃进位是 1;
原数据还为1,使用私钥加密后变成7,再使用公钥4解密后变成了11,丢弃进位也是1;这个例子仅用于理解公钥与私钥加密,公钥与私钥加密并不是这样的;
2.1 数字签名
有一个问题,一旦当公钥泄露后,中间人是可以使用公钥伪装客户端发消息的,这个时候就需要使用到数据签名了;
数据签名简单点就是使用私钥对数据进行加密,表示这个数据是我发出的,因为私钥是唯一的,具有不可伪造性;使用公钥与原数据进行验证,得出签名结果;
因此,如果想确保数据安全,数据加密与数据签名是缺一不可的;如下图:客户端发送加密数据时,使用公钥对数据进行加密,再使用私钥对数据进行签名,服务端收到数据后,使用私钥对数据进行解密,再使用对方公钥进行数据验证;
其实,还有个漏洞,在这个过程中,中间人是可以使用公钥验证签名数据得到原数据的,因此还是不安全的,解决方法就是对数据进行Hash,Hash留到Hash部分补充;
3. 压缩与解压缩
压缩:把数据换一种方式来存储,以减小存储空间;
解压缩:把压缩后的数据还原成原来的格式,便于使用;
常见压缩算法:DEFLATE、JPEG、MP3
压缩属于编码吗? 编码其实并没有很准确的概念,压缩解压缩其实也是编码解码的一种形式,但有损压缩并不属于编码,因为有损压缩是不可逆的;
4. 序列化
把数据对象(一般是内存中的,例如JVM中的对象)转换后字节序列的过程;就比如讲一个JavaBean转换成Json的形式,或将一个图片换成二进制的形式都属于序列化,只要将一个数据对象转换成一个连续的‘串’的形式都属于序列化;
对于序列化,我们最熟悉的是Java中Serializable,但并不是只有实现Serializable才可以序列化,而是实现Serializable之后虚拟机可以自动帮我们序列化;
反序列化
把字节序列重新转换成内存中的对象
5. Hash
把任意数据转换成指定大小范围(通常很小)的数据;个人不喜欢上面这个定义,因为很抽象;举个例子,每个学生对应着一个学号,通过学号可以便于对学生的管理,我们可以把学号理解为这个学生的hash值;其实就是对一个较大事务的较小抽象;Hash具有防破解,防碰撞(其实就是防重复)的特点
- 经典算法:MD5,SHA1,SHA256
- 实际用途:数据完整性验证,快速查找(hashCode和hashMap),隐私保护
隐私保护是指在服务器使用hash值保存密码,一旦服务器数据库被脱库,只能拿到数据的密码的hash值,hash值是不可逆的,因此此时密码还是安全的;但是如果密码过于简单,这时候可以用彩虹表查出来,彩虹表是对常用的数据进行的hash值存储,一旦hash值匹配,相当于密码被暴力破解了;
针对彩虹表,网站可以在用户设置密码之后,再添加一组复杂数据,称为‘yan’,再进行Hash计算,这个时候彩虹表的常用密码就不容易匹配到加‘yan’的hash表了;
为什么重写equals()方法时必须重写hashcode()方法
Java在判断两个对象是否相等时,先判断的并不是equals,而是hashcode,因为hashcode速度很快;两个对象的hashcode不等,那么两个对象一定不等,但hashcode相等时,此时两个对象并不一定相等(不理解的可以去查看hash值的生成方式),此时再去比较equals;
换句话说,按照Java的逻辑,如果equals相等,那么两个对象才是真的相等 ;但是equals比hashcode慢,因此用hashcode快速过滤掉不相等的数据;
重写equals方法,会修改两个对象相等的规则,此时如果不重写hashcode,会被hashcode提前过滤掉,影响数据准确性;
- MD5不属于编码,也不属于加密;因为MD5是不可逆的,加密是可以解密的
在加密与签名部分留了一个漏洞,在这里进行补充;原数据计算出hash值(也叫摘要或者指纹),使用私钥对hash值进行签名,这一部分不会很大,附在原数据的后面,原数据使用公钥加密,到另一端后,使用私钥解密密文得到原文,再使用另一端公钥验证hash值,通过原文计算hash值,再对hash值进行比对,确认无误;
这样中间人只能拿到公钥,一段加密数据以及原数据的hash值,既无法伪造也无法解密;
