繁体   English   中英

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

[英]how to decrypt SunJCE encrypted data using bouncy castle provider

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

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

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

我正在尝试使用Bouncy Castle作为 Java 中的 Provider 解密加密数据(来自 python)。

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

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

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

请任何人帮助使用 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)的垫块损坏。 javax.crypto.Cipher.doFinal(未知来源,bco=48)处的engineDoFinal(未知来源,bco=43)

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 ,除非你真的想要填充 - 正如彼得已经指出的大多数意图和目的,它是完全没有必要的,而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);
    }
}

那是控制台output:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM