Java 使用JNI时CryptUnprotectData返回false

Java 使用JNI时CryptUnprotectData返回false,java,c++,winapi,java-native-interface,Java,C++,Winapi,Java Native Interface,我正在尝试编写一个使用WinAPI CryptprotectData和CryptUnprotectData函数的java应用程序。我正试图通过使用JavaJNI来实现这一点。这是我第一次使用JNI,我在解密数据时遇到了问题。我在Visual Studio中对此进行了调试,发现对CryptUnprotectData的调用返回false,函数返回NULL。我不知道为什么会这样做 代码如下: JNIEXPORT jbyteArray JNICALL Java_Caller_Decrypt(JNIEnv

我正在尝试编写一个使用WinAPI CryptprotectData和CryptUnprotectData函数的java应用程序。我正试图通过使用JavaJNI来实现这一点。这是我第一次使用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;
   }
}

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

此程序中有几个大内存管理错误

1) 调用
env->ReleaseByteArrayElements(字节,数据,0)
然后继续使用数据指针指向的内存内容。此方法可能释放了内存,可能会用内存管理信息覆盖部分数据。这可能解释了
cryptounprotecteddata()
失败的原因。您必须在
CryptUnprotectedData()
之后或在创建数据副本之后调用
env->ReleaseByteArrayElements()

2) 您可以在inData.pbData上调用
LocalFree()。这是指向
env->GetByteArrayElements(字节,NULL)
的指针,由JNIAPI管理。并且必须由JNIAPI发布(您使用
ReleaseByteArrayElements
BTW太早了)

3) 您没有对outData.pbData调用LocalFree(),只有在使用
SetByteArrayRegion

除此之外,我对Windows Crypto API了解不够,无法确定您是否正确调用了它,但在我看来它是正确的

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)));