java aes 加盐
时间: 2023-11-08 15:04:47 浏览: 37
在 Java 中使用 AES 加盐可以增加密码的安全性。加盐是指在原始密码的基础上添加一些随机字符串,这个随机字符串称为“盐”,将盐和原始密码混合后再进行加密,可以防止彩虹表等攻击方式。
以下是示例代码:
```java
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
public class AesUtil {
private final static String AES_ALGORITHM = "AES/CBC/PKCS5Padding";
private final static int KEY_SIZE = 128;
private final static int IV_SIZE = 16;
private final static String CHARSET = StandardCharsets.UTF_8.name();
public static String encrypt(String plainText, String password, String salt) throws Exception {
byte[] saltBytes = salt.getBytes(CHARSET);
byte[] passwordBytes = password.getBytes(CHARSET);
byte[] keyBytes = new byte[KEY_SIZE / 8];
byte[] ivBytes = new byte[IV_SIZE];
SecretKeySpec secretKeySpec = null;
IvParameterSpec ivParameterSpec = null;
Cipher cipher = null;
SecureRandom secureRandom = new SecureRandom();
// 生成 key 和 iv
secureRandom.nextBytes(saltBytes);
secureRandom.nextBytes(ivBytes);
for (int i = 0; i < passwordBytes.length; i++) {
keyBytes[i % keyBytes.length] ^= passwordBytes[i];
}
// 初始化 Cipher
secretKeySpec = new SecretKeySpec(keyBytes, "AES");
ivParameterSpec = new IvParameterSpec(ivBytes);
cipher = Cipher.getInstance(AES_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
// 加密
byte[] encrypted = cipher.doFinal(plainText.getBytes(CHARSET));
// 拼接盐和 iv
byte[] saltIvBytes = new byte[saltBytes.length + ivBytes.length];
System.arraycopy(saltBytes, 0, saltIvBytes, 0, saltBytes.length);
System.arraycopy(ivBytes, 0, saltIvBytes, saltBytes.length, ivBytes.length);
// 返回加密后的结果
return Base64.getEncoder().encodeToString(saltIvBytes) + Base64.getEncoder().encodeToString(encrypted);
}
public static String decrypt(String cipherText, String password, String salt) throws Exception {
byte[] saltBytes = salt.getBytes(CHARSET);
byte[] passwordBytes = password.getBytes(CHARSET);
byte[] keyBytes = new byte[KEY_SIZE / 8];
byte[] ivBytes = new byte[IV_SIZE];
SecretKeySpec secretKeySpec = null;
IvParameterSpec ivParameterSpec = null;
Cipher cipher = null;
// 拆分盐和 iv
byte[] saltIvBytes = Base64.getDecoder().decode(cipherText.substring(0, 24));
System.arraycopy(saltIvBytes, 0, saltBytes, 0, saltBytes.length);
System.arraycopy(saltIvBytes, saltBytes.length, ivBytes, 0, ivBytes.length);
// 生成 key
for (int i = 0; i < passwordBytes.length; i++) {
keyBytes[i % keyBytes.length] ^= passwordBytes[i];
}
// 初始化 Cipher
secretKeySpec = new SecretKeySpec(keyBytes, "AES");
ivParameterSpec = new IvParameterSpec(ivBytes);
cipher = Cipher.getInstance(AES_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
// 解密
byte[] encrypted = Base64.getDecoder().decode(cipherText.substring(24));
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted, CHARSET);
}
}
```
示例中的加密过程中,先生成一个随机的盐和一个随机的 IV,将盐和 IV 拼接后放在加密结果的前面,然后再将加密的结果拼接在盐和 IV 的后面。在解密时,先从密文中拆出盐和 IV,然后再用同样的密码和盐生成 key,再用 key 和 IV 进行解密。