我想在java中实现AES 256位CBC算法。我想做出这样的事情。 Click here如何在Java中使用CBC(带有32位IV和密钥)实现AES 128位?
我使用下面的程序从多个SO线程,以下是我用于加密/解密的代码。按照@dave_thompson的建议更新了代码,但是IV的长度仍然是相同的错误。
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Scanner;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class EncryptionDecryption {
private static String salt;
private static int iterations = 65536 ;
private static int keySize = 256;
private static byte[] ivBytes = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
private static SecretKey secretKey;
public static void main(String []args) throws Exception {
Scanner in = new Scanner(System.in);
salt = getSalt();
String s = in.nextLine();
char[] message = s.toCharArray();
System.out.println("Message: " + String.valueOf(message));
System.out.println("Encrypted: " + encrypt(message));
System.out.println("Decrypted: " + decrypt(encrypt(message).toCharArray()));
}
public static String encrypt(char[] plaintext) throws Exception {
byte[] saltBytes = salt.getBytes();
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(plaintext, saltBytes, iterations, keySize);
secretKey = skf.generateSecret(spec);
SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretSpec);
AlgorithmParameters params = cipher.getParameters();
byte[] encryptedTextBytes = cipher.doFinal(String.valueOf(plaintext).getBytes("UTF-8"));
return DatatypeConverter.printBase64Binary(encryptedTextBytes);
}
public static String decrypt(char[] encryptedText) throws Exception {
System.out.println(encryptedText);
byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(new String(encryptedText));
SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretSpec, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = null;
try {
decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return new String(decryptedTextBytes);
}
public static String getSalt() throws Exception {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[20];
sr.nextBytes(salt);
return new String(salt);
}
}
问题与当前的代码显示我以下错误,但如果我改变IV回到16位它的作品。
以下是我所指的SO线程。
- Java 256-bit AES Password-Based Encryption
- decrypting data with AES/CBC/PKCS5Padding using blackberry
- Java 256-bit AES Password-Based Encryption
请不要混淆比特和字节。如果CBC模式有这种情况,那么16位IV将基本无用。 –
将16字节的OMG设置为0,或十六进制* 16 *字符的字符。啧。 –
(调整)该网站输入的十六进制密钥和IV,所以你的例子有128位密钥不是256位,128位(零),因为IV不是256.它直接使用密钥,而不是做PBKDF2或任何其他密钥派生,并且它正在执行零填充而不是PKCS#5填充。简而言之,如果你想要做那些网站正在做的事情,那么你的代码中几乎所有的东西都是错误的,如果你想做一些与你的代码中的东西接近的网站是完全错误的。 ** PICK ONE。**但是注意零填充是不常见的,通常是一个坏主意。 –