在用充气城堡解密后,为什么要添加这些方形符号?

时间:2018-07-27 12:58:18

标签: java encryption cryptography aes bouncycastle

我创建了一个简单的java方法,该方法使用有弹性的城堡库对文本进行加密和解密。加密按预期工作,但是当我解密某些内容时,最后得到以下多余的方形符号:

console test

我认为这可能与填充有关,但是我一直遵循the example在Bouncy Castle网站上的推荐,所以我真的不明白为什么我会得到这种输出。这是我正在使用的代码:

[主要]

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);
}

[CryptoCodec]

// 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);
    }
}

请记住,我仍在学习密码学,很想听听任何解释为什么会发生这种情况。预先感谢。

1 个答案:

答案 0 :(得分:4)

在解密cipher.getOutputSize(dataBytes.length)期间,它不知道将从填充中删除多少个字节(甚至不知道您是在告诉数据的最后一部分)。因此,它告诉您可能的最大值。

因此,您的目标数组大于所需的数组,并且您需要注意要填充多少数据。

您怎么知道填写了多少?从doFinal捕获返回值。那你怎么办呢?告诉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字节的数据将无法成功解密。