2012-11-12 219 views
1

我試圖做本地代碼C.加密AES加密/解密的工作,但,當我嘗試解密字符串。它不會以原始字符串結尾。這裏是一個不基於模式PARAM加密/ decrpt的JNI方法:Android的JNI字符串加密/解密

jbyteArray Java_com_example_hellojni_HelloJni_encrypt(JNIEnv* env, 
             jobject this, 
             jbyteArray srcData, 
             jint mode) 
{ 
    // get length of bytes 
    int srcLen=(*env)->GetArrayLength(env,srcData); 

    //convert jbyteArray to byte [] 
    jbyte data[srcLen]; 
    (*env)->GetByteArrayRegion(env, srcData, 0, srcLen, data); 
    (*env)->ReleaseByteArrayElements(env, srcData,data , 0); 


    unsigned char* indata=(unsigned char*)data; 
    const unsigned char ukey[] = { 'H','A','R','D','C','O','D','E','D',' ','K','E','Y','1','2','3'}; 
    unsigned char *outdata = NULL; 
    outdata = malloc(srcLen); 
    AES_KEY key; 
    memset(&key, 0, sizeof(AES_KEY)); 

if(mode == AES_ENCRYPT) 
    AES_set_encrypt_key(ukey, 128, &key); 
else 
    AES_set_decrypt_key(ukey, 128, &key); 

AES_ecb_encrypt(indata, outdata, &key, mode); 

jbyteArray bArray = (*env)->NewByteArray(env, srcLen); 
jboolean isCopy; 
void *decrypteddata = (*env)->GetPrimitiveArrayCritical(env, (jarray)bArray, &isCopy); 
memcpy(decrypteddata, outdata, srcLen); 

(*env)->ReleasePrimitiveArrayCritical(env, bArray, decrypteddata, 0); 

return bArray; 
} 

任何想法,爲什麼對加密的字節是不是像原來一樣?

至於建議的科多和owlstead我想仍然有同樣的問題,更高一級的執行。

下面是從saju.net.in/code/misc/openssl_aes.c.txt代碼

/** 
* Create an 256 bit key and IV using the supplied key_data. salt can be added for taste. 
* Fills in the encryption and decryption ctx objects and returns 0 on success 
**/ 
int aes_init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx, 
     EVP_CIPHER_CTX *d_ctx) 
{ 
    int i, nrounds = 5; 
    unsigned char key[32], iv[32]; 

    /* 
    * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. 
    * nrounds is the number of times the we hash the material. More rounds are more secure but 
    * slower. 
    */ 
    i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv); 
    if (i != 32) { 
    printf("Key size is %d bits - should be 256 bits\n", i); 
    return -1; 
} 

EVP_CIPHER_CTX_init(e_ctx); 
EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv); 
EVP_CIPHER_CTX_init(d_ctx); 
EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv); 

return 0; 
} 

/* 
* Encrypt *len bytes of data 
* All data going in & out is considered binary (unsigned char[]) 
*/ 
unsigned char *aes_encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, int *len) 
{ 
    /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */ 
    int c_len = *len + AES_BLOCK_SIZE, f_len = 0; 
    unsigned char *ciphertext = malloc(c_len); 

    /* allows reusing of 'e' for multiple encryption cycles */ 
    EVP_EncryptInit_ex(e, NULL, NULL, NULL, NULL); 

    /* update ciphertext, c_len is filled with the length of ciphertext generated, 
    *len is the size of plaintext in bytes */ 
    EVP_EncryptUpdate(e, ciphertext, &c_len, plaintext, *len); 

    /* update ciphertext with the final remaining bytes */ 
    EVP_EncryptFinal_ex(e, ciphertext+c_len, &f_len); 

*len = c_len + f_len; 
return ciphertext; 
} 

/* 
* Decrypt *len bytes of ciphertext 
*/ 
unsigned char *aes_decrypt(EVP_CIPHER_CTX *e, const unsigned char *ciphertext, int *len) 
{ 
    /* because we have padding ON, we must allocate an extra cipher block size of memory */ 
    int p_len = *len, f_len = 0; 
    unsigned char *plaintext = malloc(p_len + AES_BLOCK_SIZE); 

    EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL); 
    EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len); 
    EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len); 

    *len = p_len + f_len; 
    return plaintext; 
} 

這裏是我的方法是所謂格式的Java:

/* "opaque" encryption, decryption ctx structures that libcrypto uses to record 
status of enc/dec operations */ 
EVP_CIPHER_CTX en, de; 


jint 
Java_com_example_hellojni_HelloJni_aesinit(JNIEnv* env, 
               jobject obj) 
{ 
     unsigned int salt[] = {12345, 54321}; 
     unsigned char key_data[]={ 'G','X','8','j','E','r','0','4','o','6','P','C','+','I','E','+'}; 
    int key_data_len; 

    key_data_len = strlen(key_data); 

    /* gen key and iv. init the cipher ctx object */ 
    if (aes_init(key_data, key_data_len, (unsigned char *)&salt, &en, &de)) { 
    printf("Couldn't initialize AES cipher\n"); 
    __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "initializing aes failed"); 
    return 0; 
    } 
    __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "initializing aes success"); 

    return 1; 
} 


    jint 
    Java_com_example_hellojni_HelloJni_aesCleanup(JNIEnv* env, 
               jobject obj) 
    { 
EVP_CIPHER_CTX_cleanup(&en); 
EVP_CIPHER_CTX_cleanup(&de); 
return 1; 
    } 



    jbyteArray 
    Java_com_example_hellojni_HelloJni_encrypt(JNIEnv* env, 
               jobject obj, jstring textToEncrypt) 
    { 

    const char *plainText = (*env)->GetStringUTFChars(env, textToEncrypt, 0); 
    int len = strlen(plainText)+1; 
    unsigned char *ciphertext = aes_encrypt(&en, (unsigned char *)plainText, &len); 

     jbyteArray byteArray=(*env)->NewByteArray(env, strlen(ciphertext)); 
    (*env)->SetByteArrayRegion(env, byteArray, 0, strlen(ciphertext), (const jbyte*)ciphertext); 

    (*env)->ReleaseStringUTFChars(env, textToEncrypt, plainText); 


    return byteArray; 

    } 



    jbyteArray 
    Java_com_example_hellojni_HelloJni_decrypt(JNIEnv* env, 
               jobject obj, jstring textToDecrypt) 
    { 


    const unsigned char *cipherText = (*env)->GetStringUTFChars(env, textToDecrypt, NULL); 
    int len = strlen(cipherText)+1; 
    char *plainText = (char *)aes_decrypt(&de, cipherText, &len); 
    jbyteArray byteArray=(*env)->NewByteArray(env, strlen(plainText)); 
    (*env)->SetByteArrayRegion(env, byteArray, 0, strlen(plainText), (const jbyte*)plainText); 

    (*env)->ReleaseStringUTFChars(env, textToDecrypt, cipherText); 


    return byteArray; 

} 
+0

有你找到一個解決方案嗎?如果是的話可以請您與我分享我有同樣的問題 –

回答

0

您提供一個長72位的密鑰(9個字符×8位)。但是它需要128位長(正如您在撥打AES_set_encrypt_key時指定的那樣)。因此,缺失的56位將或多或少是隨機的(取決於ukey陣列旁邊的內容)。

爲了修正它,指定一個較長的鍵或用0填充其餘字節。

+0

我改變了密鑰爲16個字符長,但還是同樣的結果。更新了上面的代碼 – Saqib

+0

您的數據是16字節的倍數嗎? – Codo

+0

沒有它沒有。數據可以是任何長度的,這取決於在什麼字符串用戶類型。我使用的getBytes() – Saqib

0

您正在使用OpenSSL的低級別的加密模式。如果您使用更高級別的方法(如EVP_*),您的麻煩可能會消失。用於AES/CBC模式加密。另請參閱this related question

+0

正如您所建議的,我使用了此實現saju.net.in/代碼/ misc/openssl_aes.c.txt,但仍然找不到正確的方法。請參閱上面的編輯 – Saqib