为什么用充气城堡解密后会附加这些方形符号?

Why are these square symbols appended after decrypting with bouncy castle?

我创建了一个简单的 java 方法,它使用充气城堡库加密和解密文本。加密按预期工作,但当我解密某些内容时,我在最后得到这些额外的方形符号:

我认为这可能与填充有关,但我已经关注了 bouncy castle 网站上的 the example,所以我真的不明白为什么我会得到这种输出。这是我正在使用的代码:

[主要]

public static void main(String[] argv) {
    String ciphertext = "PlJR5pzbowsuzHIc9iTKHg==";
    String decrypted;
    CryptoCodec codec = new CryptoCodec();

    decrypted = codec.exec("AES", "xxxxooooxxxxoooo", ciphertext, false);

    System.out.println("Ciphertext: " + ciphertext);
    System.out.println("Decrypted: " + decrypted);
}

[加密解码器]

// Eod: (true) Encrypt or (false) decrypt.
public String exec(String algorithm, String key, String data, boolean eod) {

    // Using AESEngine();
    BlockCipher engine = CipherEngine.getBlockCipher(algorithm);

    BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(engine));

    byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
    byte[] dataBytes;
    if(eod) {
        dataBytes = data.getBytes(StandardCharsets.UTF_8);
    } else {
        dataBytes = Base64.decode(data);
    }

    cipher.init(eod, new KeyParameter(keyBytes));

    byte[] outputText = new byte[cipher.getOutputSize(dataBytes.length)];
    int outputTextLen = cipher.processBytes(dataBytes, 0, dataBytes.length, outputText, 0);

    try {
        cipher.doFinal(outputText, outputTextLen);
    } catch (CryptoException err) {
        err.printStackTrace();
    }

    if(eod) {
        return new String(Base64.encode(outputText));
    } else {
        return new String(outputText);
    }
}

请记住,我仍在学习密码学,很想听听任何关于为什么会发生这种情况的解释。提前致谢。

在解密过程中 cipher.getOutputSize(dataBytes.length) 不知道它将从填充中删除多少字节(它甚至不知道你告诉它数据的最后一部分)。所以它告诉你可能的最大值。

因此,您的目标数组比需要的要大,您需要考虑填充了多少数据。

你怎么知道填了多少?从 doFinal 捕获 return 值。那你用它做什么?告诉 String 构造函数何时停止读取。

然后你会得到类似

的东西
try {
    outputTextLen += cipher.doFinal(outputText, outputTextLen);
} catch (CryptoException err) {
    err.printStackTrace();
}

if(eod) {
    return new String(Base64.encode(outputText));
} else {
    return new String(outputText, 0, outputTextLen);
}

这还修复了您现在加密 16 字节数据将无法成功解密的错误。