当前位置: 首页 > 知识库问答 >
问题:

如何使用bouncy castle provider解密SunJCE加密数据

段恩
2023-03-14

我正在尝试用两个不同的服务提供商解密加密的数据。

我使用的加密算法是:AES/CTR/PKCS5Padding(AESCounter Mode with PKCS5Padding)

在从另一端进行加密的同时,他们使用SunJCE作为使用Python的服务提供者。

我正在尝试使用JAVA中的Bouncy Castle作为提供程序来解密加密的数据(来自python)。

我使用了相同的密钥和用于加密的IV。

从我方(解密时)和从另方(加密时)都有局限性。我们都不能改变服务提供商。

请任何人使用Bouncy Castle提供程序解密SunJCE的加密数据。

下面是我使用的代码片段。

java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING", "BC");
// I tried with below line as well. No luck
//Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] textToDecryptInByte = Base64.toBytes(encrypted);
byte[] decrypted = cipher.doFinal(textToDecryptInByte);
return new String(decrypted);

initVector和key是byte[]类型。

javax.crypto.BadPaddingException:在org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$bufferedGenericBlockCipher.DoFinal(源未知,BCO=19)在org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.EngineDoFinal(源未知,BCO=43)在javax.crypto.cipher.DoFinal(源未知,BCO=48)处的pad块损坏

共有1个答案

斜淳
2023-03-14

多年以来,JCE中存在一个问题,即CTR模式下的AES与NOPADDING一起工作,而不管您给出的参数是什么。您可以找到一个日期为2007年的旧线程,其中描述了该问题,并给出了两种解决方案--通常使用NOPADDING(最佳选择),或者在加密端添加自己的填充,在解密端去掉它。

这里是线程的链接(参见David Hook-4 Nov 25 2007;1:06am的回答):http://bouncy-castle.1462172.n4.nabble.com/sunjce-versus-bouncycastle-using-aes-ctr-pkcs5padding-td1465907.html这就是答案:您应该使用NoPadding,除非您真的想要填充-正如Peter所指出的,对于大多数意图和目的,它是完全不必要的,而且NoPadding是Sun JCE正在生成的,不管您要求什么。

这里是一个完整的工作示例程序,它演示了“错误的”填充--在加密端我在JCE中使用PKCS5Padding,而在BC中使用NOPADDING。通过将AesCtrNoPaddingDecryptBC更改为aesctrnoPaddingDecrypt,可以将解密更改为JCE。

/*
* Herkunft/Origin: http://javacrypto.bplaced.net/
* Programmierer/Programmer: Michael Fehr
* Copyright/Copyright: frei verwendbares Programm (Public Domain)
* Copyright: This is free and unencumbered software released into the public domain.
* Lizenttext/Licence: <http://unlicense.org>
* getestet mit/tested with: Java Runtime Environment 8 Update 191 x64
* Datum/Date (dd.mm.jjjj): 19.11.2019 
* Funktion: verschlüsselt einen string im aes ctr modus pkcs5padding mit jce
*           entschlüsselt einen string im aes ctr modus nopadding mit bc
* Function: encrypts a string using aes ctr modus with pkcs5padding using JCE
*           decrypts a string using aes ctr modus nopadding using BC
*
* Hinweis: die JCE arbeitet immer im NOPADDING-Modus, egal was alternativ angegeben ist ! 
* Notice: JCE works always in NOPADDING mode and not in PKCS5PADDING even if named !
* Link: http://bouncy-castle.1462172.n4.nabble.com/SunJCE-versus-BouncyCastle-using-AES-CTR-PKCS5Padding-td1465907.html
* 
* Sicherheitshinweis/Security notice
* Die Programmroutinen dienen nur der Darstellung und haben keinen Anspruch auf eine 
* korrekte Funktion, insbesondere mit Blick auf die Sicherheit ! 
* Prüfen Sie die Sicherheit bevor das Programm in der echten Welt eingesetzt wird.
* The program routines just show the function but please be aware of the security part - 
* check yourself before using in the real world !
*/

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class AesCtrNoPaddingRandomString {

    public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
            InvalidAlgorithmParameterException, NoSuchProviderException {
        System.out.println("AES mode CTR PKCS5PADDING or NOPADDING ?");

        Security.addProvider(new BouncyCastleProvider());

        String plaintextString = "HelloWorld12345"; // hier 15 zeichen
        String decryptedtextString = ""; // enthält später den entschlüsselten text
        final byte[] keyByte = "12345678901234567890123456789012".getBytes("UTF-8"); // 32 byte
        // random iv, 16 bytes long
        final byte[] initvectorByte = new byte[16];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(initvectorByte);

        byte[] plaintextByte = plaintextString.getBytes("UTF-8");
        byte[] ciphertextByte = null;
        byte[] decryptedtextByte = null;

        // encryption
        ciphertextByte = AesCtrPkcs5PaddingEncrypt(plaintextByte, keyByte, initvectorByte);
        // decryption with bouncy castle
        decryptedtextByte = AesCtrNoPaddingDecryptBC(ciphertextByte, keyByte, initvectorByte);
        // decrypted text
        decryptedtextString = new String(decryptedtextByte, "UTF-8");
        // output
        System.out.println("");
        System.out.println("keyByte (hex)          :" + printHexBinary(keyByte));
        System.out.println("initvectorByte (hex)   :" + printHexBinary(initvectorByte));
        System.out.println("plaintextString        :" + plaintextString);
        System.out.println("plaintextByte (hex)    :" + printHexBinary(plaintextByte));
        System.out.println("= = = Encryption AES/CTR/PKCS5PADDING JCE = = =");
        System.out.println("ciphertextByte (hex)   :" + printHexBinary(ciphertextByte));
        System.out.println("= = = Decryption AES/CTR/NOPADDING BC = = =");
        System.out.println("decryptedtextByte (hex):" + printHexBinary(decryptedtextByte));
        System.out.println("decryptedtextString    :" + decryptedtextString);
    }

    public static byte[] AesCtrPkcs5PaddingEncrypt(byte[] plaintextByte, byte[] keyByte, byte[] initvectorByte)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        byte[] ciphertextByte = null;
        SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
        IvParameterSpec ivKeySpec = new IvParameterSpec(initvectorByte);
        Cipher aesCipherEnc = Cipher.getInstance("AES/CTR/PKCS5PADDING");
        aesCipherEnc.init(Cipher.ENCRYPT_MODE, keySpec, ivKeySpec);
        ciphertextByte = aesCipherEnc.doFinal(plaintextByte);
        return ciphertextByte;
    }

    public static byte[] AesCtrNoPaddingDecryptBC(byte[] ciphertextByte, byte[] keyByte, byte[] initvectorByte)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
            NoSuchProviderException {
        byte[] decryptedtextByte = null;
        SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
        IvParameterSpec ivKeySpec = new IvParameterSpec(initvectorByte);
        Cipher aesCipherDec = Cipher.getInstance("AES/CTR/NOPADDING", "BC");
        aesCipherDec.init(Cipher.DECRYPT_MODE, keySpec, ivKeySpec);
        decryptedtextByte = aesCipherDec.doFinal(ciphertextByte);
        return decryptedtextByte;
    }

    public static byte[] AesCtrNoPaddingDecrypt(byte[] ciphertextByte, byte[] keyByte, byte[] initvectorByte)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        byte[] decryptedtextByte = null;
        SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
        IvParameterSpec ivKeySpec = new IvParameterSpec(initvectorByte);
        Cipher aesCipherDec = Cipher.getInstance("AES/CTR/NOPADDING");
        aesCipherDec.init(Cipher.DECRYPT_MODE, keySpec, ivKeySpec);
        decryptedtextByte = aesCipherDec.doFinal(ciphertextByte);
        return decryptedtextByte;
    }

    public static String printHexBinary(byte[] bytes) {
        final char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
}

这是控制台输出:

AES mode CTR PKCS5PADDING or NOPADDING ?

keyByte (hex)          :3132333435363738393031323334353637383930313233343536373839303132
initvectorByte (hex)   :FA61736967A9DE5E86F7ED8F345E0C4D
plaintextString        :HelloWorld12345
plaintextByte (hex)    :48656C6C6F576F726C643132333435
= = = Encryption AES/CTR/PKCS5PADDING JCE = = =
ciphertextByte (hex)   :5385A8F0BEC7FAC14FCC7AA2B04D9B
= = = Decryption AES/CTR/NOPADDING BC = = =
decryptedtextByte (hex):48656C6C6F576F726C643132333435
decryptedtextString    :HelloWorld12345
 类似资料:
  • 我正在尝试使用KMS和AWS加密SDK加密数据。查看AWS文档中提供的示例,似乎没有地方可以显式设置数据键。 使用由KMS生成的数据密钥使用AWS加密SDK加密数据的推荐方法是什么?

  • 问题内容: 我正在连接一个旧的Java应用程序(无法更改该应用程序),该应用程序正在使用AES加密数据。这是原始Java代码如何实例化AES密码: 我是C / C ++开发人员,而不是Java,但是从我可以看出来的传统Java代码中,既没有指定模式,也没有指定初始化向量。有人偶然知道默认情况下将使用什么Java,因为未指定它? 我们需要新的C / C ++应用程序来解密Java加密的数据。但是我不

  • 问题内容: 我正在使用ExtJS框架。我在 JavaScript中 有MD5函数来加密某些JSON。我的后端使用Java,所以我想知道如何使用 Java 解密MD5 Javascript加密? 这是我正在使用的MD5函数的JS等效项: 问题答案: MD5是 哈希 (即单向转换),因此您无法对其进行解密。您可以将已知哈希与从明文计算出的哈希进行比较,以验证输入的有效性。Java已经为此内置了库。我在

  • 问题内容: 我需要用openssl生成的和密钥替换从Unix到Java代码的加密和解密步骤 我生成密钥 我在Unix中使用键(我需要在Java中执行) 这是我的尝试 但它不起作用,PKCS8EncodedKeySpec / X509EncodedKeySpec不正确…但是我不知道该放什么 问题答案: 我认为您在读取PEM文件时遇到问题。JPA不直接支持PEM格式。您有两种选择,要么将它们转换为DE

  • 我正在用SecKeyEncryptedData在ojb-c中加密,并试图用javax.cipher在Java中解密,但遇到了一个问题。 我最近开始做长块,需要使用对称加密,使用AES密钥加密,使用非对称密钥对加密。我解码有问题。 obj-c:java: 解码显然失败了。 所以我的问题分为两个部分。 null

  • 问题内容: 我目前是一名学生,并且正在学习PHP,我正在尝试对PHP中的数据进行简单的加密/解密。我进行了一些在线研究,其中一些非常令人困惑(至少对我而言)。 这是我想做的事情: 我有一个包含这些字段 (用户ID,Fname,Lname,Email,Password)的表 我要拥有的是先将所有字段加密,然后再解密(如果没有任何加密算法,是否可以用于加密/解密) 我想学习的另一件事是如何创建一种与优