了解编码、加密、Hash、序列化和字符集的概念。
编码
编码是信息 (文本或者非文本的二进制文件) 从「一种形式」或者格式转换到「另一种形式」的过程。
编码只是表现形式的转换,并不是一种加密方式。
常见的编码有:
Base64编码
URL编码(也叫%编码)
压缩/解压缩编码
Base64编码
用途
Base64编码
可以把非文本的二进制文件 (如图片、视频) 转换成字符串。可以用普通表单(只支持传文本)上传图片。
Base64
传图片是很老的方法,可以用multipart
或者image/jpeg
的方式传图片;Base64
不是一种加密方式,并不安全;Base64
会增大文件体积,并不高效。
URL编码
用途
URLEncode
和URLDecode
是问了消除歧义,避免解析错误,把保留字符转换成%编码
。
比如
https://www.baidu.com/s?wd=编码
会被转换成https://www.baidu.com/s?wd=%E7%BC%96%E7%A0%81
压缩/解压缩编码
用途
顾名思义,压缩
是减少文件体积,方便传输;解压缩
是把压缩后的文件还原成原文件。
常见的压缩文件格式
- zip:文件压缩,压缩算法是
DEFLATE
- JPEG/PNG:图片压缩
- MP3:音频压缩
- MP4:视频压缩
压缩分成「有损压缩」和「无损压缩」,「有损压缩」是不可逆的。
加密
对称加密
对称加密:密钥相同,加密算法和解密算法不同。
常见对称加密算法
- DES:密钥太短(64位),已经弃用
- AES:密钥有128位、192位和256位
对称加密的缺点:密钥传输有风险。
非对称加密
非对称加密:密钥不同,加密算法和解密算法相同。
常见非对称加密算法
- RSA:可以用来加密和签名
- DSA:只用来签名(速度快)
非对称加密会生成一对密钥:公钥和私钥。其中私钥自己持有,绝对保密;公钥是可以公开出去的。这样就避免了密钥传输风险。
私钥加密的密文,可以用公钥解密;公钥加密的密文,可以用私钥解密;但是公钥和私钥不能替换,因为公钥可以通过私钥计算得到 (椭圆曲线算法) 。
数字签名和验证
非对称加密会遇到 数据伪造风险 (使用公钥伪造数据),所以产生了 「数据签名-验证」的用法。
- 签名:A用私钥对原数据的「Hash」进行加密,得到「密文」,同时把「Hash」和「密文」发给B;
- 验证:B用公钥对「密文」进行解密,得到的结果和「Hash」对比,如果一致说明确实是用A的私钥加密的,证明发送方确实是A。
加密的使用流程
没有一种加密方式是绝对安全的,对称加密和非对称加密也没有优劣之分。需要根据具体场景选择适合的加密方式。
前提说明:
- A、B是通信双方,默认A和B所持有的数据是不会泄漏的(这里只分析传输过程中的安全问题);
- C是坏人,假设通信过程中的所有数据都会被C所拦截。
对称加密的使用流程
情景1:
1. A和B都有密钥,不需要传输密钥; 2. C只能拦截到密文,无法解密,是安全的。
情景2:
1. A没有密钥,B有密钥,B需要把密钥传给A; 2. C同时拦截到密文和密钥,是不安全的。
非对称加密的使用流程
情景1:只有一对公钥和私钥
**1. B持有自己的私钥,公钥公开给A和C;
- A使用B公钥加密后的密文发送给B,B再用B私钥解密;C无法用B公钥解密,安全;
- B使用B私钥加密后的密文发送给A,A再用B公钥解密;C也可以用B公钥解密,不安全;**
情景2:有两对公钥和私钥(A和B)
1. AB分别持有自己的私钥,和对方的公钥;C也持有两者的公钥; 2. A使用B公钥加密后的密文发送给B,B再用B私钥解密;C无法用B公钥解密,安全; 3. B使用A公钥加密后的密文发送给A,A再用A私钥解密;C无法用A公钥解密,安全;
如果改成用私钥加密,公钥解密会怎样呢?
用私钥加密,就要用公钥解密,C拥有两个公钥,所以是不安全的。
数字签名和验证
上面采用两对公钥和私钥,并且用公钥加密,私钥解密的方案,还有一个风险,就是C可以用公钥伪造数据发送给A和B。
情景3:使用数字签名和验证
1. 首先,对原数据进行Hash计算,得到原数据的Hash值(体积小,方便传输); . 使用自己的私钥对Hash进行加密(签名),然后把Hash和密文发送给对方; 3. 接受方使用对方的公钥解密,然后和原数据Hash对比,如果一致,说明发送方是拥有私钥的(验证); 4. C没有A和B的私钥,所以无法伪造。
情景4:完整的加密和签名流程
所以非对称加密传输数据,需要:
1. 两对公钥和私钥;
2. 用公钥加密,私钥解密;
3. 用私钥签名,公钥验证。
Hash
用途
Hash
是把任意数据转成指定大小(一般很小)的数据。可以用来作摘要、数字指纹。
摘要、数字指纹就好像人的DNA一样,可以用来唯一表示该数据,但是不能逆向还原出原数据。
应用场景
- 数据完整性验证
对数据
Data
进行Hash
,得到DataHash
(很小),接收方接受到Data
后再进行一次Hash
,得到的结果跟DataHash
对比,一致的话可以认为接收到的数据是完整的。
- 快速查找
HashMap
是一个可以用来快速查找的数据结构,通过对比对象的Hash值实现。
Java的Object对象有默认实现的
equals()
和hashCode()
方法,通过hashCode()
可以快速判断两个对象是否相等,如果hashCode
相等再判断equals()
。(所以要重写equals()
方法也要同时重写hashCode()
方法)
常见的Hash算法
- MD5
- SHA1
- SHA256
序列化
- 序列化:把内存中的对象转换成字节序列(一般是JSON),用于存储或者传输。
- 反序列化:把字节序列(一般是JSON)转换成内存中的对象。
Java
中实现Serializable
接口,就可以对对象进行序列化。
字符集
字符集 是一个由整数向现实文字符号的映射(Map)。简单来说就是用整数表示文字符号。
- ASCII 字符集
- Unicode 字符集
- UTF-8:Unicode的编码分支
- UTF-16:Unicode的编码分支
- GBK 字符集
一个字符集的不同编码分支,指的是同一个字符集的不同表示方式; GBK现在基本退出历史舞台。
公众号:JairusTse的日常
(转载本站文章请注明作者和出处 JairusTse的技术博客)