简单理解,编码就是把信息按照一定的规则进行组织,变换消息形式的过程,所谓解码就是把收到的信息按照一定的规则进行解析,并且这个规则往往是固定的,必须是编码者和解码者事先都知道或约定好的。常见的编码手段有Base64和压缩算法。
Base64最早起源于HTTP协议下的数据传输,由于HTTP协议是文本协议,所以在HTTP协议下传输二进制数据需要将二进制数据转换为字符数据。然而直接转换是不行的。因为网络传输只能传输可打印字符(在ASCII码中规定,0~31、127这33个字符属于控制字符,32~126这95个字符属于可打印字符,也就是说网络传输只能传输这95个字符)。使用Base64就是将不在这些字符范围内的其他字符转换为可打印字符。
具体的64位的映射关系如下图:
Base64算法的固定规则:因为索引最大63,所以Base64的索引最多只占6个Bit,但是ASCII码字符需要8个Bit来表示,所以,Base64按照三个一组,会把连续的3个字节变成4个字节,然后每个字节补齐高位的2个0,这样38就等于46了,也就是说,转换后的字符串理论上将要比原来的长1/3。同时Base64规定,当需要转换的字符不是3的倍数时,一律采用补0的方式凑足3的倍数。
百度百科的例子介绍很形象
转换前 10101101,10111010,01110110
转换后 00101011, 00011011 ,00101001 ,00110110
十进制 43 27 41 54
对应码表中的值 r b p 2
所以上面的24位编码,编码后的Base64值为 rbp2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,有关MIME的RFC还有很多,如果需要详细情况请自行查找。)
第一个字节,根据源字节的第一个字节处理。
规则:源第一字节右移两位,去掉低2位,高2位补零。
既:00 + 高6位
第二个字节,根据源字节的第一个字节和第二个字节联合处理。
规则如下,第一个字节高6位去掉然后左移四位,第二个字节右移四位
即:源第一字节低2位 + 源第2字节高4位
第三个字节,根据源字节的第二个字节和第三个字节联合处理,
规则第二个字节去掉高4位并左移两位(得高6位),第三个字节右移6位并去掉高6位(得低2位),相加即可
第四个字节,规则,源第三字节去掉高2位即可
//用更接近于编程的思维来说,编码的过程是这样的:
//第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一//个目标字符。
//然后将第一个字符与0x03(00000011)进行与(&)操作并左移4位,接着第二个字符右移4位与前者相或(|),即获得第二个目标字符。
//再将第二个字符与0x0f(00001111)进行与(&)操作并左移2位,接着第三个字符右移6位与前者相或(|),获得第三个目标字符。
//最后将第三个字符与0x3f(00111111)进行与(&)操作即获得第四个目标字符。
//在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。
java使用Base64进行编码和解码:
//编码
java.util.Base64.getEncoder().encodeToString("aaaa".getBytes("UTF-8"));
//解码
byte[] decode = Base64.getDecoder().decode(encode);
//转换为String
String aaaa = new String(decode, "UTF-8")
压缩算法是指在不丢失信息的前提下,缩减数据量以减少存储空间,提高传输、存储和处理效率的一种技术方法。或者是按照一定的算法对数据进行重新组织,减少数据的冗余和存储的空间,在电子与通信领域也常被称为信号编码。
消息压缩的基本原理是霍夫曼树,实现上有很多种,比如常见的gzip、LZW压缩、lz4、游程编码(RLC)、snappy等等,使用过程中根据业务场景,从性能、压缩率等方向去选择合适的。
霍夫曼树和常见的压缩算法详细介绍
压缩算法比较
Java序列化就是指把Java对象转换为字节序列的过程,反之,反序列化就是指把字节序列恢复为Java对象的过程。其作用就是在跨进程跨服务的数据传输过程中,进行对象状态的保存和重建。
下面是摘自 jdk api 文档里面关于接口 Serializable 的描述
关于 serialVersionUID 的描述
加密算法分对称加密和非对称加密,其中对称加密算法的加密与解密 密钥相同,非对称加密算法的加密密钥与解密 密钥不同,此外,还有一类 不需要密钥 的 散列算法。
常见的 对称加密 算法主要有 DES、3DES、AES 等,常见的 非对称算法 主要有 RSA、DSA 等,散列算法 主要有 SHA-1、MD5 等。
MD5 用的是 哈希函数,它的典型应用是对一段信息产生 信息摘要,以 防止被篡改。严格来说,MD5 不是一种 加密算法 而是 摘要算法。无论是多长的输入,MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)。
java.security.MessageDigest.getInstance("MD5").digest(content);
SHA1 和 MD5类似,也是一种较流行的消息摘要算法,它比 MD5 的安全性更强。对于长度小于 2 ^ 64 位的消息,SHA1 会产生一个 160 位的 消息摘要。基于 MD5、SHA1 的信息摘要特性以及 不可逆 (一般而言),可以被应用在检查 文件完整性 以及 数字签名 等场景。
java.security.MessageDigest.getInstance("SHA1").digest(content);
HMAC 发送方 和 接收方 都基于 key ,利用哈希算法 (MD5、SHA1 等)计算,来传输和保存消息,这样,哪怕黑客窃取了消息,但是没有key,是 无法计算 出正确的 散列值的,这样就可以 防止数据被篡改。
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class EncryptUtil {
public static String getBase64String(byte[] s) {
return Base64.getEncoder().encodeToString(s);
}
public static byte[] hamcsha1(String data, String key) {
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
return mac.doFinal(data.getBytes());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
针对网络传输的url和参数保护可以使用编码算法,但是针对加密场景,比如数据保密存储等,千万别使用普通的编码算法,一定要使用加密算法,同理,传输过程中有安全性要求的,除了加密算法,还需要通过密钥来进一步保证数据安全性!