我已经为此苦苦挣扎了几天。我需要使用一个带有加密参数的 API。该 API 是用 C# 编写的。请求的加密如下:
算法:AES
加密方式:CBC
填充模式:PKCS7
区 block 大小:128
key 大小:256
Key: String --> 通过将提供的字符串转换为大小为 32 的字节数组来生成 key :Encoding.ASCII.GetBytes(…)。 API 声明该字符串是由他们使用字符串的 MD5 哈希函数生成的。
IV:IV 数组是通过将提供的字符串转换为大小为 16 的字节数组而生成的:Encoding.ASCII.GetBytes(…)。
加密字符串的表示形式:Base64
在搜索并尝试了网上建议的很多方法之后,我仍然无法生成相同的加密值(特别是默认情况下不支持 PKCS7,而 PKCS5 应该可以正常工作,但事实并非如此)。以下是我尝试过的一些事情:
1)使用充气城堡 jar 来使用PKCS7
2) 添加 JCE 合规性,以便能够消除对 key 和 block 大小的限制。
与他们联系后,他们向我发送了一个正在运行的 android 代码片段(如果我在纯 java 8 中运行,则会提示提供程序(NoSuchAlgorithmException:找不到任何支持 AES/CBC/PKCS7Padding 的提供程序)):
public static String encrypt(String value) {
String plainText = value;
String escapedString;
try {
byte[] key = ENCRYPT_KEY.getBytes("UTF-8");
byte[] ivs = ENCRYPT_IV.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivs);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, paramSpec);
escapedString = Base64.encodeToString(cipher.doFinal(plainText.getBytes("UTF-8")), Base64.DEFAULT).trim();
return escapedString;
} catch (Exception e) {
e.printStackTrace();
return value;
}
}
请提供任何帮助,我们将不胜感激。
这是我尝试过的代码片段:
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;
}
}
最佳答案
Java Cipher package仅支持使用 AES/CBC/PKCS5Padding
进行 PKCS#7 填充。这不是一个好的命名,因为 PKCS#5 填充支持 8 字节 block 大小,而 DES 和 PKCS#7 支持最多 255 字节。对于 Java 使用此;
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
对于最现代的分组密码来说,#5 和 #7 不可互换,因为 AES 是 128 位分组密码。请参阅 Crypto.StackExchange 上的问题。
并且,用于使用 256 位 key 大小的 AES;
Java 标准密码库限制为 128 位 key 大小。你必须去下载Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6
关于使用 CBC 和 PKCS7Padding 的 Java AES 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53139243/