2011-08-13 11 views
8

Tengo un byte[] en Java que informe sobre su longitud que 256 bytes, que los que paso a una función nativa en C.problema de bytes que pasa [] a través de JNI a C en Android

Cuando traté de obtener los datos de cada este arreglo estaba completamente equivocado y cuando lo imprimí no coincidía con los datos que imprimí justo antes de pasarlo a C.

Intenté algunas formas de acceder a los datos incluyendo GetByteArrayRegion y GetByteArrayElements pero nada parece para darme los datos que espero.

Cuando estaba investigando esto traté de ver lo que JNI creía que la longitud de jbyteArray era con - informaba la longitud como 1079142960, mucho más que los 256 bytes que esperaba. También el valor era diferente cada vez que la función se llama, por ejemplo, otra vez volvió GetArrayLength 1079145720.

Aquí está el código que estoy utilizando para acceder a la matriz:

JNIEXPORT jbyteArray function(JNIEnv* env, jbyteArray array) { 
    int length = (*env)->GetArrayLength(env, array); 

    jbyte data[256]; 

    (*env)->GetByteArrayRegion(env, array, 0, 256, data); 
    //also tried 
    //jbyte *data = (jbyte*) (*env)->GetByteArrayElements(env, array, NULL); 
} 

Esto parece bastante sencillo así que No estoy realmente seguro de lo que está pasando. La matriz parece estar bien desde Java, pero se generó en C y se pasó de vuelta, así que supongo que algo puede haber salido mal que a Java no le importa sino que rompe la matriz cuando vuelve a C.

Aquí está el código Solía ​​generar la matriz y devolverla a Java:

//there is some openSSL stuff here that sets up a pointer to an RSA struct called keys that is size bytes large 

jbyteArray result = (*env)->NewByteArray(env, size); 

(*env)->SetByteArrayRegion(env, result, 0, size, (jbyte*)keys; 

¿E-cando algo?

Gracias

+0

¿Cómo se ve el código de Java? –

+0

no pasa nada interesante en Java Cojo la matriz de bytes de un objeto SharedPreferences y luego verifico los datos y la longitud que se ven bien y luego los paso a la función nativa –

Respuesta

12

Esta función prototipo es incorrecto:

JNIEXPORT jbyteArray function(JNIEnv* env, jbyteArray array) 

El segundo argumento es o bien un jclass o una jobject. Si el método es estático, debe ser:

JNIEXPORT jbyteArray function(JNIEnv* env, jclass cls, jbyteArray array) 

Y si no es estática:

JNIEXPORT jbyteArray function(JNIEnv* env, jobject obj, jbyteArray array) 

Usted está tratando la clase o un objeto como una matriz, lo que explica los inesperados resultados que se obtienen.

+0

Este fue el problema. Había pasado un tiempo desde que había hecho algún trabajo en JNI y cuando estaba armando el prototipo olvidé que tenías que hacer esto. Gracias –

0

Prueba a agregar la cadena con el carácter '\ 0'. Probablemente no sea capaz de identificar el final de la cadena.

+0

no es una cadena its struct –

1

Supongo que el problema principal es que fuerza una estructura de OpenSSL en una matriz de bytes. Lo más probable es que esta estructura se libere con el tiempo. Eso explicaría las extrañas y diferentes duraciones que se le informan cuando regrese a C. Ceder un RSA* a Java tampoco le ayudará mucho - Java no tiene conocimiento sobre esa estructura particular y no podrá reconocerla .

Lo que debe intentar es usar uno de

  • i2d_PKCS8PrivateKey_bio (BIO * pb, EVP_PKEY * x, EVP_CIPHER const * enc, char * kstr, int Klen, pem_password_cb * CB, void * u)
  • int i2d_RSA_PUBKEY (RSA * a, unsigned char ** pp)

dependiendo de si sólo quiere pasar la información de clave pública o también la información privada a Java (see also here). De esta manera, puede estar seguro de tratar con una matriz de bytes desde el principio.

Una vez que esto funcione para usted (utilizando las técnicas que ya ha probado), de vuelta en Java puede analizar la matriz de bytes en algo significativo. Esto es sencillo en el caso de la clave pública: use X509EncodedKeySpec con su matriz y genere una clave pública usando KeyFactory#generatePublic.

Las cosas son un poco más complicadas en el caso de la clave privada.Java solo entiende el PKCS#8 format mientras que OpenSSL codifica sus claves RSA privadas de acuerdo con el formato PKCS # 1 de forma predeterminada. Pero ya puede convertir su clave a PKCS # 8 usando i2d_PKCS8PrivateKey_bio. Es necesario para envolver su RSA* como EVP_PKEY* primera, sin embargo:

EVP_pkey *pkey = EVP_PKEY_new(); 
EVP_PKEY_assign_RSA(pkey, rsa); 

No cifrar su clave y utilizar un in-memory BIO, a continuación, pasar a la matriz de bytes resultante a Java y no al constructor de PKCS8EncodedKeySpec y finalmente generar su clave privada con el KeyFactory.

Cuestiones relacionadas