0

我正在尝试编写一个使用 WinAPI CryptprotectData 和 CryptUnprotectData 函数的 java 应用程序。我正在尝试通过使用 java JNI 来实现这一点。这是我第一次使用 JNI,我在解密数据时遇到了问题。我在 Visual Studio 中对此进行了调试,发现对 CryptUnprotectData 的调用返回 false 并且函数返回 NULL。我不知道它为什么这样做。

这是代码:

JNIEXPORT jbyteArray JNICALL Java_Caller_Decrypt(JNIEnv * env, jobject obj, jbyteArray bytes)
{
   int len = env->GetArrayLength(bytes);
   jbyte * data = env->GetByteArrayElements(bytes,NULL);
   env->ReleaseByteArrayElements(bytes, data, 0);
   DATA_BLOB inData = {len, reinterpret_cast<unsigned char *>(data)};
   DATA_BLOB outData = {0,NULL};

   if(CryptUnprotectData(&inData,NULL,NULL,NULL,NULL,0,&outData))
   {
       LocalFree(inData.pbData);
       jbyteArray buff= env->NewByteArray(len);
       env->SetByteArrayRegion(buff,0,len,reinterpret_cast<jbyte *>(outData.pbData));
       return buff;
   }
   else
   {
       return NULL;
   }
}

这是相关的java代码:

String password = "Password";
Caller c = new Caller();
System.out.println("Password");
byte[] buffer = c.Encrypt(password.getBytes());
System.out.println("Encrypted: " + new String(buffer));
System.out.println("Decrypted: " + new String(c.Decrypt(buffer)));

我不知道为什么 CryptUnprotectData 函数返回 false。自从我使用 c++ 并迷上了 java 已经有一年了,所以我有点生疏了,所以我可能只是错过了一些东西,但我想知道我是否只是错过了一步,因为这是我第一次使用JNI。任何帮助/建议将不胜感激!

4

1 回答 1

2

这个程序有几个大的内存管理错误。

1)你调用env->ReleaseByteArrayElements(bytes, data, 0)然后继续使用数据指针指向的内存内容。这个方法可能已经释放了它的内存,可能用内存管理信息覆盖了它的部分数据。这可能解释了CryptUnprotectedData()失败的原因。您必须在制作数据副本env->ReleaseByteArrayElements()之后或之后致电。CryptUnprotectedData()

2) 你调用LocalFree()inData.pbData。这是指向 的指针,env->GetByteArrayElements(bytes,NULL)由 JNI API 管理。ReleaseByteArrayElements并且必须由 JNI API 发布(您使用BTW做得太早了)。

3) 您没有在 outData.pbData 上调用 LocalFree(),只有在使用复制数据后才应该这样做SetByteArrayRegion

否则,我对 Windows Crypto API 的了解不够,无法确定您是否正确调用它,但它看起来对我来说是正确的。

于 2013-02-03T02:33:25.983 回答