用jni方式传递DES加密字符串 - 补充"java调用vc写的dll"

来源:互联网 发布:three.js绘制弧线 编辑:程序博客网 时间:2024/05/01 05:30

 

在上篇"java调用vc6写的dll - 关于jni应用中的字符串参数传递"中,接收到字符串后再解密时,有时候不能将密文完全复原成明文.经过一轮加密和解密后,得到的明文和原始明文长度不一致,且后半段为乱码.经过检查并核实,基本找到了该问题的成因.这些问题是由错误的字符串处理方法造成的.


第一个细节,在c里面,strlen, strcpy和strcmp等函数,都是基于字符串处理的.系统判断字符串的依据是结束字符"/0".只要遇到"/0",就认为一个字符串结束.第二个细节,ascii码范围是0-255,通常字符串使用的都是可显示字符,其ascii码范围在0-127之间.( /0是结束字符, /127是del),而128-255之间的符号,则被显示为乱码.第三个细节,由编码为1-126的字符组成的字符串,经过DES加密后,生成的字符串里,其字符编码从0到255不一,可能包含多个"/0"字符.


至此真相大白.即我们不能简单的用strlen和strcpy等字符串函数,来处理加密后的字符串.因为这些函数一碰到结束字符"/0",就停止处理,而实际上,"/0"后面可能还有一堆字符没有被囊括进来.如何解决这个问题?可以使用字符指针(char *)配合自加(++)或者自减(--)运算符,来复制和传递加密后的字符串,然后针对字符指针进行我们需要的操作.

容易被忽视的语法:
char b=0;  //b表示结束字符"/0"。
strlen()函数得到的是包括了“/0”的长度。
strcpy()函数复制的时候,连源字符串里的“/0”一起复制。

 

VC(DLL)范例代码:
-------------------------------------------------------------------------------------------------------
// 加密函数
JNIEXPORT jbyteArray JNICALL Java_DESInvokeLib_encrypt
  (JNIEnv *jniEnv, jclass, jint length, jbyteArray jarrByte, jint lengthK, jbyteArray jarrByteK)
{
 ///////////////////////////////////////////////////////////////获取明文
 jbyte* pJbyte = jniEnv->GetByteArrayElements(jarrByte, 0);
 char* szByte = (char *)pJbyte; 

 long datalen = length;    // 从参数中获得明文长度 
 char *buf = new char[datalen +1];
 for (int j =0;j< datalen;j++) buf[j] = szByte[j];
 buf[datalen] = '/0';       // 强制加上结束标志,以防传输产生的乱码

 ///////////////////////////////////////////////////////////////获取key
 jbyte* pJbyteK = jniEnv->GetByteArrayElements(jarrByteK, 0);
 char* szByteK = (char *)pJbyteK; 

 int datalenK = lengthK;
 char bufK[255];  
 memset(bufK,0,255);
 for (int k =0;k< datalenK;k++) bufK[k] = szByteK[k];

 ///////////////////////////////////////////////////////////////加密
 CDes myDes;
 myDes.Des_Go( buf, buf, datalen, bufK, datalenK, ENCRYPT );

 ///////////////////////////////////////////////////////////////返回密文
 int newdatalen =(datalen+7)&0xfffffff8;  
 jbyteArray jarrRet = jniEnv->NewByteArray( newdatalen );
 jniEnv->SetByteArrayRegion( jarrRet, 0, newdatalen, (jbyte *)buf );

 return jarrRet;
}

 


//解密函数

JNIEXPORT jbyteArray JNICALL Java_DESInvokeLib_decrypt
    (JNIEnv *jniEnv, jclass, jint length, jbyteArray jarrByte, jint lengthK, jbyteArray jarrByteK)
{
 ///////////////////////////////////////////////////////////////获取密文
 
 jbyte* pJbyte = jniEnv->GetByteArrayElements(jarrByte, 0);
 char* szByte = (char *)pJbyte; 

 long datalen = length;
 char *buf = new char[datalen +1];
 for (int j =0;j< datalen;j++) buf[j] = szByte[j];
 buf[datalen] = '/0';


 ///////////////////////////////////////////////////////////////获取key
 jbyte* pJbyteK = jniEnv->GetByteArrayElements(jarrByteK, 0);
 char* szByteK = (char *)pJbyteK; 

 int datalenK = lengthK;
 char bufK[255];
 memset(bufK,0,255);

 for (int k =0;k< datalenK;k++) bufK[k] = szByteK[k];

 ///////////////////////////////////////////////////////////////解密
 CDes myDes;
 myDes.Des_Go( buf, buf, datalen, bufK, datalenK, DECRYPT );

 ///////////////////////////////////////////////////////////////返回明文
 jbyteArray jarrRet = jniEnv->NewByteArray( strlen(buf) );
 jniEnv->SetByteArrayRegion( jarrRet, 0, strlen(buf), (jbyte *)buf );

 return jarrRet;
}

 

ps: 由于jni在vc与java程序间传输,可能会产生乱码,因此java调用dll时将明文长度做参数传递给dll,同时,dll收到字符串并做(char *)处理后,在结尾后"/0"强制结束字符串.
-------------------------------------------------------------------------------------------------------

原"java调用vc6写的dll - 关于jni应用中的字符串参数传递"地址:
http://blog.csdn.net/vinchwang/archive/2007/04/25/1584384.aspx

 

原创粉丝点击