1、编码与解码

1.1、介绍

java安全编码技术 java安全编码标准pdf_哈希算法

java安全编码技术 java安全编码标准pdf_对称加密_02

java安全编码技术 java安全编码标准pdf_数字签名_03


java安全编码技术 java安全编码标准pdf_对称加密_04

编码按适用范围可以简单分为:

  • 美国编码(ASCII)
    ASCII为基础编码,来源于美国;
    其它编码都兼容ASCII编码;
  • 欧盟编码(ISO8859-1、WINDOWS-1252)
    先是ISO-8858-1,后升级为WINDOWS-1252。两者互不兼容。
  • 中华编码(GB2312、GBK、GB18030)
    先是GB2312,接着GBK,最后是GB18030。字符数量依次扩容。
  • 中国繁体编码(BIG5)
    BIG5,主要用于港澳台。
  • 世界编码(UNICODE)
    世界编码:UNICODE,可以包括全世界所有编码,理论上可以存100多万字符。世界通用。不完全兼容基它编码。如BIG5编码的文件,用UNICODE打开后仍是乱码,但UNICODE可以显示繁体,要以UNICODE保存并打开。

java安全编码技术 java安全编码标准pdf_java安全编码技术_05

java安全编码技术 java安全编码标准pdf_非对称加密_06

1.2、URL编码

  • URL编码是编码算法,不是加密算法
  • URL编码的目的是把任意文本数据编码为%前缀表示的文本,便于浏览器和服务器处理
  • URL编码是浏览器发送数据给服务器时使用的编码,它通常附加在URL的参数部分

例如:

https://www.baidu.com/s?wd=%E4%B8%AD%E6%96%87

之所以需要URL编码,是因为出于兼容性考虑,很多服务器只识别ASCII字符。但如果URL中包含中文、日文这些非ASCII字符怎么办?不要紧,URL编码有一套规则:

  • 如果字符是A`Z`,`a`z0~9以及-_.*,则保持不变;
  • 如果是其他字符,先转换为UTF-8编码,然后对每个字节以%XX表示。

例如:字符的UTF-8编码是0xe4b8ad,因此,它的URL编码是%E4%B8%AD。URL编码总是大写。

  • Java标准库提供了一个==URLEncoder.encode()==类来对任意字符串进行URL编码:
//编码
String encoded = URLEncoder.encode("中文!", StandardCharsets.UTF_8);

URLEncoder把空格字符编码成+,而现在的URL编码标准要求空格被编码为%20,不过,服务器都可以处理这两种情况

  • 解码URLDecoder.decode
//解码
String decoded = URLDecoder.decode("%E4%B8%AD%E6%96%87%21", StandardCharsets.UTF_8);

1.3、Base64编码

  • Base64编码也是编码算法,不是加密算法
  • Base64编码的目的是把任意二进制数据编码为文本,但编码后数据量会增加1/3
  • 编码 Base64.getEncoder().encodeToString()
byte[] input = new byte[] { (byte) 0xe4, (byte) 0xb8, (byte) 0xad };
String b64encoded = Base64.getEncoder().encodeToString(input);
System.out.println(b64encoded);
  • 解码 Base64.getDecoder().decode()
byte[] output = Base64.getDecoder().decode("5Lit");
System.out.println(Arrays.toString(output)); // [-28, -72, -83]

2、哈希算法

2.1、介绍

  • 哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
  • 哈希算法最重要的特点就是:
  • 相同的输入一定得到相同的输出
  • 不同的输入大概率得到不同的输出
  • 哈希算法的目的就是为了验证原始数据是否被篡改
  • Java字符串的hashCode()就是一个哈希算法,它的输入是任意字符串,输出是固定的4字节int整数

2.2、哈希碰撞

  • 哈希碰撞是指,两个不同的输入得到了相同的输出
"AaAaAa".hashCode(); // 0x7460e8c0
"BBAaBB".hashCode(); // 0x7460e8c0

碰撞是一定会出现的,因为输出的字节长度是固定的,StringhashCode()输出是4字节整数,最多只有4294967296种输出,但输入的数据长度是不固定的,有无数种输入。所以,哈希算法是把一个无限的输入集合映射到一个有限的输出集合,必然会产生碰撞

  • 碰撞不可怕,我们担心的不是碰撞,而是碰撞的概率,因为碰撞概率的高低关系到哈希算法的安全性。一个安全的哈希算法必须满足:
  • 碰撞概率低;
  • 不能猜测输出。

不能猜测输出是指,输入的任意一个bit的变化会造成输出完全不同,这样就很难从输出反推输入(只能依靠暴力穷举)

2.4、常用的哈希算法

算法

输出长度(位)

输出长度(字节)

MD5

128 bits

16 bytes

SHA-1

160 bits

20 bytes

RipeMD-160

160 bits

20 bytes

SHA-256

256 bits

32 bytes

SHA-512

512 bits

64 bytes

// 创建一个MessageDigest实例:
MessageDigest md = MessageDigest.getInstance("MD5");
// 反复调用update输入数据:
md.update("Hello".getBytes("UTF-8"));
md.update("World".getBytes("UTF-8"));
byte[] result = md.digest(); // 16 bytes: 68e109f0f40ca72a15e05cc22786f8e6
System.out.println(new BigInteger(1, result).toString(16));

2.4、哈希算法的用途

因为相同的输入永远会得到相同的输出,因此,如果输入被修改了,得到的输出就会不同

  • 判断下载到本地的软件是原始的、未经篡改的文件。只需要自己计算一下本地文件的哈希值,再与官网公开的哈希值对比,如果相同,说明文件下载正确,否则,说明文件已被篡改
  • 存储用户口令

2.5、防止彩虹表攻击

  • 对每个口令额外添加随机数,称之为加盐(salt)

加盐的目的在于使黑客的彩虹表失效,即使用户使用常用口令,也无法从MD5反推原始口令

3、BouncyCastle

是一个提供了很多哈希算法和加密算法的第三方库

用法

3.1、加入jar包

bcprov-jdk15on-xxx.jar

3.2、注册BouncyCastle

  • Java标准库的java.security包提供了一种标准机制,允许第三方提供商无缝接入
// 注册BouncyCastle:
Security.addProvider(new BouncyCastleProvider());

3.3、调用

// 按名称正常调用:
MessageDigest md = MessageDigest.getInstance("RipeMD160");
md.update("HelloWorld".getBytes("UTF-8"));
byte[] result = md.digest();
System.out.println(new BigInteger(1, result).toString(16));

4、Hmac算法

  • Hmac算法就是一种基于密钥的消息认证码算法,它的全称是Hash-based Message Authentication Code,是一种更安全的消息摘要算法。
  • Hmac算法总是和某种哈希算法配合起来用的

例如,我们使用MD5算法,对应的就是HmacMD5算法,它相当于“加盐”的MD5:

HmacMD5 ≈ md5(secure_random_key, input)

  • HmacMD5可以看作带有一个安全的key的MD5。使用HmacMD5而不是用MD5加salt,有如下好处:
  • HmacMD5使用的key长度是64字节,更安全;
  • Hmac是标准算法,同样适用于SHA-1等其他哈希算法;
  • Hmac输出和原有的哈希算法长度一致。
  • Hmac本质上就是把key混入摘要的算法。验证此哈希时,除了原始的输入数据,还要提供key。

5、对称加密算法

  • 对称加密算法使用同一个密钥进行加密和解密,常用算法有DES、AES和IDEA等;
  • 密钥长度由算法设计决定,AES的密钥长度是128/192/256位;
  • 使用对称加密算法需要指定算法名称、工作模式和填充模式。

java安全编码技术 java安全编码标准pdf_对称加密_07

6、口令加密算法

  • PBE算法通过用户口令和安全的随机salt计算出Key,然后再进行加密;
  • Key通过口令和安全的随机salt计算得出,大大提高了安全性;
  • PBE算法内部使用的仍然是标准对称加密算法(例如AES)

7、密钥交换算法

  • DH算法是一种密钥交换协议,通信双方通过不安全的信道协商密钥,然后进行对称加密传输。
  • DH算法没有解决中间人攻击。

8、非对称加密算法

  • 非对称加密就是加密和解密使用的不同的密钥:只有同一个公钥-私钥对才能正常加解密。
  • 非对称加密的典型算法就是RSA算法,它是由Ron Rivest,Adi Shamir,Leonard Adleman这三个哥们一起发明的,所以用他们仨的姓的首字母缩写表示。
  • 非对称加密相比对称加密的显著优点在于,对称加密需要协商密钥,而非对称加密可以安全地公开各自的公钥,在N个人之间通信的时候:使用非对称加密只需要N个密钥对,每个人只管理自己的密钥对。而使用对称加密需要则需要N*(N-1)/2个密钥,因此每个人需要管理N-1个密钥,密钥管理难度大,而且非常容易泄漏。
  • 非对称加密的缺点就是运算速度非常慢,比对称加密要慢很多
  • 在实际应用的时候,非对称加密总是和对称加密一起使用

9、签名算法

数字签名就是用发送方的私钥对原始数据进行签名,只有用发送方公钥才能通过签名验证。

数字签名用于:

  • 防止伪造;
  • 防止抵赖;
  • 检测篡改。

常用的数字签名算法包括:MD5withRSA/SHA1withRSA/SHA256withRSA/SHA1withDSA/SHA256withDSA/SHA512withDSA/ECDSA等。

10、数字证书

  • 数字证书就是集合了多种密码学算法,用于实现数据加解密、身份认证、签名等多种功能的一种安全标准。
  • 数字证书采用链式签名管理,顶级的Root CA证书已内置在操作系统中。
  • 数字证书存储的是公钥,可以安全公开,而私钥必须严格保密。