Java 方法调用为相同参数提供不一致的结果
blake2b散列是一种函数方法,我得到了不一致的结果。在我看来,问题在于java端,它以某种方式对两个方法调用之间的输入参数执行更改。我不明白两次调用SodiumJNI.crypto_generichash_blake2b_salt_personal_no_input之间的输入参数是怎么回事。本机函数(如下所示)不会对Java 方法调用为相同参数提供不一致的结果,java,java-native-interface,libsodium,Java,Java Native Interface,Libsodium,blake2b散列是一种函数方法,我得到了不一致的结果。在我看来,问题在于java端,它以某种方式对两个方法调用之间的输入参数执行更改。我不明白两次调用SodiumJNI.crypto_generichash_blake2b_salt_personal_no_input之间的输入参数是怎么回事。本机函数(如下所示)不会对键、盐和信息执行任何更改。因此,输出应该是相同的,但事实并非如此 我的测试方法如下所示: import android.util.Base64; import android
键
、盐
和信息
执行任何更改。因此,输出应该是相同的,但事实并非如此
我的测试方法如下所示:
import android.util.Base64;
import android.util.Log;
static void kdf() {
final byte[] key = new byte[32];
final byte[] salt = new byte[32];
final byte[] info = Base64.decode("aGFuZHNoYWtl", Base64.DEFAULT);
byte[] out0 = new byte[64];
int result0 = SodiumJNI.crypto_generichash_blake2b_salt_personal_no_input(out0, out0.length, key, key.length, salt, info);
if (result0 == 0) {
Log.d("Tests", "out0: " + Base64.encodeToString(out0, Base64.DEFAULT));
//prints:
//out0: nCzeDcbw1YmdPq+jYnslNDoXKNyXMvIsqx9QJ1PLRNPxh7dvXkTeSkF2REYznHExaWCQP7J0kFvDu9l9ECs4VQ==
}
byte[] out1 = new byte[64];
int result1 = SodiumJNI.crypto_generichash_blake2b_salt_personal_no_input(out1, out1.length, key, key.length, salt, info);
if (result1 == 0) {
Log.d("Tests", "out1: " + Base64.encodeToString(out1, Base64.DEFAULT));
//prints;
//out1: dNfj+ccfGzTDiTAgzHNE5Hujyxnl6yX2BAPamCBw8X3fPYgbdtNDPoA3JKQGCziJw40wVTr/kPCpVUqMqMiVKw==
}
}
奇怪的是,out0
和out1
并不相同
本机函数实现如下所示:
public class SodiumJNI {
public final static native int sodium_init();
public final static native int crypto_generichash_blake2b_salt_personal_no_input(byte[] out, int outlen, byte [] key, int keylen, byte[] salt, byte[] personal);
static {
try {
System.loadLibrary("sodiumjni");
if (sodium_init() == -1) {
throw new RuntimeException("Sodium could not be initialized.");
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
以及本机函数:
JNIEXPORT jint JNICALL Java_com_app_jni_SodiumJNI_crypto_1generichash_1blake2b_1salt_1personal_1no_1input(JNIEnv *jenv, jclass jcls,
jbyteArray joutput, jint joutlength, jbyteArray jkey, jint jkeylength, jbyteArray jsalt, jbyteArray jpersonal) {
jint jresult = 0 ;
unsigned char *output = (unsigned char *) 0 ;
size_t outlength ;
unsigned char *key = (unsigned char *) 0 ;
size_t keylength ;
unsigned char *salt = (unsigned char *) 0 ;
unsigned char *personal = (unsigned char *) 0 ;
int result;
(void)jenv;
(void)jcls;
{
output = (unsigned char *) (*jenv)->GetByteArrayElements(jenv, joutput, 0);
}
outlength = (size_t)joutlength;
{
key = (unsigned char *) (*jenv)->GetByteArrayElements(jenv, jkey, 0);
}
keylength = (size_t)jkeylength;
{
salt = (unsigned char *) (*jenv)->GetByteArrayElements(jenv, jsalt, 0);
}
{
personal = (unsigned char *) (*jenv)->GetByteArrayElements(jenv, jpersonal, 0);
}
result = (int)crypto_generichash_blake2b_salt_personal(output,
outlength,
NULL,
0,
(unsigned char const *)key,
keylength,
(unsigned char const *)salt,
(unsigned char const *)personal);
jresult = (jint)result;
{
(*jenv)->ReleaseByteArrayElements(jenv, joutput, (jbyte *) output, 0);
}
{
(*jenv)->ReleaseByteArrayElements(jenv, jkey, (jbyte *) key, JNI_ABORT);
}
{
(*jenv)->ReleaseByteArrayElements(jenv, jsalt, (jbyte *) salt, JNI_ABORT);
}
{
(*jenv)->ReleaseByteArrayElements(jenv, jpersonal, (jbyte *) personal, JNI_ABORT);
}
return jresult;
}
好。。。out0和out1指向不同的内存位置。因此,您会得到不同的结果。日志不会打印位置,而是打印内容。
GetByteArrayElements
可以返回副本,但不能保证返回副本。它很可能返回指向实际数据的指针。请详细说明。你看到c数组在哪里被释放,在哪里被实例化,或者在哪里被传递到libke2b方法了吗?我的观点是,你似乎认为GetByteArrayElements
返回一个数据副本,你可以在不改变相应Java数组的情况下修改它。但是,无法保证您得到的是副本,因此您可能必须自己创建副本。GetByteArrayElements
的最后一个参数可用于确定这一点(即jboolean*isCopy
)。