2013-02-03 23 views
0

我正在嘗試編寫一個使用WinAPI CryptprotectData和CryptUnprotectData函數的java應用程序。我正在嘗試通過使用java JNI來完成此操作。這是我第一次使用JNI,並且在解密數據時遇到了問題。我在Visual Studio中調試了這個,發現對CryptUnprotectData的調用返回false,並且函數返回NULL。我不知道爲什麼這樣做。使用JNI時CryptUnprotectData返回false

下面是代碼:

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。任何幫助/建議將不勝感激!

回答

2

這個程序有幾個大的內存管理錯誤。

1)您調用env->ReleaseByteArrayElements(bytes, data, 0),然後繼續使用數據指針指向的內存內容。這種方法可能釋放了內存,可能會用內存管理信息覆蓋部分數據。這可能解釋了爲什麼CryptUnprotectedData()失敗。您必須在CryptUnprotectedData()之後或在您複製數據後致電env->ReleaseByteArrayElements()

2)您可以在inData.pbData上調用LocalFree()。這是指向env->GetByteArrayElements(bytes,NULL)的指針,由JNI API管理。並且必須通過JNI API發佈(您過早使用ReleaseByteArrayElements)。

3)你沒僅用SetByteArrayRegion

否則複製數據後,上outData.pbData調用LocalFree(),你應該做的,我不知道足夠有關Windows加密API肯定知道,如果你說得對,但它看起來是對的。

+0

謝謝!我不知道我是如何錯過的,現在起作用 – user1036756