首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用bouncy城堡提供程序解密SunJCE加密数据

如何使用bouncy城堡提供程序解密SunJCE加密数据
EN

Stack Overflow用户
提问于 2019-11-18 15:14:11
回答 1查看 1.2K关注 0票数 0

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

我使用的加密算法是:AES/CTR/PKCS5PADDING (带有PKCS5Padding的AES计数器模式)

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

我正在尝试使用Bouncy城堡作为Java的提供者来解密加密的数据(来自python)。

我使用了同样的密钥和IV,这是用来加密的。

从我这边(解密时)和另一边(加密时)都有限制。我们都不能改变服务提供商.

Java的默认提供程序是SunJCE,因为我使用的是自定义的JVM版本,它不包含SunJCE库。如果我将SunJCE配置为提供程序(在不同的机器上尝试使用完整版本的Java ),我就能够成功地解密相同的加密数据。所以我觉得,这个代码没有其他问题。

请任何人帮助解密SunJCE的加密数据使用Bouncy城堡提供商。

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

代码语言:javascript
复制
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[]类型。

我解密时得到的异常:

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块

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-18 23:20:42

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

下面是到线程的链接(参见2007年11月25日大卫·胡克-4日的答案;凌晨1点06分):http://bouncy-castle.1462172.n4.nabble.com/SunJCE-versus-BouncyCastle-using-AES-CTR-PKCS5Padding-td1465907.html --这就是答案:你应该使用NoPadding,除非你真的想要填充物--就像Peter指出的那样,它是完全不必要的,而NoPadding是Sun正在生产的东西,不管您请求的是什么__。

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

代码语言:javascript
复制
/*
* 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);
    }
}

这是控制台输出:

代码语言:javascript
复制
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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58917639

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档