使用CBC和PKCS7Padding的Java AES加密
我已经为此挣扎了几天了。我需要使用一个接受加密参数的API。API是用C#编写的。请求的加密如下所示:使用CBC和PKCS7Padding的Java AES加密,java,encryption,aes,pkcs#7,Java,Encryption,Aes,Pkcs#7,我已经为此挣扎了几天了。我需要使用一个接受加密参数的API。API是用C#编写的。请求的加密如下所示: 算法:AES 密码模式:CBC 填充模式:PKCS7 块大小:128 密钥大小:256 Key:String-->通过将提供的字符串转换为大小为32:Encoding.ASCII.GetBytes(…)的字节数组来生成密钥。API声明字符串是由它们使用字符串的MD5哈希函数生成的 IV:IV数组是通过将提供的字符串转换为大小为16:Encoding.ASCII.GetBytes(…)的字节数
算法:AES
密码模式:CBC
填充模式:PKCS7
块大小:128
密钥大小:256 Key:String-->通过将提供的字符串转换为大小为32:Encoding.ASCII.GetBytes(…)的字节数组来生成密钥。API声明字符串是由它们使用字符串的MD5哈希函数生成的 IV:IV数组是通过将提供的字符串转换为大小为16:Encoding.ASCII.GetBytes(…)的字节数组生成的 加密字符串的表示形式:Base64
在搜索和尝试了这么多在线建议的内容之后,我仍然无法生成相同的加密值(特别是默认情况下不支持PKCS7,PKCS5应该是相同的,但它不是)。以下是我尝试过的一些事情:
1) 使用bouncy castle jar来使用PKCS7
2) 添加JCE合规性,以消除对键和块大小的限制 联系他们后,他们向我发送了一个运行正常的android代码段(如果我在纯java 8中运行,会抱怨提供程序(NoSuchAlgorithmException:找不到任何支持AES/CBC/PKCS7Padding的提供程序)): 如果您有任何帮助,我们将不胜感激 以下是我尝试的代码片段:
package com.melhem.TestJava;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Base64;
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;
public class StringFunc {
final static String key = "API_KEY_32_CHARs";
final static String iv = "API_IV_16_CHARs";
final static String algorithm = "AES/CBC/PKCS7Padding";
private static Cipher cipher = null;
private static SecretKeySpec skeySpec = null;
private static IvParameterSpec ivSpec = null;
public static void main(String[] args) {
System.out.println(encrypt("STRING_TO_ENCODE"));
}
private static void setUp(){
try{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
skeySpec = new SecretKeySpec(key.getBytes("ASCII"), "AES");
ivSpec = new IvParameterSpec(iv.getBytes("ASCII"));
cipher = Cipher.getInstance(algorithm);
}catch(NoSuchAlgorithmException | NoSuchPaddingException ex){
ex.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String encrypt(String str){
try{
// Integer strL = (int) Math.ceil(str.length() / 8.0);
// Integer strB = strL*8;
// str = padRight(str, ' ', strB);
setUp();
try {
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec);
System.out.println("Block size: " + cipher.getBlockSize() * 8);
System.out.println("Algorithm name: " + cipher.getAlgorithm());
System.out.println("Key size: " + skeySpec.getEncoded().length * 8);
} catch (InvalidAlgorithmParameterException ex) {
ex.printStackTrace();
return "";
}
byte[] enc = cipher.doFinal(str.getBytes("ASCII"));
String s = new String(Base64.getEncoder().encode(enc));
s = s.replace("+", "__plus__");
s = s.replace("/", "__slash__");
return s;
}catch(InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex){
ex.printStackTrace();
return "";
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";
}
}
public static String padRight(String msg, char x, int l) {
String result = "";
if (!msg.isEmpty()) {
for (int i=0; i<(l-msg.length()); i++) {
result = result + x;
}
result = msg + result;
}
return result;
}
}
package com.melhem.TestJava;
导入java.io.UnsupportedEncodingException;
导入java.security.invalidalgorithParameterException;
导入java.security.InvalidKeyException;
导入java.security.NoSuchAlgorithmException;
导入java.security.security;
导入java.util.Base64;
导入javax.crypto.BadPaddingException;
导入javax.crypto.Cipher;
导入javax.crypto.IllegalBlockSizeException;
导入javax.crypto.NoSuchPaddingException;
导入javax.crypto.spec.IvParameterSpec;
导入javax.crypto.spec.SecretKeySpec;
公共类StringFunc{
最终静态字符串key=“API\u key\u 32\u CHARs”;
最终静态字符串iv=“API_iv_16_CHARs”;
最终静态字符串算法=“AES/CBC/PKCS7Padding”;
私有静态密码=null;
私有静态SecretKeySpec skeySpec=null;
私有静态IvParameterSpec ivSpec=null;
公共静态void main(字符串[]args){
System.out.println(加密(“字符串编码”);
}
私有静态无效设置(){
试一试{
addProvider(新org.bouncycastle.jce.provider.BouncyCastleProvider());
skeySpec=newsecretkeyspec(key.getBytes(“ASCII”),“AES”);
ivSpec=新的IvParameterSpec(iv.getBytes(“ASCII”);
cipher=cipher.getInstance(算法);
}捕获(NoSuchAlgorithmException | NoSuchPaddingException ex){
例如printStackTrace();
}捕获(不支持的编码异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
公共静态字符串加密(字符串str){
试一试{
//整数strL=(int)Math.ceil(str.length()/8.0);
//整数strB=strL*8;
//str=padRight(str',,strB);
设置();
试一试{
cipher.init(cipher.ENCRYPT_模式,skeySpec,ivSpec);
System.out.println(“块大小:“+cipher.getBlockSize()*8”);
System.out.println(“算法名称:+cipher.getAlgorithm());
System.out.println(“键大小:+skeySpec.getEncoded().length*8);
}捕获(无效算法参数异常){
例如printStackTrace();
返回“”;
}
byte[]enc=cipher.doFinal(str.getBytes(“ASCII”);
字符串s=新字符串(Base64.getEncoder().encode(enc));
s=s。替换(“+”,“_加上“);
s=s。替换(“/”,“_斜杠”;
返回s;
}捕获(InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex){
例如printStackTrace();
返回“”;
}捕获(不支持的编码异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
返回“”;
}
}
公共静态字符串padRight(字符串msg、字符x、int l){
字符串结果=”;
如果(!msg.isEmpty()){
对于(int i=0;iJava仅支持PKCS#7填充和AES/CBC/PKCS5Padding
。这不是一个好的命名,因为PKCS#5填充支持8字节的块大小,而DES和PKCS#7最多支持255字节。对于Java,请使用此选项
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
#5和#7对于大多数现代分组密码来说是不可互换的,因为AES是128位分组密码。请参阅上的问题
以及,用于使用256位密钥大小的AES
Java标准密码库限制为128位密钥大小。您必须去下载JavaThx kelalaka..我尝试过,但它抛出了无效的算法参数异常:错误的IV长度:必须是8字节长..此外,API要求IV的大小为16字节,算法为AES是的,我以前尝试过使用它,因为它们是可互换的它会产生API无法解密的不同值。您认为这是否意味着API所有者在加密后会执行额外的步骤,或者问题是使用PKCS5Padding?我已经从JCE添加了两个JAR,但问题仍然存在。这不是因为它在添加JCE JAR后抱怨密钥大小,而是它提供了错误的值。您忘记了doFi吗nal?如果您使用最新版本的Java 8或更高版本,您不再需要无限强度管辖权策略文件,它们已经包含在内。这里是您问题中缺少的内容:您声称自己尝试过但不起作用的Java代码。好吧,此代码不会产生您声称在其他地方遇到的异常。请仔细阅读。MCVE是解决stackoverflow问题的方法。您的问题与p无关
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");