android中使用jni对字符串加解密实现分析

近期项目有个需求。就是要对用户的敏感信息进行加密处理,比方用户的账户password,手机号等私密信息。在java中,就对字符串的加解密我们能够使用AES算法加密字符串。使用它的优点就不必多说了,但我们又知道android的源码是能够被反编译的,所以使用纯Java方式的AES加密是不安全的,所以想到了使用android中的jni来对字符串加解密处理,它会产生一个.so文件,更重要的是它通过C/C++代码实现。所以安全行比較高。它能够被反编译成机器码,但差点儿不能被还原反编译。那么以下就具体介绍下这样的的加密处理。

鉴于全然使用C/C++代码进行字符串的加解密,我们须要考虑不同系统平台上数据类型的差异问题。这里推荐还有一种易于实现的方法。即使用Java中的AES加解密逻辑,而将AES加解密所须要的核心秘钥放入到C中,通过调用jni来从静态类库中读取须要的秘钥,详细实现例如以下:

项目代码结构图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2h5XzIwMTJfZ29nbw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

Java中的AES算法逻辑:

publicclass SecurityUtil {

privatestaticbyte[]keyValue;

privatestaticbyte[]iv;

privatestatic SecretKeykey;

privatestatic AlgorithmParameterSpecparamSpec;

privatestatic Cipherecipher;

static {

System.loadLibrary("cwtlib");

keyValue = getKeyValue();

iv = getIv();

if(null
!= keyValue &&

null !=iv)
{

KeyGeneratorkgen;

try {

kgen = KeyGenerator.getInstance("AES");

// Java项目中的写法

SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

// Android项目中的写法

SecureRandom random = SecureRandom.getInstance("SHA1PRNG","Crypto");

random.setSeed(keyValue);

kgen.init(128,random);

key =kgen.generateKey();

paramSpec =new
IvParameterSpec(iv);

ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

} catch (NoSuchAlgorithmExceptione)
{

} catch (NoSuchPaddingExceptione)
{

}

}

}

publicstaticnativebyte[]
getKeyValue();

publicstaticnativebyte[]
getIv();

publicstatic String
encode(Stringmsg) {

String str ="";

try {

//用密钥和一组算法參数初始化此 cipher

ecipher.init(Cipher.ENCRYPT_MODE,key,paramSpec);

//加密并转换成16进制字符串

str = asHex(ecipher.doFinal(msg.getBytes()));

} catch (BadPaddingExceptione)
{

} catch (InvalidKeyExceptione)
{

} catch (InvalidAlgorithmParameterExceptione)
{

} catch (IllegalBlockSizeExceptione)
{

}

returnstr;

}

publicstatic String
decode(Stringvalue) {

try {

ecipher.init(Cipher.DECRYPT_MODE,key,paramSpec);

returnnew String(ecipher.doFinal(asBin(value)));

} catch (BadPaddingExceptione)
{

} catch (InvalidKeyExceptione)
{

} catch (InvalidAlgorithmParameterExceptione)
{

} catch (IllegalBlockSizeExceptione)
{

}

return"";

}

privatestatic String
asHex(bytebuf[]) {

StringBuffer strbuf =new
StringBuffer(buf.length * 2);

inti;

for (i = 0;i
<buf.length;i++)
{

if (((int)buf[i]
& 0xff) < 0x10)//小于十前面补零

strbuf.append("0");

strbuf.append(Long.toString((int)buf[i]
& 0xff, 16));

}

returnstrbuf.toString();

}

privatestaticbyte[]
asBin(Stringsrc) {

if (src.length()
< 1)

returnnull;

byte[]encrypted
=newbyte[src.length()
/ 2];

for (inti
= 0;i <src.length() / 2;i++)
{

inthigh = Integer.parseInt(src.substring(i
* 2, i * 2 + 1), 16);//取高位字节

intlow = Integer.parseInt(src.substring(i
* 2 + 1, i * 2 + 2), 16);//取低位字节

encrypted[i]
= (byte) (high * 16 +low);

}

returnencrypted;

}

C中的读取秘钥的实现:

#include<stdio.h>

#include"cwtlib.h"

constchar keyValue[] = {

21, 25, 21, -45, 25, 98, -55, -45, 10, 35, -45, 35,

26, -5, 25, -65, -78, -99, 85, 45, -5, 10, -0, 11,

-35, -48, -98, 65, -32, 14, -67, 25, 36, -56, -45, -5,

12, 15, 35, -15, 25, -14, 62, -25, 33, -45, 55, 12, -8

};

constchar iv[] =  {

-33, 32, -25, 25, 35, -27, 55, -12, -15, 23, 45, -26, 32, 5 - 2, 74, 54

};

JNIEXPORT jbyteArray JNICALL Java_com_cwtlib_aesencript_SecurityUtil_getKeyValue

(JNIEnv *env, jclass obj)

{

jbyteArray kvArray = (*env)->NewByteArray(env,sizeof(keyValue));

jbyte *bytes = (*env)->GetByteArrayElements(env,kvArray,0);

int i;

for (i = 0; i <sizeof(keyValue);i++)

{

bytes[i] = (jbyte)keyValue[i];

}

(*env)->SetByteArrayRegion(env,kvArray, 0,sizeof(keyValue),bytes);

(*env)->ReleaseByteArrayElements(env,kvArray,bytes,0);

return kvArray;

}

JNIEXPORT jbyteArray JNICALL Java_com_cwtlib_aesencript_SecurityUtil_getIv

(JNIEnv *env, jclass obj)

{

jbyteArray ivArray = (*env)->NewByteArray(env,sizeof(iv));

jbyte *bytes = (*env)->GetByteArrayElements(env,ivArray, 0);

int i;

for (i = 0; i <sizeof(iv);
i++)

{

bytes[i] = (jbyte)iv[i];

}

(*env)->SetByteArrayRegion(env,ivArray, 0,sizeof(iv), bytes);

(*env)->ReleaseByteArrayElements(env,ivArray,bytes,0);

return ivArray;

}

在android中怎样调用:

publicclass MainActivityextends
Activity {

privatestaticfinal
StringTAG ="MainActivity";

private StringencriptStr
="18721002361";//加密的字符串

@Override

protectedvoid
onCreate(BundlesavedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//加密后

String
enstr = SecurityUtil.encode(encriptStr);

Log.d(TAG,"加密后:"
+enstr);

//解密后

String
destr = SecurityUtil.decode(enstr);

Log.d(TAG,"解密后:"
+destr);

}

}

这里以一个手机号为例进行加解密处理,详细的效果图能够在日志中查看到,详细例如以下。

加解密的对比效果图:

好了,到这里我已经罗列出了全部主要文件实现,假设有问题能够在评论或是群(179914858)中进行讨论。另外,原创作品来自不易,转载请注明出处,谢谢。

最后附上原代码供參考,下载地址:请点这里


android中使用jni对字符串加解密实现分析的更多相关文章

  1. 深入理解Android(5)——从MediaScanner分析Android中的JNI

    前面几篇介绍了Android中的JNI和基本用法,这一篇我们通过分析Android源代码中的JNI实例,来对JNI部分做一个总结. 一.通向两个不同世界的桥梁 在前面我们说过,JNI就像一个桥梁,将J ...

  2. 深入理解Android(2)——理解Android中的JNI(中)

    阳光小强参加了CSDN博客之星评选,如果你觉得阳光小强的博客对你有所帮助,为小强投上一票吧:http://vote.blog.csdn.net/blogstar2014/details?usernam ...

  3. Android中关于JNI 的学习(零)简单的样例,简单地入门

    Android中JNI的作用,就是让Java可以去调用由C/C++实现的代码,为了实现这个功能.须要用到Anrdoid提供的NDK工具包,在这里不讲怎样配置了,好麻烦,配置了好久. . . 本质上,J ...

  4. android中滑动SQLite数据库分页加载

    今天用到了android中滑动SQlit数据库分页加载技术,写了个测试工程,将代码贴出来和大家交流一下: MainActivity package com.example.testscrollsqli ...

  5. QuickBase64 - Android 下拉通知栏快捷base64加解密工具

    Android Quick Setting Tile Base64 Encode/Decode Tool Android 下拉通知栏快捷 base64 加解密,自动将剪切板的内容进行 base64 E ...

  6. Android中关于JNI 的学习(三)在JNI层訪问Java端对象

    前面两篇文章简介了JNI层跟Java层的一些相应关系,包含方法名,数据类型和方法名称等,相信在理论层面.可以非常好地帮助我们去了解JNI在Native本地开发中的作用,对JNI的一些概念也有了一个初步 ...

  7. 深入理解Android(4)——理解Android中的JNI(下)

    在前面文章中简单介绍了JNI,这一篇文章来简单看一下jni.h中定义的一些常用方法,来实现通过C++调用Android中的Java代码. 转载请说明出处:http://blog.csdn.net/da ...

  8. 华为OJ:字符串加解密

    题目描述 1.对输入的字符串进行加解密,并输出. 2加密方法为: 当内容是英文字母时则用该英文字母的后一个字母替换,同时字母变换大小写,如字母a时则替换为B:字母Z时则替换为a: 当内容是数字时则把该 ...

  9. Android中的Apk的加固(加壳)原理解析和实现

    一.前言 今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理.现阶段.我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk, ...

随机推荐

  1. 小鱼提问2 属性访问器中get,set再用public修饰行吗,private呢?

    /// <summary> /// 是否有一个用户正在连接服务器中 /// </summary> public bool IsConnectting { get { retur ...

  2. 全局变量,extern和static以及命名空间的区别

    全局变量,extern和static以及命名空间的区别        全局变量只是在声明它的文件中有效,假如在另一个文件中声明定义了一个相同名称的全局变量,则在后续使用这两个变量的时候会产生名字上的冲 ...

  3. VS中,NUnit适合测试者尽心开发自动化测试,而Unit适合开发者开发单元测试。

    1.整合Visual Studio和NUnit 在Visual Studio 2010中,通过安装NUnit插件,可以不使用外部客户端,直接运行测试. 当然,貌似在最新版本的VS2012中,安装过NU ...

  4. 安装AppManager

    http://www.searchvirtual.com.cn/showcontent_66884.htm

  5. 深信服模式(先做减法,必须拜访客户三次、研究需求方向,把产品的问题控制住,快速反应,在未来十年,绝大部分业务都会搬到Internet上来,实现All on Internet)good

    深圳市盛凯信息科技有限公司与深信服合作多年,可以说是看着深信服“飞速”长大的.盛凯的总经理邓渊在采访中笑言:“他们(深信服)发展得太快,而我们发展得太慢.” 深信服的产品线已从最初只有VPN一条,到目 ...

  6. 宣布正式发布 Windows Azure Notification Hub,新增 SQL Server AlwaysOn 可用性组侦听器支持

    今天,我们非常高兴地宣布,针对使用 Windows Azure 的移动和企业开发人员推出一些新功能.这些新功能可以减少构建移动应用程序的开发时间和成本,并能帮助企业开发人员实现高可用性和全球业务连续性 ...

  7. spring集成mongodb封装的简单的CRUD

    1.什么是mongodb         MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. mongoDB MongoDB是一个介 ...

  8. spring 资源加载使用说明

    Spring 提供了一个强大加载资源的机制,不但能够通过“classpath:”.“file:” 等资源地址前缀识别不同的资源类型,还支持Ant 风格带通配符的资源地址. 首先,我们来了解一下Spri ...

  9. SQLServer 2008 :error 40 出现连接错误

      在与SQLServer建立连接时出现与网络相关的或特定与实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且SQL SERVER已配置允许远程链接.(provide:命名管道提供程序,e ...

  10. java 錯誤集錦.

    (1)加载驱动成功com.microsoft.sqlserver.jdbc.SQLServerException: 不支持此服务器版本.目标服务器必须是 SQL Server 2000 或更高版本.链 ...