AES/CBC/PKCS5Padding JAVA 和 JNI 中的不同结果
AES/CBC/PKCS5Padding different results in JAVA and JNI
我有一个 Java 加密代码,如下所示
byte[] encrypt(byte[] clearData) {
byte[] passwordKey = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,0x0f};
byte[] rawSecretKey = new byte[]{0x34, (byte) 0xA4, 0x16, 0x09, 0x77, (byte) 0x85, (byte) 0xB4, 0x31,
0x75, 0x12, (byte) 0x92, (byte) 0xDD, (byte) 0xCA, 0x15, (byte) 0xAB, (byte) 0xBA};
secretKey = new SecretKeySpec(passwordKey, "AES");
ivParameterSpec = new IvParameterSpec(rawSecretKey);
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
byte[] encryptedData;
encryptedData = aesCipher.doFinal(clearData);
return encryptedData;
}
我必须将此代码移植到 JNI。我已经构建了 openssl 并制作了如下所示的 JNI 包装器函数:
JNIEXPORT jbyteArray JNICALL Java_axon_voiceassistant_utils_JNIUtils_getcr(JNIEnv *env, jclass cls, jbyteArray srcData)
{
int srcLen=env->GetArrayLength(srcData);
unsigned char* indata = new unsigned char[srcLen];
env->GetByteArrayRegion (srcData, 0, srcLen, reinterpret_cast<jbyte*>(indata));
const unsigned char ukey[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,0x0f};
unsigned char iv [] = {0x34, 0xA4, 0x16, 0x09, 0x77,0x85, 0xB4, 0x31,
0x75, 0x12, 0x92,0xDD, 0xCA, 0x15, 0xAB, 0xBA};
const size_t encs_length = ((srcLen + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_data[encs_length];
memset(enc_data, 0, sizeof(enc_data));
AES_KEY key;
memset(&key, 0, sizeof(AES_KEY));
AES_set_encrypt_key(ukey, 128, &key);
AES_cbc_encrypt(indata, enc_data, srcLen, &key, iv, AES_ENCRYPT);
jbyteArray bArray = env->NewByteArray(encs_length);
jboolean isCopy;
void *enc_copy = env->GetPrimitiveArrayCritical((jarray)bArray, &isCopy);
memcpy(enc_copy, enc_data, encs_length);
env->ReleasePrimitiveArrayCritical( bArray, enc_copy, 0);
return bArray;
}
但是我在 JNI 版本上得到的结果与在 Java 版本上的结果不同。可能是什么问题?
您已在 JNI 代码中对明文进行零填充:
const size_t encs_length = ((srcLen + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_data[encs_length];
memset(enc_data, 0, sizeof(enc_data));
但是您的 Java 代码使用的是 PKCS #7 填充。其中一项需要更改。
注意:我认为(根据一些研究)AES_cbc_encrypt
默认情况下会进行零填充,因此您自己完成此操作的步骤可能是多余的。
要解决此问题,请在您的 JNI 代码中手动实现 PKCS #7 填充(实际上非常简单),或者考虑使用更高级的 EVP 函数,它了解如何填充数据。
我有一个 Java 加密代码,如下所示
byte[] encrypt(byte[] clearData) {
byte[] passwordKey = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,0x0f};
byte[] rawSecretKey = new byte[]{0x34, (byte) 0xA4, 0x16, 0x09, 0x77, (byte) 0x85, (byte) 0xB4, 0x31,
0x75, 0x12, (byte) 0x92, (byte) 0xDD, (byte) 0xCA, 0x15, (byte) 0xAB, (byte) 0xBA};
secretKey = new SecretKeySpec(passwordKey, "AES");
ivParameterSpec = new IvParameterSpec(rawSecretKey);
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
byte[] encryptedData;
encryptedData = aesCipher.doFinal(clearData);
return encryptedData;
}
我必须将此代码移植到 JNI。我已经构建了 openssl 并制作了如下所示的 JNI 包装器函数:
JNIEXPORT jbyteArray JNICALL Java_axon_voiceassistant_utils_JNIUtils_getcr(JNIEnv *env, jclass cls, jbyteArray srcData)
{
int srcLen=env->GetArrayLength(srcData);
unsigned char* indata = new unsigned char[srcLen];
env->GetByteArrayRegion (srcData, 0, srcLen, reinterpret_cast<jbyte*>(indata));
const unsigned char ukey[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,0x0f};
unsigned char iv [] = {0x34, 0xA4, 0x16, 0x09, 0x77,0x85, 0xB4, 0x31,
0x75, 0x12, 0x92,0xDD, 0xCA, 0x15, 0xAB, 0xBA};
const size_t encs_length = ((srcLen + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_data[encs_length];
memset(enc_data, 0, sizeof(enc_data));
AES_KEY key;
memset(&key, 0, sizeof(AES_KEY));
AES_set_encrypt_key(ukey, 128, &key);
AES_cbc_encrypt(indata, enc_data, srcLen, &key, iv, AES_ENCRYPT);
jbyteArray bArray = env->NewByteArray(encs_length);
jboolean isCopy;
void *enc_copy = env->GetPrimitiveArrayCritical((jarray)bArray, &isCopy);
memcpy(enc_copy, enc_data, encs_length);
env->ReleasePrimitiveArrayCritical( bArray, enc_copy, 0);
return bArray;
}
但是我在 JNI 版本上得到的结果与在 Java 版本上的结果不同。可能是什么问题?
您已在 JNI 代码中对明文进行零填充:
const size_t encs_length = ((srcLen + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_data[encs_length];
memset(enc_data, 0, sizeof(enc_data));
但是您的 Java 代码使用的是 PKCS #7 填充。其中一项需要更改。
注意:我认为(根据一些研究)AES_cbc_encrypt
默认情况下会进行零填充,因此您自己完成此操作的步骤可能是多余的。
要解决此问题,请在您的 JNI 代码中手动实现 PKCS #7 填充(实际上非常简单),或者考虑使用更高级的 EVP 函数,它了解如何填充数据。