当前位置: 首页 > 面试题库 >

带有Bouncy Castle的256位AES / CBC / PKCS5Padding

双恩
2023-03-14
问题内容

我在将以下JDK JCE加密代码映射到Bouncy Castles轻型API时遇到麻烦:

public String dec(String password, String salt, String encString) throws Throwable {
    // AES algorithm with CBC cipher and PKCS5 padding
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");

    // Construct AES key from salt and 50 iterations 
    PBEKeySpec pbeEKeySpec = new PBEKeySpec(password.toCharArray(), toByte(salt), 50, 256);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
    SecretKeySpec secretKey = new SecretKeySpec(keyFactory.generateSecret(pbeEKeySpec).getEncoded(), "AES");

    // IV seed for first block taken from first 32 bytes
    byte[] ivData = toByte(encString.substring(0, 32));
    // AES encrypted data
    byte[] encData = toByte(encString.substring(32));

    cipher.init( Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec( ivData ) );

    return new String( cipher.doFinal( encData ) );
}

上面的方法很好用,但是由于Oracle对加密强度的限制,所以移植性不强。我已经尝试过几次尝试移植到Bouncy Castles轻量级API,但没有成功。

public String decrypt1(String password, String salt, String encString) throws Exception {

    byte[] ivData = toByte(encString.substring(0, 32));
    byte[] encData = toByte(encString.substring(32));

    PKCS12ParametersGenerator gen = new PKCS12ParametersGenerator(new SHA256Digest());
    gen.init(password.getBytes(), toByte(salt), 50);
    CBCBlockCipher cbcBlockcipher = new CBCBlockCipher(new RijndaelEngine(256));
    CipherParameters params = gen.generateDerivedParameters(256, 256);

    cbcBlockcipher.init(false, params);

    PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(cbcBlockcipher, new PKCS7Padding());
    byte[] plainTemp = new byte[aesCipher.getOutputSize(encData.length)];
    int offset = aesCipher.processBytes(encData, 0, encData.length, plainTemp, 0);
    int last = aesCipher.doFinal(plainTemp, offset);
    byte[] plain = new byte[offset + last];
    System.arraycopy(plainTemp, 0, plain, 0, plain.length);
    return new String(plain);
}

上面的尝试导致org.bouncycastle.crypto.DataLengthException:解密中的最后一个块不完整。

我在网上搜索示例,但是没有很多示例使用PKCS5 / PKCS7作为填充为CBC提供256位AES的IV数据。

注意:toByte函数使用base64或类似方法将String转换为字节数组。


问题答案:

这应该为您工作:

public String dec(String password, String salt, String encString)
        throws Exception {

    byte[] ivData = toByte(encString.substring(0, 32));
    byte[] encData = toByte(encString.substring(32));

    // get raw key from password and salt
    PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(),
            toByte(salt), 50, 256);
    SecretKeyFactory keyFactory = SecretKeyFactory
            .getInstance("PBEWithSHA256And256BitAES-CBC-BC");
    SecretKeySpec secretKey = new SecretKeySpec(keyFactory.generateSecret(
            pbeKeySpec).getEncoded(), "AES");
    byte[] key = secretKey.getEncoded();

    // setup cipher parameters with key and IV
    KeyParameter keyParam = new KeyParameter(key);
    CipherParameters params = new ParametersWithIV(keyParam, ivData);

    // setup AES cipher in CBC mode with PKCS7 padding
    BlockCipherPadding padding = new PKCS7Padding();
    BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
            new CBCBlockCipher(new AESEngine()), padding);
    cipher.reset();
    cipher.init(false, params);

    // create a temporary buffer to decode into (it'll include padding)
    byte[] buf = new byte[cipher.getOutputSize(encData.length)];
    int len = cipher.processBytes(encData, 0, encData.length, buf, 0);
    len += cipher.doFinal(buf, len);

    // remove padding
    byte[] out = new byte[len];
    System.arraycopy(buf, 0, out, 0, len);

    // return string representation of decoded bytes
    return new String(out, "UTF-8");
}

我假设您实际上是在进行十六进制编码,toByte()因为您的代码对IV使用32个字符(提供了必要的16个字节)。虽然我没有您用于加密的代码,但我确实验证了此代码将提供与您的代码相同的解密输出。



 类似资料:
  • bouncyCastle新手,欢迎提供帮助。我正在尝试使用bounncycastle java API在我的系统上解密一个由第三方加密的文件。它似乎可以很好地解密文件,除了解密文件开头的一团垃圾数据。代码如下 解密的数据块看起来很好,除了开头的“?”??? 用于解密文件的openssl命令在下面的命令中运行良好。事实上,我在解密时使用的是openssl打印的密钥和iv。 加密文件中的openssl

  • 问题内容: 我正在尝试编写一个简单的Java程序,该程序将使用加密纯文本。有上课: 有可能的用法: 我的输出是,但是执行此命令时: 我得到的东西与Java程序()有所不同。可悲的是,我不知道为什么结果不一样,因为我使用相同的算法和相同的键和iv。这是否意味着我的Java程序无法正常运行?任何帮助,将不胜感激。 问题答案: 两种方法都可以正常工作,但是您正在加密不同的事物。 此处的字符串语法()在字

  • 问题内容: 我目前正在使用 256个字节的* 密钥大小来用Java加密文件,但是在搜索时我在stackexchange PKCS#5-PKCS#7填充上发现了它,并提到: * PKCS#5填充是8个字节块大小的PKCS#7填充的子集 所以我想知道 相对于上述配置,性能会更好吗? 正如我们所提到的,我们如何在Java中配置块大小 PKCS#7填充适用于从1到255字节的任何块大小。 我的示例代码是

  • 我希望有一个用C编写的程序,可以在没有openssl这样的大型库的帮助下,用AES-CBC对字符串进行编码/解码。 目标: 使用密码短语对字符串进行编码/解码: 因此,应用程序需要接受3个输入参数。。。 输入字符串(待编码)/或已编码字符串(待解码) 用于编码/解码字符串的密码 编码或解码指示器 我对C语言不熟悉(我可以用C#编码)。 我已经找到了https://github.com/kokke/

  • 我在Erlang中加密AES 256位CBC然后用c代码解密它时遇到了一个问题。而加密/解密在Erlang和C中有效,但不能从一个到另一个。 和 c 代码 我得到的错误是 当我在Erlang中解密时,它可以正常工作,当我在C中加密时,它也可以使用相同的Key和IV。它是否是密码模式不匹配。虽然在我看来是正确的。任何指针都会非常有用。谢谢。 我算出,同样的数据我用C加密和解密,然后进行十六进制转储。

  • 我只想用这3种模式测试openSSL中的AES:128192和256密钥长度,但我解密的文本与我的输入不同,我不知道为什么。此外,当我传递一个巨大的输入长度(比如1024字节)时,我的程序显示。。。我的意见总是一样的,但这并不重要,至少现在是这样。代码如下: 编辑: 当我将输出大小更改为而不是时,我得到了结果: 那么,是否有可能存在Outpus大小和IV大小的问题?它们应该有什么尺寸(AES-CB