我有以下 Spring Boot 服务用于加密和解密字符串:
@Service
public class EncryptionServiceImpl implements EncryptionService {
// Strong AES key (256-bit)
private static final String AES_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final int AES_KEY_SIZE = 256;
// Generate a strong secret key for AES encryption
private SecretKey secretKey;
private SecureRandom secureRandom = new SecureRandom();
private DataKeysRepository dataKeysRepository;
@Autowired
public EncryptionServiceImpl(DataKeysRepository dataKeysRepository) throws Exception {
// Generate or load your AES SecretKey securely
this.secretKey = generateSecretKey();
if (this.secretKey == null) {
throw new IllegalStateException("SecretKey generation failed!");
}
this.dataKeysRepository = dataKeysRepository;
}
/**
* Generates a strong AES SecretKey.
* @return SecretKey
* @throws Exception If key generation fails.
*/
private SecretKey generateSecretKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(AES_KEY_SIZE, secureRandom); // 256-bit AES key
return keyGenerator.generateKey();
}
@Override
public String encrypt(String plainText)
{
try {
byte[] iv = new byte[16];
secureRandom.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Initialize cipher for encryption
Cipher cipher = Cipher.getInstance(AES_CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
// Encrypt the plain text
byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
// Combine IV and encrypted text for storage/transmission
byte[] ivAndEncryptedText = new byte[iv.length + encryptedTextBytes.length];
System.arraycopy(iv, 0, ivAndEncryptedText, 0, iv.length);
System.arraycopy(encryptedTextBytes, 0, ivAndEncryptedText, iv.length, encryptedTextBytes.length);
DataKeys data = new DataKeys();
data.setText(Base64.getEncoder().encodeToString(ivAndEncryptedText));
data.setCreatedAt(OffsetDateTime.now());
DataKeys key = dataKeysRepository.save(data);
// Return UUID of the encrypted text
return key.getId().toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public String decrypt(String key)
{
Optional<DataKeys> byId = dataKeysRepository.findById(UUID.fromString(key));
if (byId.isPresent()) {
DataKeys dataKeys = byId.get();
try {
byte[] ivAndEncryptedText = Base64.getDecoder().decode(dataKeys.getText());
// Extract the IV
byte[] iv = new byte[16];
System.arraycopy(ivAndEncryptedText, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Extract encrypted text
byte[] encryptedTextBytes = new byte[ivAndEncryptedText.length - iv.length];
System.arraycopy(ivAndEncryptedText, iv.length, encryptedTextBytes, 0, encryptedTextBytes.length);
// Initialize cipher for decryption
Cipher cipher = Cipher.getInstance(AES_CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
// Decrypt and return as plain text
byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
当我发送加密和解密文本的请求时,它工作正常。 但是当我重新启动微服务然后尝试解密字符串时,我收到错误:
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:861)
at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:941)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:734)
at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2244)
在这个Java方法中:
doFinal(...)
你知道是什么原因导致这个问题吗?
但是当我重新启动微服务然后尝试解密字符串时,我收到错误
keyGenerator.init(AES_KEY_SIZE, secureRandom); // 256-bit AES key
每次初始化后都会生成一个新密钥。要解密密文,您需要相同的密钥来加密和解密,因此 oyu 需要将密钥保存在某处