如何使用充气城堡提供商解密 SunJCE 加密数据
how to decrypt SunJCE encrypted data using bouncy castle provider
我正在尝试通过两个不同的服务提供商来解密加密数据。
我使用的加密算法是:AES/CTR/PKCS5PADDING(AES Counter Mode with PKCS5Padding)
在从另一端进行加密时,他们使用 SunJCE 作为使用 Python 的服务提供商。
我正在尝试使用 Bouncy Castle 作为 Java 中的提供商解密加密数据(来自 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)
在 org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(未知来源,bco=43)
在 javax.crypto.Cipher.doFinal(来源不明,bco=48)
JCE 中存在一个问题,因为多年来 AES 在 CTR 模式下与 NOPADDING 一起工作,无论您提供什么参数。您可以找到一个日期为 2007 年的旧线程,其中描述了问题并给出了两个解决方案 - 通常使用 NOPADDING(最佳选择)或在加密端添加您自己的填充并在解密端删除它。
这是线程的 link(参见 David Hook-4 2007 年 11 月 25 日的回答;1:06am):
http://bouncy-castle.1462172.n4.nabble.com/SunJCE-versus-BouncyCastle-using-AES-CTR-PKCS5Padding-td1465907.html
这就是答案:不过你应该使用 NoPadding,除非你真的想要填充 - 正如彼得在大多数意图和目的中所指出的那样,它完全是
不必要的,并且 NoPadding 是 Sun JCE 所产生的,无论
您要求的.
这是一个完整的工作示例程序,演示了 "wrong" 填充 - 在加密方面,我在 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
我正在尝试通过两个不同的服务提供商来解密加密数据。
我使用的加密算法是:AES/CTR/PKCS5PADDING(AES Counter Mode with PKCS5Padding)
在从另一端进行加密时,他们使用 SunJCE 作为使用 Python 的服务提供商。
我正在尝试使用 Bouncy Castle 作为 Java 中的提供商解密加密数据(来自 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) 在 org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(未知来源,bco=43) 在 javax.crypto.Cipher.doFinal(来源不明,bco=48)
JCE 中存在一个问题,因为多年来 AES 在 CTR 模式下与 NOPADDING 一起工作,无论您提供什么参数。您可以找到一个日期为 2007 年的旧线程,其中描述了问题并给出了两个解决方案 - 通常使用 NOPADDING(最佳选择)或在加密端添加您自己的填充并在解密端删除它。
这是线程的 link(参见 David Hook-4 2007 年 11 月 25 日的回答;1:06am): http://bouncy-castle.1462172.n4.nabble.com/SunJCE-versus-BouncyCastle-using-AES-CTR-PKCS5Padding-td1465907.html 这就是答案:不过你应该使用 NoPadding,除非你真的想要填充 - 正如彼得在大多数意图和目的中所指出的那样,它完全是 不必要的,并且 NoPadding 是 Sun JCE 所产生的,无论 您要求的.
这是一个完整的工作示例程序,演示了 "wrong" 填充 - 在加密方面,我在 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