在 Java 中加密,而解密方法已知
Encryption in Java while Decryption method is known
我尝试在Java中做加解密机制。我找到了一些解密代码,但我不知道如何加密。什么样的加密方式会兼容这样的解密方式:
private byte[] padKey(byte[] key) {
byte[] paddedKey = new byte[32];
System.arraycopy(key, 0, paddedKey, 0, key.length);
return paddedKey;
}
private byte[] unpad(byte[] data) {
byte[] unpaddedData = new byte[data.length - data[data.length - 1]];
System.arraycopy(data, 0, unpaddedData, 0, unpaddedData.length);
return unpaddedData;
}
public String decrypt(String encodedJoinedData) throws Exception {
// Base64-decode the joined data
byte[] joinedData = Base64.decode(encodedJoinedData);
// Get IV and encrypted data
byte[] iv = new byte[16];
System.arraycopy(joinedData, 0, iv, 0, iv.length);
byte[] encryptedData = new byte[joinedData.length - iv.length];
System.arraycopy(joinedData, iv.length, encryptedData, 0, encryptedData.length);
// Pad key
byte[] key = padKey("SiadajerSiadajer".getBytes());
Key aesKey = new SecretKeySpec(key, "AES");
// Specify CBC-mode
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
// Decrypt data
byte[] decryptedData = cipher.doFinal(encryptedData);
// Remove custom padding
byte[] unpaddedData = unpad(decryptedData);
return new String(unpaddedData);
}
如果您正在寻找与您的 decrypt
方法相对应的加密方法,您只需在 decrypt
方法中反转该过程即可。必须在 encrypt
方法的主体中完成以下操作(让 plainText
成为包含纯文本的 String
参数):
添加自定义填充
// Pad data (custom padding)
byte[] paddedData = pad(plainText.getBytes(), 16);
加密您的纯文本
// Pad key
byte[] key = padKey("SiadajerSiadajer".getBytes());
Key aesKey = new SecretKeySpec(key, "AES");
// Specify block-cipher (AES), mode (CBC) and padding (PKCS5)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// Create random IV
SecureRandom secureRandom = new SecureRandom();
byte iv[] = new byte[cipher.getBlockSize()];
secureRandom.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Encrypt data
cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivParameterSpec);
byte[] encryptedData = cipher.doFinal(paddedData);
加入IV和加密数据
// Join IV and encrypted data
byte[] joinedData = new byte[iv.length + encryptedData.length];
System.arraycopy(iv, 0, joinedData, 0, iv.length);
System.arraycopy(encryptedData, 0, joinedData, iv.length, encryptedData.length);
Base 64-编码连接数据
// Base64-encode data
String encodedJoinedData = Base64.encode(joinedData, 0);
最后,encodedJoinedData
必须归还。
此外,您必须实现自定义填充。以下方法实现了自定义 PKCS5-Padding,并且可能与 unpad
方法对应:
private byte[] pad(byte[] data, int size) {
byte padLength = (byte)(size - (data.length % size));
byte[] paddedData = new byte[data.length + padLength];
System.arraycopy(data, 0, paddedData, 0, data.length);
for (int i = data.length; i < paddedData.length; i++)
paddedData[i] = (byte)padLength;
return paddedData;
}
顺便说一句,您的 decrypt
方法(以及 encrypt
方法)存在一些问题:
- 您不应使用硬编码密钥,但这可能仅用于测试目的。要创建安全的 AES 密钥,请参见例如How to create a secure random AES key in Java?.
- 最明显的缺陷是它在
decrypt
/encrypt
方法中被取消填充/填充两次,这没有任何意义。因此,删除所选的 PKCS5-Padding(即从 AES/CBC/PKCS5Padding
更改为 AES/CBC/NoPadding
)或两者中的自定义填充,decrypt
- 和 encrypt
-方法(前提是可能在您的项目范围内)。
我尝试在Java中做加解密机制。我找到了一些解密代码,但我不知道如何加密。什么样的加密方式会兼容这样的解密方式:
private byte[] padKey(byte[] key) {
byte[] paddedKey = new byte[32];
System.arraycopy(key, 0, paddedKey, 0, key.length);
return paddedKey;
}
private byte[] unpad(byte[] data) {
byte[] unpaddedData = new byte[data.length - data[data.length - 1]];
System.arraycopy(data, 0, unpaddedData, 0, unpaddedData.length);
return unpaddedData;
}
public String decrypt(String encodedJoinedData) throws Exception {
// Base64-decode the joined data
byte[] joinedData = Base64.decode(encodedJoinedData);
// Get IV and encrypted data
byte[] iv = new byte[16];
System.arraycopy(joinedData, 0, iv, 0, iv.length);
byte[] encryptedData = new byte[joinedData.length - iv.length];
System.arraycopy(joinedData, iv.length, encryptedData, 0, encryptedData.length);
// Pad key
byte[] key = padKey("SiadajerSiadajer".getBytes());
Key aesKey = new SecretKeySpec(key, "AES");
// Specify CBC-mode
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
// Decrypt data
byte[] decryptedData = cipher.doFinal(encryptedData);
// Remove custom padding
byte[] unpaddedData = unpad(decryptedData);
return new String(unpaddedData);
}
如果您正在寻找与您的 decrypt
方法相对应的加密方法,您只需在 decrypt
方法中反转该过程即可。必须在 encrypt
方法的主体中完成以下操作(让 plainText
成为包含纯文本的 String
参数):
添加自定义填充
// Pad data (custom padding) byte[] paddedData = pad(plainText.getBytes(), 16);
加密您的纯文本
// Pad key byte[] key = padKey("SiadajerSiadajer".getBytes()); Key aesKey = new SecretKeySpec(key, "AES"); // Specify block-cipher (AES), mode (CBC) and padding (PKCS5) Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Create random IV SecureRandom secureRandom = new SecureRandom(); byte iv[] = new byte[cipher.getBlockSize()]; secureRandom.nextBytes(iv); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); // Encrypt data cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivParameterSpec); byte[] encryptedData = cipher.doFinal(paddedData);
加入IV和加密数据
// Join IV and encrypted data byte[] joinedData = new byte[iv.length + encryptedData.length]; System.arraycopy(iv, 0, joinedData, 0, iv.length); System.arraycopy(encryptedData, 0, joinedData, iv.length, encryptedData.length);
Base 64-编码连接数据
// Base64-encode data String encodedJoinedData = Base64.encode(joinedData, 0);
最后,encodedJoinedData
必须归还。
此外,您必须实现自定义填充。以下方法实现了自定义 PKCS5-Padding,并且可能与 unpad
方法对应:
private byte[] pad(byte[] data, int size) {
byte padLength = (byte)(size - (data.length % size));
byte[] paddedData = new byte[data.length + padLength];
System.arraycopy(data, 0, paddedData, 0, data.length);
for (int i = data.length; i < paddedData.length; i++)
paddedData[i] = (byte)padLength;
return paddedData;
}
顺便说一句,您的 decrypt
方法(以及 encrypt
方法)存在一些问题:
- 您不应使用硬编码密钥,但这可能仅用于测试目的。要创建安全的 AES 密钥,请参见例如How to create a secure random AES key in Java?.
- 最明显的缺陷是它在
decrypt
/encrypt
方法中被取消填充/填充两次,这没有任何意义。因此,删除所选的 PKCS5-Padding(即从AES/CBC/PKCS5Padding
更改为AES/CBC/NoPadding
)或两者中的自定义填充,decrypt
- 和encrypt
-方法(前提是可能在您的项目范围内)。