java - 如何将加密数据从 C++ 传输到 Java

标签 java c++ java-native-interface jbytearray

我有一个使用 JNI(JAVA , C++ . 简要地 : 我将一个简单的字符串传递给 C++ 程序。 C++ 程序为我加密该字符串并返回密码字符串。 我将为客户打印密文。

问题: 当我在 c++ 中加密并将其传递给 java 时,一些字符无法传输。 但是当我使用 C++ 控制台打印它时,它是正确的。 其中一个字符是:

â , ü

C++ 控制台中的密文:

ozmzâx~w|(~i}|64ío(üuvt*po~,s|*nY|(yy~(ktztskk|sgX

java传输的密文:

ozmz?x~w|(~i}|64ío(?uvt*po~,s|*nY|(yy~(ktztskk|sgX

(â , ü is lost)

因此,由于这个错误,当我想解密文本时,这些字符无法正确解密(但在 C++ 中正确解密!)

纯文本:

Hello, This is a test message for encryptor test, we will test it for our application

密文java:

Rmvpy4*Prq},su~m}xuos}iqirybozmz?x~w|(~i}|64ᄀo(?uvtpo~,s|*nY|(yy| (ktztskk|sgX

解密文本:

Hello, This is a test message for encrケptor test, キe キill test it for our application

(在“加密器”和“我们”和“将”中失败) 我能做什么?

我以 jbyteArray 格式将字符从 C++ 传输到 Java。

C++代码:

JNIEXPORT jbyteArray JNICALL Java_com_mf_dems_HelloJNI_encryptTest
(JNIEnv *env, jobject thisObject, jobject encryptorContext, jstring 
jInputBlock)
{

//get class
jclass encryptorContextClass = env->GetObjectClass(encryptorContext);

//get keyLength
jfieldID keyLengthFieldId = env->GetFieldID(encryptorContextClass, 
"keyLength", "I");
jint keyLength = env->GetIntField(encryptorContext, keyLengthFieldId);

//get blockLength
jfieldID blockLengthFieldId = env->GetFieldID(encryptorContextClass, 
"blockLength", "I");
jint blockLength = env->GetIntField(encryptorContext, blockLengthFieldId);

//get key
jfieldID keyFieldId = env->GetFieldID(encryptorContextClass, "key", "[C");
jobject jKeyArray =env->GetObjectField(encryptorContext, keyFieldId);
jchar *key =env->GetCharArrayElements((jcharArray)(jKeyArray), NULL);

//get inputBlock
const jchar *inputBlock = env->GetStringChars(jInputBlock, NULL);

jbyte *buf = new jbyte[blockLength];

unsigned int i=0;
for(i ; i< blockLength ; i++)
{
    buf[i] =((inputBlock[i] +10) ^ key[i] ^ key[i+15] ^ 0x11);
}

env->ReleaseStringChars(jInputBlock, inputBlock);
env->ReleaseCharArrayElements((jcharArray)(jKeyArray), key, 0);

jbyteArray jOut = env->NewByteArray(blockLength);
env->SetByteArrayRegion(jOut, 0, blockLength, buf);
delete [] buf;
return jOut;

Java 代码:

 EncryptorContext encryptorContext = new EncryptorContext();
    encryptorContext.setBlockLength(17);
    encryptorContext.setKeyLength(32);
    encryptorContext.setKey(new char[encryptorContext.getKeyLength()]);
    String plainText = "Hello, This is a test message for encryptor test, we will test it for our application.";
    String cipherText = "";
    //set key
    for (int i = 0; i < encryptorContext.getKeyLength(); i++) {
        encryptorContext.getKey()[i] = (char) (i + 1);
    }
    //ENCRYPT
    for (int i = 0; i < (plainText.length() -encryptorContext.getBlockLength()); i +encryptorContext.getBlockLength()) 
    {
       byte [] out = helloJNI.encryptTest(encryptorContext, 
       plainText.substring(i, i + encryptorContext.getBlockLength()));
       byte[] latin1 = new String(out, "ISO-8859-1").getBytes("UTF-8");
        for (byte b : out) {
            cipherText+=(char)b;
        }
    }
     System.out.println(cipherText);

最佳答案

解决方案是将加密输出编码为基于字符的编码。解密时首先解码回二进制。一些加密实现使用一个选项处理 Base64,默认情况下是 orbiter,而其他加密实现则需要您自己进行编码/解码。

加密是基于字节的,而不是字符,并不是所有的字节值都可以显示/都是字符。解决方案是以字符编码(如 ASCII)对加密的二进制数据进行编码,两种主要方法是表示二进制字节的两种常用方式,因此它们可以显示:Base64 (适合计算机)和 Hexadecimal (对开发人员有好处)..

-更多-
二字显示:
ozmzâx~w|(~i}|64ío(üuvt*po~,s|*nY|(yy~(ktztskk|sgX
ozmz?x~w|(~i}|64ío(?uvt*po~,s|*nY|(yy~(ktztskk|sgX
之所以不同,是因为两个系统对某些字节值使用的字符略有不同,较低的一个使用 ? 来表示它没有字形的值。

纯文本为 86 个字符,填充为 96 个字符。这将加密 tp 96 个字符。加密文本显示 50 个字符,因此缺少 46 个字节,这些是没有可显示值的字节值和/或显示提前终止。

关于java - 如何将加密数据从 C++ 传输到 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49518414/

相关文章:

c++ - 通过 std::unique_ptr 使用 std::map 访问运算符 [] 的正确语法

java - 如何避免在 Spring Boot 应用程序中写入显式端口号 (8443)

java - 在eclipse中导入gradle项目时出现问题

java - 如何在Realm中保存相关类?

java - 显示的是代码而不是组件

java - JNI、多线程和调用方法

c++ - 显示模态窗口 1 秒

c++ - 如何在 Objective C++ header 中包含 C++ header ?

java - 使用 JNA 从 java 中的内部源对象 (.so) 文件调用 C++ 函数时出现链接异常。

java - C++多线程Java JNI方法调用