JavaSE系列-08 加密与安全

加密与安全

数据安全:防窃听、防篡改、防伪造

编码算法

URL编码

URL编码的目的是把任意文本数据编码为%前缀表示文本
编码规则:

1)A-Z,a-z,0-9以及- _ . *保持不变
2)其他字符以%XX表示
	<:%3C
	中:%E4%B8%AD(UTF-8:0xe4b8ad)
String orginal = "URL 参数";
String encoded = URLEncoder.encode(orginal, "UTF-8");
System.out.println(encoded); // URL+%E5%8F%82%E6%95%B0
String ori = new String(URLDecoder.decode(encoded, "UTF-8"));
System.out.println(ori); // URL 参数

Base64编码

Base64编码的目的是把任意二进制数据编码为文本(长度增加1/3)

String base64Encode(byte[] data)
byte[]{
   
   0xe4, 0xb8, 0xad} -> "5Lit"

在这里插入图片描述
Base64编码是一种文本(a-z,A-Z,0-9,+/=)表示二进制内容的方式,适用于文本协议,但是效率会下降,Base64应用于:电子邮件协议
Base64编码长度如果不是3的整数倍,会末尾补0x00或0x00 0x00,编码后加一个等号(=)表示补充了1个字节,编码后加两个等号(==)表示补充了2个字节。

public class Main {
   
   
	public static void main(String[] args) throws Exception {
   
   
		String original = "Hello\u00ff编码测试";
		String b64 = Base64.getEncoder().encodeToString(original.getBytes());
		System.out.println(b64);
		String ori = new String(Base64.getDecoder().decode(b64), "UTF-8");
		System.out.println(ori);
	}
}
// SGVsbG/Dv+e8lueggea1i+ivlQ==
// Helloÿ编码测试

// 还可以利用withoutPadding()去掉末尾的等号
String b64 = Base64.getEncoder().withoutPadding().encodeToString(original.getBytes());
// SGVsbG/Dv+e8lueggea1i+ivlQ

// 使用URL的Base64编码是 加号(+)变减号(-),反斜线(/)变下划线(_)
String original = "Hello\u00ff编码测试";
		String b64 = Base64.getUrlEncoder().withoutPadding().encodeToString(original.getBytes());
		System.out.println(b64);
		String ori = new String(Base64.getUrlDecoder().decode(b64), "UTF-8");
		System.out.println(ori);
// SGVsbG_Dv-e8lueggea1i-ivlQ
// Helloÿ编码测试

其他类似Base64的编码有:Base32、Base48、Base58

摘要算法

摘要算法(哈希算法 / Hash / Digest / 数字指纹)
计算任意长度数据的摘要,输出固定长度,相同的输入始终得到相同的输出,不同的输入尽量得到不同的输出
Java的Object.hashCode()方法就是一个摘要算法

输入:任意数据
输出:固定长度数据(int,byte[4])
相同的输入得到相同的输出:equals、hashCode

碰撞:两个不同的输入得到了相同的输出
Hash算法的安全性:

1)碰撞率低
2)不能猜测输出
3)输入的任意一个bit的变化会造成输出完全不同
4)很难从输出反推输入(只能穷举)

常用的摘要算法

算法 输出长度
MD5 128bits 16bytes
SHA-1 160bits 20bytes
SHA-256 256bits 32bytes
RipeMD-160 160bits 20bytes

MD5

1)验证原始数据是否被篡改
2)存储用户口令
3)需要防止彩虹表攻击:对每个口令额外添加随机数salt
用途:验证文件的完整性、存储用户口令

md5(inputPassword)
md5(salt + inputPassword)

import java.math.BigInteger;
import java.security.MessageDigest;

public class Main {
   
   
	public static byte[] toMD5(byte[] input) {
   
   
		MessageDigest md;
		try {
   
   
			md = MessageDigest.getInstance("MD5");
		} catch (Exception e) {
   
   
			throw new RuntimeException(e);
		}
		md.update(input);
		return md.digest();
	}
	public static void main(String[] args) throws Exception {
   
   
		String s = "Md5摘要算法测试";
		byte[] r = toMD5(s.getBytes("UTF-8"));
		System.out.println(String.format("%032x", new BigInteger(1, r)));
	}
}
String password = "Hello, world";
String salt = "Random salt";
byte[] r = toMD5((salt + password).getBytes("UTF-8"));
System.out.println(String.format("%032x", new BigInteger(1, r)));

SHA1

是由美国国家安全局开发的一种哈希算法,输出160bits或20bytes,主要有SHA-0 / SHA-1 / SHA-256 / SHA-512,比MD5更加安全

算法 输出长度
SHA-1 160bits 20bytes
SHA-256 256bits 32bytes
SHA-512 512bits 64bytes
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(input); 
...
byte[] result = md.digest(); // 20bytes

BouncyCastle

是第三方算法提供的一组加密/哈希算法,官网:http://www.bouncycastle.org/
如何使用第三方提供的算法

添加第三方jar至classpath
注册第三方算法提供方 Security.addProvider(new BouncyCastleProvider());//注册
正常使用JDK提供的接口
Security.addProvider(new BouncyCastleProvider());//注册
MessageDigest md = MessageDigest.getInstance("RipeMD160");
md.update(input);
...
byte[] result = md.digest(); // 20bytes

Hmac

Hash-based Message Authentication Code,是基于秘钥的消息认证码算法,是一种更安全的消息摘要算法
HmacMd5 ≈ md5(secure_ksy, data);
Hmac是把Key混入摘要的算法

byte data = ...
KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
SecretKey skey = keyGen.generateKey();
Mac mac = Mac.getInstance("HmacMD5");
mac.init(skey);
mac.update(data);
byte[] result = mac.doFinal();

可以配合MD5、SHA-1等摘要算法
摘要长度和原摘要算法长度相同

加密算法

对称加密算法

使用同一个密钥进行加密和解密
在这里插入图片描述
常用算法:DES、AES、IDEA等

算法 密钥长度 工作模式 填充模式
DES 56/64 ECB/CBC/PCBC/CTR/… NoPadding/PKCS5Padding…
AES 128/192/256 ECB/CBC/PCBC/CTR/… NoPadding/PKCS5Padding/PKCS7Padding…
IDEA 128 ECB PKCS5Padding/PKCS5Padding…
密钥长度由算法设计决定,AES的密钥长度是128 / 192 / 256
使用对称加密算法需要指定:算法名称 / 工作模式(ECB、CBC、PCBC…)/填充模式(NoPadding、PKCS5Padding、PKCS7Padding…)
ECB模式
public class AES_ECB_Cipher {
   
   
	static final String CIPHER_NAME = "AES/ECB/PKCS5Padding";
	/**
	 * 加密
	 */
	public static byte[] encrypt(byte[] key, byte[] input) throws Exception{
   
   
		Cipher cipher = Cipher.getInstance(CIPHER_NAME);
		SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
		cipher.init(Cipher.ENCRYPT_MODE, keySpec);
		return cipher.doFinal(input);
	}
	/**
	 * 解密
	 */
	public static byte[] decrpty(byte[] key, byte[] input) throws Exception{
   
   
		Cipher cipher = Cipher.getInstance(CIPHER_NAME);
		SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
		cipher.init(Cipher.DECRYPT_MODE, keySpec);
		return cipher.doFinal(input);
	}
	public static void main(String[] args) throws Exception{
   
   
		// 原文:
		String message = "Hello, world! encrypted using AES!";
		System.out.println("Message: " + message);
		// 128位密钥 = 16 bytes Key:
		byte[] key = "1234567890abcdef".getBytes("UTF-8");
		// 加密:
		byte[] data = message.getBytes(StandardCharsets.UTF_8);
		byte[] encrypted = encrypt(key, data);
		System.out.println("Enctypted data: " + Base64.getEncoder().encodeToString(encrypted));
		// 解密:
		byte[] decrypted = decrpty(key, encrypted);
		System.out.println("Decrypted data: " + new String(decrypted, "UTF-8"));
	}
}
// Message: Hello, world! encrypted using AES!
// Enctypted data: 6ofAje3dbEse
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

讲文明的喜羊羊拒绝pua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值