解密未返回正确的明文

Decryption not returning correct plaintext

我正在尝试创建一个简单的 AES encryption/decryption 模块以用于更大的项目,但我在使用 AES 方法时遇到了问题。我做了很多研究,但我无法弄清楚我的代码中出了什么问题(我怀疑我遗漏了一些简单的东西)。

主要:

public static byte[] genKey() {
    // Create key generator
    KeyGenerator keyGen;
    try {
        keyGen = KeyGenerator.getInstance("AES");
    }
    catch(GeneralSecurityException e) {
        e.printStackTrace();
        return null;
    }

    // Create random byte generator
    SecureRandom r = new SecureRandom();

    // Initialize key generator
    keyGen.init(256, r);

    SecretKey key = keyGen.generateKey();

    return key.getEncoded();
}

public static void main(String[] args) throws GeneralSecurityException {
// write your code here
    // Create AES handler
    AES aes = new AES();

    // Generate key
    byte[] key = genKey();

    // Set key for AES
    aes.setKey(key);

    Scanner in = new Scanner(System.in);

    System.out.print("Please enter a phrase to encrypt: ");
    String input = in.nextLine();

    // Encrypt phrase
    byte[][] encrypted = aes.encrypt(input);

    // Decrypt phrase
    String plaintext = aes.decrypt(encrypted[0], encrypted[1]);

    // Print results
    System.out.println("Ciphertext: " + encrypted[1]);
    System.out.println("Plaintext: " + plaintext);
}

AES:

private Cipher cipher;
private SecretKey key;

public AES() {
    // Create Cipher
    try {
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
    }
}

public void setKey(byte[] key) {
    this.key = new SecretKeySpec(key, "AES");
}

public byte[][] encrypt(String plaintext) throws GeneralSecurityException {
    System.out.println("Using key : " + key.getEncoded() + " to encrypt");
    byte[][] values = new byte[2][];

    // Decode plaintext into bytes
    byte[] decodedPlaintext = new byte[0];
    try {
        decodedPlaintext = plaintext.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    // Generate an IV and set up the Cipher to encrypt
    byte[] ivBytes = new byte[16];
    SecureRandom rand = new SecureRandom();
    rand.nextBytes(ivBytes);

    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    cipher.init(Cipher.ENCRYPT_MODE, key, iv);

    // Encrypt decoded plaintext
    byte[] ciphertext = cipher.doFinal(decodedPlaintext);
    values[0] = ivBytes;
    values[1] = ciphertext;

    return values;
}

public String decrypt(byte[] ivBytes, byte[] ciphertext) throws GeneralSecurityException {
    System.out.println("Using key " + key.getEncoded() + " to decrypt");
    // Set up cipher to decrypt
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    cipher.init(Cipher.DECRYPT_MODE, key, iv);

    byte[] decodedPlaintext = cipher.doFinal(ciphertext);

    // Encode plaintext
    String plaintext = Base64.getEncoder().encodeToString(decodedPlaintext);

    return plaintext;
}

结果:

Please enter a phrase to encrypt: test
Using key : [B@442d9b6e to encrypt
Using key [B@3d012ddd to decrypt
Ciphertext: [B@515f550a
Plaintext: dGVzdA==

我不明白为什么我的 encryption/decryption 似乎在使用不同的密钥,而我一开始只设置了一次密钥。我创建的密钥有误吗?

我也试过:

byte[] key = new byte[32];

SecureRandom r = new SecureRandom();

r.nextBytes(key);

// Set key for AES
aes.setKey(key);

和运行属于同一问题。

如果您在 AES class 中一直跟踪 this.key 使用 Arrays.toString(this.key.getEncoded()) 进行编码和解码,它确实看起来像是在使用永久密钥。

this.key.getEncoded().toString()) returns 每次都有不同的表示,但看起来实际的字节数组是相同的。

我换了

String plaintext = Base64.getEncoder().encodeToString(decodedPlaintext);

String plaintext = new String(decodedPlaintext, StandardCharsets.UTF_8);

它似乎奏效了。