1. 什么是对称加密
对称密钥算法(Symmetric-key algorithm),又称为私钥加密、共享密钥加密,是密码学中的一类加密算法。对称加密的特点是,在加密和解密时使用相同的密钥,或是使用两个可以简单地相互推算的密钥。常见的对称加密算法有 DES,3DES,AES,RC2,RC4,RC5,SM4等。
2. 对称加密的优缺点
优点:
加密计算量小,速度快,适合对大量数据进行加密的场景。
缺点:
密钥传输问题:如上所说,由于对称加密的加密和解密使用的是同一个密钥,所以对称加密的安全性就不仅仅取决于加密算法本身的强度,更取决于密钥是否被安全的保管,因此加密者如何把密钥安全的传递到解密者手里,就成了对称加密面临的关键问题。
密钥管理问题:再者随着密钥数量的增多,密钥的管理问题会逐渐显现出来。比如我们在加密用户的信息时,不可能所有用户都用同一个密钥加密解密,这样的话,一旦密钥泄漏,就相当于泄露了所有用户的信息,因此需要为每一个用户单独的生成一个密钥并且管理,这样密钥管理的代价也会非常大。
3. 分组模式
- ECB : 电子密码本(Electronic codebook)
- CBC : 密码块链接(Cipher-block chaining)
- PCBC : 填充密码块链接(Propagating cipher-block chaining), 也被称为 明文密码块链接(Plaintext cipher-block chaining)
- CFB : 密文反馈(Cipher feedback)
- OFB : 输出反馈(Output feedback)
- CTR : 计数器模式(Counter mode), 也被称为 ICM整数计数模式(Integer Counter Mode), 或 SIC模式(Segmented Integer Counter)
- GCM : 伽罗瓦/计数器模式(Galois/Counter Mode)。
4. 填充方式
- NoPadding
- PKCS#7_PADDING
- PKCS#5_PADDING
- ZeroPadding
- ISO10126Padding
5. DES算法
DES 全称 Data Encryption Standard,是一种使用密钥加密的块算法。现在认为是一种不安全的加密算法,因为现在已经有用穷举法攻破 DES 密码的报道了。尽管如此,该加密算法还是运用非常普遍,是一种标准的加密算法,3DES 是 DES 的加强版本。
DES密钥必须是8的倍数,否则会报 java.security.InvalidKeyException: Wrong key size。DES 标准密钥就是56位,8个字符即8个字节,每个字节的最高位不用,即每个字节只用7位,8个字符正好是56位。
示例代码:
public class DESUtil {
public static String encrypt(String plainText, String key) {
try {
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "DES");
// 默认是DES/ECB/PKCS5Padding
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] bytes = cipher.doFinal(plainText.getBytes());
return Base64Utils.encodeToString(bytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static String decrypt(String cipherText, String key) {
try{
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] bytes = Base64Utils.decodeFromString(cipherText);
byte[] plainBytes = cipher.doFinal(bytes);
return new String(plainBytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String key = "12345678";
// 加密过程
String cipherStr = DESUtil.encrypt("hello world", key);
System.out.println("cipherStr: " + cipherStr);
String plainStr = DESUtil.decrypt(cipherStr, key);
System.out.println("plainStr: " + plainStr);
}
}
输出:
cipherStr: KNugLrX23UddguNoHIO7dw==
plainStr: hello world
6. AES算法
AES是一种对称加密算法,全称为“高级加密标准”(Advanced Encryption Standard)。它是一个区块加密算法,适用于大多数应用场景,包括加密和解密,还可以在不同的平台和设备之间进行加密和解密操作。
AES 是一种分组密码算法,它将明文数据分成固定大小的分组进行处理。每个分组的大小通常为 128 位(16 字节),也可以是 192 位或 256 位。在加密过程中,对每个分组使用相同的密钥和加密算法进行操作,将明文分组转换为密文分组。这种分组处理方式使得 AES 能够高效地处理大量数据,同时保证数据的安全性。
AES 支持不同长度的密钥,分别为 128 位、192 位和 256 位。密钥长度越长,加密的安全性越高,但计算复杂度也会相应增加。在实际应用中,需要根据安全需求和计算资源等因素选择合适的密钥长度。例如,对于一般的商业应用,128 位密钥通常已经能够提供足够的安全性;而对于一些对安全性要求极高的场景,如军事、金融等领域,可能会选择使用 256 位密钥。
示例代码:
public class AESUtil {
public static String encrypt(String plainText, String key) {
try {
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] bytes = cipher.doFinal(plainText.getBytes());
return Base64Utils.encodeToString(bytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static String decrypt(String cipherText, String key) {
try {
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] bytes = Base64Utils.decodeFromString(cipherText);
byte[] plainBytes = cipher.doFinal(bytes);
return new String(plainBytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String key = "1234567890123456";
String cipherStr = AESUtil.encrypt("hello world", key);
System.out.println("cipherStr: " + cipherStr);
String plainStr = AESUtil.decrypt(cipherStr, key);
System.out.println("plainStr: " + plainStr);
}
}
下面演示一下AES采用CBC分组模式的加密算法:
public class AESUtil {
public static String encryptByCBC(String plainText, String key, String iv){
try {
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] bytes = cipher.doFinal(plainText.getBytes());
return Base64Utils.encodeToString(bytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static String decryptByCBC(String cipherText, String key, String iv){
try {
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] cipherBytes = Base64Utils.decodeFromString(cipherText);
byte[] bytes = cipher.doFinal(cipherBytes);
return new String(bytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String key = "1234567890123456";
String iv = "9876543210654321";
String cipherStr = AESUtil.encryptByCBC("This is a test plainText", key, iv);
System.out.println("cipherStr: " + cipherStr);
String plainStr = AESUtil.decryptByCBC(cipherStr, key, iv);
System.out.println("plainStr: " + plainStr);
}
}
7. SM4算法
SM4 是一种中国国家密码标准(GB/T 32907-2016)中定义的分组加密算法,又称为“中国商用密码算法SM4”。它是由中国国家密码管理局发布的,并广泛应用于金融、电子商务和其他需要数据加密的场景。
SM4 是一种对称加密算法,意味着加密和解密使用相同的密钥。它是一个 128 位(16 字节)分组密码,意味着它将明文分成 128 位的块,然后对每个块进行加密。SM4 使用了 128 位的密钥进行加密和解密。
SM4 算法的主要特点是:
分组长度:128 位。
密钥长度:128 位。
分组模式:支持多种模式,如ECB(电子密码本)、CBC(加密分组链接)、CTR(计数器模式)等。
示例代码:
首先引用maven依赖包:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
Java代码示例:
public class SM4Util {
static {
if(Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null){
Security.addProvider(new BouncyCastleProvider());
}
}
public static String encrypt(String plainText, String key) {
try{
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "SM4");
Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding", BouncyCastleProvider.PROVIDER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] bytes = cipher.doFinal(plainText.getBytes());
return Base64Utils.encodeToString(bytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static String decrypt(String cipherText, String key) {
try{
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "SM4");
Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding", BouncyCastleProvider.PROVIDER_NAME);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] cipherBytes = Base64Utils.decodeFromString(cipherText);
byte[] bytes = cipher.doFinal(cipherBytes);
return new String(bytes);
}catch (Exception ex){
return null;
}
}
public static void main(String[] args) {
String key = "1234567890123456";
String cipherStr = SM4Util.encrypt("this is sm4 test", key);
System.out.println("cipherStr: " + cipherStr);
String plainStr = SM4Util.decrypt(cipherStr, key);
System.out.println("plainStr: " + plainStr);
}
}
输出:
cipherStr: UptAXiDiT7j98cIKRwdAt2yI9zmvKimnNTgfVne63vc=
plainStr: this is sm4 test
个人公众号,欢迎关注,持续交流。

1865

被折叠的 条评论
为什么被折叠?



