转载请注明出处:https://blog.csdn.net/mythmayor/article/details/107228669

引言

在日常开发中我们经常需要保存一些私密的信息,例如加解密的密钥等等。这时候我们就要来考虑如何存储密钥了。先来简单介绍几种存储方式:

Java硬编码方式

SharedPreferences存储

文件存储

数据库存储

以上几种存储方式是很不安全的,例如采用硬编码方式存储,程序包很容易被反编译获取到密钥。SharedPreferences、文件和数据库又有可能因为用户的误删操作而丢失密钥,所以一般很少存储到这一类的文件中。那么问题来了,我们应该用什么方式来确保密钥的存储相对更安全呢?

密钥存储方案

在日常开发中,推荐运用若干种方案拼接起完整的密钥。

在下面的案例中,我将运用以下方式输出密钥各部分内容(后面会逐个讲解)

Java硬编码

gradle配置

特殊的算法

利用strings.xml

现在假设我们需要进行AES加解密,按要求来定义一个密钥,密钥的形式可能是这样的:

String AES_KEY = "1234567890!@#$%^";//硬编码方式定义AES密钥

是不是已经有同学看不下去了。。。

好吧,更好的方式是这样的:

String AES_KEY = ProjectUtil.getAESKeyPart1(3, 4)//根据自定义算法输出密钥第1部分

+ BuildConfig.AES_KEY_PART2//根据gradle配置输出密钥第2部分

+ CommonUtil.getString(R.string.AES_KEY_PART3)//根据string.xml输出密钥第3部分

+ MyConstant.AES_KEY_PART4;//根据硬编码方式输出密钥第4部分

String AES_KEY_PART4 = "!@#$%^";

怎么样?是不是瞬间感觉难懂了一些,下面就来逐一讲解。

第一部分:ProjectUtil.getAESKeyPart1(3, 4)

这部分很好说,这里我自定义了一个算法,用以迷惑“有缘人”

public static int getAESKeyPart1(int x, int y) {

for (int i = 1; i <= x * y; i++) {

if (i % x == 0 && i % y == 0)

return i;

}

return x * y;

}

我这里定义的算法主要输出的是数字,在实际开发中你也可以定义一些类似的算法。

第二部分:BuildConfig.AES_KEY_PART2

这里主要是通过gradle的配置来自动生成AES_KEY_PART2这个常量。具体操作如下:

打开Module下的build.gradle文件,在android标签下的buildTypes下添加配置。

buildTypes {

release {

buildConfigField "boolean", "LOG_DEBUG", "true"//显示Log

buildConfigField "String", "AES_KEY_PART2", "\"3456\""

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

}

debug {

buildConfigField "boolean", "LOG_DEBUG", "false"//不显示Log

buildConfigField "String", "AES_KEY_PART2", "\"3456\""

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

}

}

如上所见,我使用buildConfigField关键字添加了LOG_DEBUG和AES_KEY_PART2两个字段。LOG_DEBUG用以控制是否输出并显示Log。在添加完配置之后,就可以Rebuild项目了,然后你就可以打开自动生成的BuildConfig类,这时候你添加的常量就在此类当中了。

public final class BuildConfig {

// ...

public static final String AES_KEY_PART2 = "3456";

public static final boolean LOG_DEBUG = false;

}

需要注意的是,在定义字符串(尤其是数字字符串)的时候,一定要定义成:

buildConfigField "String", "AES_KEY_PART2", "\"3456\""

而不是

buildConfigField "String", "AES_KEY_PART2", "3456"

原因是第一种方式的话会在BuildConfig中生成

public static final String AES_KEY_PART2 = "3456";

而第二种方式则会在BuildConfig中生成

public static final String AES_KEY_PART2 = 3456;

第二种自然就会报编译错误了。

第三部分:CommonUtil.getString(R.string.AES_KEY_PART3)

在我的strings.xml中定义了一个字符串:

7890

第四部分:MyConstant.AES_KEY_PART4

在我的MyConstant类中定义了一个常量:

String AES_KEY_PART4 = "!@#$%^";

总结

上面介绍的密钥存储方式极大的增加了逆向的难度,辅以代码混淆等手段,在很大程度上提高了密钥存储的安全性。总体来说,在App端保存密钥并无法完全保证密钥的安全性,只能通过一些手段增加被反编译的难度。

android+静态密钥,Android - 更安全地保存静态密钥相关推荐

  1. 【Android NDK 开发】Android.mk 配置静态库 ( Android Studio 配置静态库 | 配置动态库与静态库区别 | 动态库与静态库打包对比 )

    文章目录 I . Android Studio 中使用 Android.mk 配置静态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  2. android java静态库,Android NDK开发相关知识集合

    1.关于方法名 调用 native 方法之前,首先要调用 System.loadLibrary 接口加载一个实现了native 方法的动态库才能正常访问,否则就会抛出 java.lang.Unsati ...

  3. .net程序员转战android第三篇---登录模块之静态登录

    这一篇我将分2个部分记录登录界面,第一部分是静态登录, 这部分将如何从界面布局.控件使用.文件关系.数据验证.登陆实现等5小块记录. 第二部分是动态登录,这块会基于上面的4小块,在数据验证不是静态数据 ...

  4. android jni java调用c,Android与JNI(一) ---- Java调用C 静态调用

    第一.通过eclipse新建一个工程名为HelloJni的android工程,并编译. 第二.右键工程-->Android Tools --> Add Native Support,出现如 ...

  5. android 初始化类,Android 常用编程技巧/Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)...

    1.设置屏幕的亮度: WindowManager.LayoutParams lp=getWindow().getAttributes(); lp.screenBrightness=1.0f; getW ...

  6. android java静态库,Android make 中变量记录

    转换mk文件到bp文件 $ out/soong/host/linux-x86/bin/androidmk Android.mk > Android.bp 编译不同类型的模块 编译成 Native ...

  7. android 静态_Google静态地图Android

    android 静态 In this tutorial we're going to implement a google static maps in our android application ...

  8. android 播放静态mp4,Android 使用VideoView播放MP4的简单实现

    使用VideoView播放MP4 播放示例 实现简单的播放功能,播放手机本地的MP4文件.不依赖任何第三方框架,不添加任何防腐剂. 添加一个系统自带的控制条. 申请权限 读取存储中的MP4文件 准备布 ...

  9. android java 实体类 object变量 保存_Android中Intent传递对象的两种方法Serializable,Parcelable...

    Android中的传递有两个方法,一个是Serializable,另一个是Parcelable. Serializable是J2SE本身就支持的.而Parcelable是Android所特有的. 二者 ...

最新文章

  1. 你真的了解try{ return }finally{}中的return?
  2. 剑指offer十一:二进制中1的个数
  3. SQLite学习手册(索引和数据分析/清理)
  4. Maxscript中渲染中文版Vray完成贴图(VrayCompleteMap)的方法
  5. Redis java API ——Jedis的使用
  6. vb与三菱plc以太网通讯_实战演练|三菱触摸屏GOT2000与三菱Q系列以太网通讯
  7. opencv android
  8. 纯数学教程 Page 325 例LXVIII (12)
  9. 微课|中学生可以这样学Python(例4.6):抓小狐狸游戏
  10. HDU3788 ZOJ问题【文本处理】
  11. alpha冲刺-事后诸葛亮
  12. springboot集成kafka_厉害!腾讯T3-2都还在学的微服务+MySQL+Kafka+boot2.x+虚拟机PDF
  13. linux给文件备份,Linux文件备份
  14. linux环境下使用logrotate工具实现nginx日志切割
  15. VS2017IIS注册
  16. PS4常用DNS一览 PSN下载速度慢登录失败解决办法
  17. 七个技巧!Godaddy域名安全指数提高N倍
  18. 写技术博客的一些心得体会
  19. 计算机与人脑的出版社,计算机与人脑
  20. xz2p更新android 9,索尼新旗舰XZ2P曝光:首发Android 9.0

热门文章

  1. elasticsearch 查询数据 | 分页查询
  2. java线程暂停与恢复suspend和resume
  3. PU learning学习笔记
  4. 一次堆外OOM问题排查
  5. 【译】canvas笔触魔法师
  6. 《解释的工具:生活中的经济学原理》读书笔记7(完)
  7. 详解MySQL中EXPLAIN解释命令
  8. CSS系列:CSS中盒子模型
  9. oracle中schema指的是什么?
  10. ArcGIS.Server.9.2.DotNet在ElementGraphicsLayer画点、线、折线、面、圆、矩形的代码