java/android jni练习-字符串加解密

一、任务目标:服务器端对一个32位密钥加密,传到客户端后再解密。加解密算法已知,是C++所写。

二、简单分析:

1、服务器端:myeclipse+tomcat+mysql+servlet搭建的简单服务器,存放加密视频,和加密的密钥。

2、客户端:android客户端,获取加密的密钥再解密,然后再利用解密后的密钥解密视频

3、服务器客户端都是java,加解密是C++,所以采用jni技术,视频加密解密不再多说,主要研究字符串的加解密

三、服务器端java+jni:

与android jni调so不用 ,java 可以调用dll,所以大致步奏如下

1、生成jni头文件

打开命令行窗口 跳转到java源代码目录,然后生成.class文件,命令

javac ****.java

再生成头文件:命令

javah -jni ****(没有扩展名)

2、生成dll

打开VS2012创建dll工程,把上面头文件导入,并导入jni.h jni_md.h等头文件,总之提示没啥就去jdk里面找吧(C:\Program Files\Java\jdk1.7.0_60\include)。项目如下:

AES_Jni_Test.h是刚才生成的头文件,下面的cpp就是具体实现接口函数,enctypt_and_decrypt_algorithm就是已知的加解密的源代码。

之后选择所在平台需要的dll(32or64位)

再把生成的dll放入C:\Program Files\Java\jdk1.7.0_60\bin

最后在java代码中先调用System.loadLibrary(“****”);(DLL文件名,没有扩展名)

3、参数传递

上层java给C++传递的参数有3个,len是加密字符串长度,byte是加密后的字符串,这里有byte[],没用string,是减少麻烦,因为java和c++的数据类型不同,

字符串编码也不同,传字符串问题很多,key就是密钥

package AES.Jni;

public class Test {
	static { 
        System.loadLibrary("AES"); 
    }
	public native static byte[] encrypt(int len,byte[] str,String key); 
        public native static byte[] decrypt(int len,byte[] str,String key); 

}
C++接口 AES_Jni_Test.cpp,接收上面的参数,并调用C++解密代码(实现未给出),注意的就是C和C++中jniEnv是不同的 格式也不同<pre name="code" class="cpp">JNIEXPORT jbyteArray JNICALL Java_AES_Jni_Test_encrypt
	(JNIEnv *jniEnv, jclass, jint length, jbyteArray jarrByte,jstring str)
{
	//接收明文字节数组
	jbyte* pJbyte = jniEnv->GetByteArrayElements(jarrByte, 0);
	if (pJbyte == NULL) { 
		return NULL; 
	} 
	char* szByte = (char *)pJbyte;
	//接受密钥
	const char * src = jniEnv->GetStringUTFChars(str, NULL);
	char* skey=(char *)src;
     
	char buf[255];
	//存明文到buffer并加密
	memset( buf, 0, sizeof(buf) );
	strcpy( buf, szByte );
	buf[length] = '\0'; 
	//生成结果并返回
	jbyteArray jarrRet = jniEnv->NewByteArray( strlen(buf) );
	strcpy( szByte, buf );

	jniEnv->SetByteArrayRegion( jarrRet, 0, strlen(buf), (jbyte *)szByte );
	jniEnv->ReleaseByteArrayElements(jarrRet, pJbyte, 0);
	return jarrRet;
}

JNIEXPORT jbyteArray JNICALL Java_AES_Jni_Test_decrypt(JNIEnv *jniEnv,jclass,jint length,jbyteArray jarrByte,jstring str){
	//接收明文
	jbyte* pJbyte = jniEnv->GetByteArrayElements(jarrByte, 0);
	if (pJbyte == NULL) { 
		return NULL; 
	} 
	char* szByte = (char *)pJbyte;
	const char * src = jniEnv->GetStringUTFChars(str, NULL);
	char* skey=(char *)src;
	char buf[255];
	//存明文到buffer并加密
	memset( buf, 0, sizeof(buf) );
	strcpy( buf, szByte );
	buf[length] = '\0';
	//生成结果并返回
	jbyteArray jarrRet = jniEnv->NewByteArray( strlen(buf) );
	strcpy( szByte, buf );

	jniEnv->SetByteArrayRegion( jarrRet, 0, strlen(buf), (jbyte *)szByte );
	jniEnv->ReleaseByteArrayElements(jarrRet, pJbyte, 0);
	return jarrRet;

}
4、测试
private void testAES() {
		SkeyDecrypt skeydecrypt=new SkeyDecrypt();//类似上面的TEST累,加载dll,声明native方法
		String Key = "0123456789abcdef0123456789abcdee";
		try{
		    byte[] plainSkeyBytes = Key.getBytes("utf-8");//到底用哪个字符集要看具体情况,没中文用iso-8859-1的单字节编码更好
                    int len = plainSkeyBytes.length;
                    System.out.println("plainTextBytes length is: " + len);
                    byte[] encryptedTextBytes = skeydecrypt.encrypt(len, plainSkeyBytes,skey_decrpyt);
                    String encryptedText = new String(encryptedTextBytes, "utf-8");
                    System.out.println("encryptedText is: " + encryptedText);      
		    System.out.println("----------------------------");
		
		    byte[] decryptedSkeyBytes = skeydecrypt.decrypt(len,encryptedTextBytes,skey_decrpyt);

                    //将字符数组转换为String
                    System.out.println("decryptedTextBytes length is: " +decryptedSkeyBytes.length);
                    String decryptedText = new String(decryptedSkeyBytes, "utf-8");
                    System.out.println("decryptedText is: " + decryptedText);
		    System.out.println();
		    System.out.println("------------ END ----------------");
		} catch (UnsupportedEncodingException e) {
            e.printStackTrace();
       }  
}
四、客户端
android平台jni,前面有文章介绍过了,简单说下,要生成so库,windows用cygwin,linux写脚本

以Windows为例,进入项目jni目录,用ndk编译,生成so后,载入就可以使用了。
五、字符串编码和字符集
 可以参考 http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值