只是想知道为什么在Java和C中加密的相同纯文本不会生成相同的密文。 对于DES algo,我注意到了
输入text = "text", key = "test"
C密文len = 24
Java生成密文len = 8
对于256Bit AES,我注意到了类似的差异
C密文len = 32
Java生成密文len = 16
这是我的“C”代码
char* enc(const char* text, const char* keyStr)
{
EVP_CIPHER_CTX ctx;
unsigned char key[32] = {0};
unsigned char iv[16] = {0};
unsigned char in[16] = {0};
unsigned char out[32]; /* at least one block longer than in[] */
memset(out, 0, 32);
int outlen1, outlen2;
memcpy(in, text, strlen(text));
memcpy(key, keyStr, strlen(keyStr));
EVP_EncryptInit(&ctx, EVP_aes_256_cbc(), key, iv);
EVP_EncryptUpdate(&ctx, out, &outlen1, in, sizeof(in));
EVP_EncryptFinal(&ctx, out + outlen1, &outlen2);
char* ret = (char*)malloc(outlen1 + outlen2+1);
memset(ret, 0, outlen1 + outlen2+1);
memcpy(ret, out, outlen1 + outlen2);
EVP_CIPHER_CTX_cleanup(&ctx);
return ret;
}
这是“Java”代码
public static byte[] enc(byte[] input, byte[] keyStr){
byte[] output = null;
try {
byte[] newKey = getByteArrays(keyStr, 0, 32);
SecretKey secretKey = new SecretKeySpec(newKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
String ivStr = "";
byte[] ivKey = getByteArrays(ivStr.getBytes("UTF-8"), 0, 16);
IvParameterSpec ips = new IvParameterSpec(ivKey);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ips, null);
output = cipher.doFinal(input);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return output;
}
我有使用C加密的条目列表,我想用Java解密这些条目。
更新
以下更新有助于获得相同的长度,包括'C'和'JAVA'
EVP_EncryptUpdate(& ctx,out,& outlen1,in,strlen(text));
不只是想知道为什么“C”和“JAVA”返回的密文对于相同的文本和密钥是不同的,我希望它们是相同的
答案 0 :(得分:1)
C代码输出32个字节的密文的原因是因为你在输入>>将输入字符串填充到加密函数之前填充输入字符串。
在这一行:
EVP_EncryptUpdate(&ctx, out, &outlen1, in, sizeof(in));
该函数不知道您用零填充数据。由于sizeof(in)
为16,因此明文的长度需要16。使用PKCS5填充(和AES),16个字节将填充到32个字节。
在Java代码中,您没有手动填充输入,只是直接将其传递给加密函数。因此,加密函数将您的明文大小视为4个字节,使用PKCS5填充将其填充为16。
所以你的解决方案很简单:不要在C代码中手动填充输入。只需将明文直接传递给EVP_EncryptUpdate
即可。它已经设计用于处理未填充的明文。