我遇到了一些麻烦。我正在尝试调用基于C的加密库,并从Java代码提供byte[]
。只有将我的Java签名更改为int[]
时,它才会起作用。什么给?
我要调用的实际C-图函数是:
ecc_verify(const uint8_t p_publicKey[32], const uint8_t p_hash[32], const uint8_t p_signature[32*2]
我在Java中的JNI类具有:
public native static boolean jni_verify(byte[] publicKey, byte[] data, byte[] signature);
导致此标头文件签名:
JNIEXPORT jboolean JNICALL Java_com_something_eccjni_EccJniExport_jni_1verify
(JNIEnv *, jclass, jbyteArray, jbyteArray, jbyteArray);
我的C实现是:
JNIEXPORT jboolean JNICALL Java_com_something_eccjni_EccJniExport_ecdsa_1verify
(JNIEnv *jniEnv, jclass clazz, jbyteArray publicKeyArray, jbyteArray dataArray, jbyteArray signatureArray){
jboolean isCopy;
jbyte* publicKey = (*jniEnv)->GetByteArrayElements(jniEnv, publicKeyArray, &isCopy);
jbyte* data = (*jniEnv)->GetByteArrayElements(jniEnv, dataArray, &isCopy);
jbyte* signature = (*jniEnv)->GetByteArrayElements(jniEnv, signatureArray, &isCopy);
int result = ecdsa_verify((uint8_t *) publicKey,(uint8_t *) data,(uint8_t *) signature);
(*jniEnv)->ReleaseByteArrayElements(jniEnv, publicKeyArray, publicKey, JNI_ABORT);
(*jniEnv)->ReleaseByteArrayElements(jniEnv, dataArray, data, JNI_ABORT);
(*jniEnv)->ReleaseByteArrayElements(jniEnv, signatureArray, signature, JNI_ABORT);
return result;
}
这个从不起作用。这通常会导致一条消息:
java(9966,0x7000012c8000) malloc: *** error for object 0x7fb7a0614758: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
但是,如果我将所有内容都更改为此:
public native static boolean ecdsa_verify(int[] publicKey, int[] data, int[] signature);
JNIEXPORT jboolean JNICALL Java_com_something_eccjni_EccJniExport_ecdsa_1verify
(JNIEnv *, jclass, jintArray, jintArray, jintArray);
JNIEXPORT jboolean JNICALL Java_com_something_eccjni_EccJniExport_ecdsa_1verify
(JNIEnv *jniEnv, jclass clazz, jintArray publicKeyArray, jintArray dataArray, jintArray signatureArray){
jboolean isCopy;
jint* publicKey = (*jniEnv)->GetIntArrayElements(jniEnv, publicKeyArray, &isCopy);
jint* data = (*jniEnv)->GetIntArrayElements(jniEnv, dataArray, &isCopy);
jint* signature = (*jniEnv)->GetIntArrayElements(jniEnv, signatureArray, &isCopy);
int result = ecdsa_verify((uint8_t *) publicKey,(uint8_t *) data,(uint8_t *) signature);
(*jniEnv)->ReleaseIntArrayElements(jniEnv, publicKeyArray, publicKey, JNI_ABORT);
(*jniEnv)->ReleaseIntArrayElements(jniEnv, dataArray, data, JNI_ABORT);
(*jniEnv)->ReleaseIntArrayElements(jniEnv, signatureArray, signature, JNI_ABORT);
return result;
}
发生了什么事?
编辑
这是调用Java:
System.load(EccJni.class.getResource("/EccJniExport.jnilib").getFile());
byte[] publicKey = new byte[32];
byte[] privateKey = new byte[32];
EccJniExport.ecc_make_key(publicKey, privateKey);
byte[] data = new byte[32];
for (int i = 0; i < data.length; i++) {
data[i] = (byte) i;
}
byte[] signature = new byte[32];
EccJniExport.ecdsa_sign(privateKey, data, signature);
System.out.println("result:" + EccJniExport.ecdsa_verify(publicKey, data, signature));
再次,如果将byte[]
更改为int[]
您的字节不足以为signature
数组分配。
C函数期望该参数的32*2
字节,但是您的Java代码是分配32
字节。
解释了当您使用int[]
数组而不是byte[]
数组时,代码为何工作。在这种情况下,您将分配32*4
字节。