Szyfrowanie / deszyfrowanie łańcuchów Android JNI

Próbuję wykonać szyfrowanie / deszyfrowanie aes w natywnym kodzie C. Szyfrowanie działa, ale gdy próbuję odszyfrować ciąg. Nie kończy się jako oryginalny ciąg. Oto metoda JNI, która szyfruje / dekrptuje w oparciu o tryb param:

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

Jakieś pomysły, dlaczego odszyfrowywanie zaszyfrowanych bajtów nie jest tym samym, co oryginał?

Jak zasugerował Codo i owlstead, próbowałem implementacji na wyższym poziomie, która nadal ma ten sam problem.

Oto kod z 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;
}

oto moje metody, które nazywają się formą 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;

}

questionAnswers(2)

yourAnswerToTheQuestion