前言
之前对非对称加密作了介绍(请大力点击),现对对称加密作个简单介绍。
对称加密算法
能通过相同的密钥对报文进行加密、解密的算法,叫对称加密算法。
比如,客户端,将一段报文通过密钥加密成密文,发送密文给服务端,服务端收到密文,通过相同的密钥解密,还原报文。
常用的对称加密算法:DES
特点:
- 通过相同的密钥对报文进行加密、解密。所以,需要保证密钥的保密。
- 计算速度快。所以,经常与计算速度慢的
非对称加密算法
一起使用,形成混合加密(后续博文描述)。
为什么要有密钥
我们有加密算法,为什么要有密钥?
答:加密算法只是一种算法(可视作一套逻辑),通常为大家所知,比如DES。如果一段报文,通过大家熟知的逻辑加密,那么其他人也能通过相应的逻辑解密,这样意义不大。所以就有密钥,相当于算法的密码,算法逻辑加上密钥公共将报文加密成密文,相应的,需通过算法逻辑和密钥才能正确解密。
危险
最常见的破解加密算法的手段是枚举攻击。由于大家都知道算法的逻辑,通过枚举密钥的所有可能性尝试解码。所以,密钥的位数决定了枚举攻击的难度,密钥位数越多,越难枚举出所有的可能性破解,当然,我们加解密的计算速度也有相应的影响。随着现代计算机计算速度提升,密钥的位数也在提升。
简单的例子
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.junit.Test;
public class DESUtils {
/**
* 加密
* @param data 加密的数据
* @param key 密钥
* @return 加密后的数据
*/
public static byte[] encrypt(byte[] data, byte[] key) {
try {
DESKeySpec desKeySpec = new DESKeySpec(key);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(data);
} catch (InvalidKeyException e) {
throw new RuntimeException("无效的Key值");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("无DES算法");
} catch (InvalidKeySpecException e) {
throw new RuntimeException("无效的KeySpec");
} catch (NoSuchPaddingException e) {
throw new RuntimeException("无Padding");
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
}
}
/**
* 解密
* @param data 解密前的数据
* @param key 密钥
* @return 解密后的数据
*/
public static byte[] decrypt(byte[] data, byte[] key) {
try {
DESKeySpec desKeySpec = new DESKeySpec(key);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(data);
} catch (InvalidKeyException e) {
throw new RuntimeException("无效的Key值");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("无DES算法");
} catch (InvalidKeySpecException e) {
throw new RuntimeException("无效的KeySpec");
} catch (NoSuchPaddingException e) {
throw new RuntimeException("无Padding");
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
}
}
@Test
public void encryptTest() {
System.out.println(Base64.getEncoder().encodeToString(DESUtils.encrypt("hello".getBytes(), "12345678".getBytes())));
}
@Test
public void decryptTest() {
System.out.println(new String(DESUtils.decrypt(Base64.getDecoder().decode("uhbGoCVxJa8="), "12345678".getBytes())));
}
}