如何将加密数据从c ++传输到java

时间:2018-03-27 16:49:51

标签: 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 |?(〜我} |?64ío(UVT * PO〜,S | * NY |(YY〜(ktztskk | SGX

     

(â,ü丢失)

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

纯文字:

  

您好,这是加密器测试的测试消息,我们将对其进行测试   我们的申请

密文java:

  

Rmvpy4 * PRQ},S U〜米} X UOS} IQI rybozmz X〜W |?(〜I} |?64ㄱO(UVT PO〜 ,S | *纽约|(YY |   (ktztskk | SGX

解密文字:

  

你好,这是一个测试信息,用于加密测试,キe ge test test   为了我们           应用

(“加密器”,“我们”和“将”失败) 我该怎么办?

我以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 CODE:

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

1 个答案:

答案 0 :(得分:2)

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

加密是基于字节的,而不是字符,并非所有字节值都可以显示/是字符。解决方案是使用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个字节,这些字节值没有可显示的值和/或显示提前终止。