android studio实现raw资源文件加密
2017-11-09 15:53
204 查看
android studio实现raw文件自动加密(AES加密)
本文将介绍android studio利用gradle进行raw资源文件加密的一种方式(所有代码均写在build.gradle中):第一步:首先要需要了解的是gradle打包监听器BuildListener的两个方法:
projectsEvaluated()方法执行在生成apk前。
所以在projectsEvaluated方法进行apk资源文件copy工作和加密工作。
buildFinished()方法执行在apk生成之后。
在buildFinished方法中进行加密资源文件的恢复和临时文件的删除工作(临时文件用于未加密代码的临时存储,打包结束后需要放会raw文件夹中)
需copy如下代码:
gradle.addBuildListener(new BuildListener() { @Override void buildStarted(Gradle gradle) { println "buildStarted" } @Override void settingsEvaluated(Settings settings) { println "settingsEvaluated" } @Override void projectsLoaded(Gradle gradle) { println "projectsLoaded" } @Override void projectsEvaluated(Gradle gradle) { println "projectsEvaluated" copyFolder(rawDir,tempDir) encodeDir(rawDir,aesKeyCommen) } @Override void buildFinished(BuildResult buildResult) { copyFolder(tempDir,rawDir); deleteAllFilesOfDir(tempDir); } })
第二步:在build.gradle中实现上步骤的方法copyFolder,encodeDir,deleteAllFileofDir等方法,
gradle打包兼容java代码,下面贴出这些方法的实现:
//加密的资源文件路径 def rawDir ='./app/src/main/res/raw/' //资源文件临时存储文件夹名称 def tempDir ='./tempDir' //加密的key def aesKey = "\"abcdefgabcdefg12\"" def aesKeyCommen = "abcdefgabcdefg12" //拷贝文件夹 void copyFolder(String oldPath, String newPath) { try { (new File(newPath)).mkdirs(); //如果文件夹不存在 则建立新文件夹 File a = new File(oldPath); String[] file = a.list(); File temp = null; for (int i = 0; i < file.length; i++) { if (oldPath.endsWith(File.separator)) { temp = new File(oldPath + file[i]); } else { temp = new File(oldPath + File.separator + file[i]); } if (temp.isFile()) { FileInputStream input = new FileInputStream(temp); FileOutputStream output = new FileOutputStream(newPath + "/" + (temp.getName()).toString()); byte[] b = new byte[1024 * 5]; int len; while ((len = input.read(b)) != -1) { output.write(b, 0, len); } output.flush(); output.close(); input.close(); } if (temp.isDirectory()) {//如果是子文件夹 copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]); } } } catch (Exception e) { println("复制整个文件夹内容操作出错"); e.printStackTrace(); } } //删除文件夹 void deleteAllFilesOfDir(String path) { File file=new File(path); if (!file.exists()) return; if (file.isFile()) { file.delete(); return; } File[] files = file.listFiles(); for (int i = 0; i < files.length; i++) { deleteAllFilesOfDir(files[i].getAbsolutePath()); } file.delete(); } //读取文件到string static String file2String(File file, String encoding) { InputStreamReader reader = null; StringWriter writer = new StringWriter(); try { if (encoding == null || "".equals(encoding.trim())) { reader = new InputStreamReader(new FileInputStream(file), encoding); } else { reader = new InputStreamReader(new FileInputStream(file)); } //将输入流写入输出流 char[] buffer = new char[1024]; int n = 0; while (-1 != (n = reader.read(buffer))) { writer.write(buffer, 0, n); } } catch (Exception e) { e.printStackTrace(); return null; } finally { if (reader != null) try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } //返回转换结果 if (writer != null) return writer.toString(); else return null; } //加密算法 private static byte[] encrypt(String content, String password) { try { byte[] keyStr = getKey(password); SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//algorithmStr byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, key);// ʼ byte[] result = cipher.doFinal(byteContent); return result; // } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } //解密算法 private static byte[] decrypt(byte[] content, String password) { try { byte[] keyStr = getKey(password); SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//algorithmStr cipher.init(Cipher.DECRYPT_MODE, key);// ʼ byte[] result = cipher.doFinal(content); return result; // } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } private static byte[] getKey(String password) { byte[] rByte = null; if (password!=null) { rByte = password.getBytes(); }else{ rByte = new byte[24]; } return rByte; } //二进制转16进制 static String parseByte2HexStr(byte[] buf) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < buf.length; i++) { String hex = Integer.toHexString(buf[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } static byte[] parseHexStr2Byte(String hexStr) { if (hexStr.length() < 1) return null; byte[] result = new byte[hexStr.length() / 2]; for (int i = 0; i < hexStr.length() / 2; i++) { int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); result[i] = (byte) (high * 16 + low); } return result; } //加密方法 static String encodeContent(String content, String keyBytes){ //加密之后的字节数组,转成16进制的字符串形式输出 return parseByte2HexStr(encrypt(content, keyBytes)); } //解密方法 static String decodeContent(String content, String keyBytes){ //解密之前,先将输入的字符串按照16进制转成二进制的字节数组,作为待解密的内容输入 byte[] b = decrypt(parseHexStr2Byte(content), keyBytes); return new String(b); } //projectsEvaluated里调用的方法 aesKey: key rawDir:加密的文件夹 void encodeDir(String rawDir, String aesKey){ println "do 加密代码" File searchPlug = new File(rawDir); if (searchPlug.exists() && searchPlug.isDirectory()) { print "文件夹存在" File[] files = searchPlug.listFiles() for (File file : files) { if(!file.name.endsWith(".glsl")){ continue } String str=file2String(file,"utf-8") def content = encodeContent(str, aesKey) // def result = decodeContent(content, aesKey) // println(" 原始文件:content"+str) // println(" 加密后文件:content"+content) // println(" 解密后文件:content"+result) def stream = file.newOutputStream() stream.write(content.bytes) stream.flush() } } }
第三步:在gradle和android程序中实现加密key的共享
在gradle文件中增加代码
defaultConfig { buildConfigField "String", "AES_KEY",aesKey }
在android代码中利用BuildConfig.AES_KEY获取build.gradle文件中配置的key。
注:在gradle文件中使用的key用def aesKeyCommen = “abcdefgabcdefg12”
在 buildConfigField 里需要传入的String为: “\”abcdefgabcdefg12\””
因为gradle生成java类时会默认省掉“”。
第四步:android程序里解密:
1 . 新建工具类:
public class AESUtils { private static byte[] encrypt(String content, String password) { try { byte[] keyStr = getKey(password); SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//algorithmStr byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, key);// ʼ byte[] result = cipher.doFinal(byteContent); return result; // } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } private static byte[] decrypt(byte[] content, String password) { try { byte[] keyStr = getKey(password); SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//algorithmStr cipher.init(Cipher.DECRYPT_MODE, key);// ʼ byte[] result = cipher.doFinal(content); return result; // } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } private static byte[] getKey(String password) { byte[] rByte = null; if (password!=null) { rByte = password.getBytes(); }else{ rByte = new byte[24]; } return rByte; } /** * 将二进制转换成16进制 * @param buf * @return */ public static String parseByte2HexStr(byte buf[]) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < buf.length; i++) { String hex = Integer.toHexString(buf[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } /** * 将16进制转换为二进制 * @param hexStr * @return */ public static byte[] parseHexStr2Byte(String hexStr) { if (hexStr.length() < 1) return null; byte[] result = new byte[hexStr.length() / 2]; for (int i = 0; i < hexStr.length() / 2; i++) { int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); result[i] = (byte) (high * 16 + low); } return result; } /** *加密 */ public static String encode(String content,String keyBytes){ //加密之后的字节数组,转成16进制的字符串形式输出 return parseByte2HexStr(encrypt(content, keyBytes)); } /** *解密 */ public static String decode(String content,String keyBytes){ //解密之前,先将输入的字符串按照16进制转成二进制的字节数组,作为待解密的内容输入 byte[] b = decrypt(parseHexStr2Byte(content), keyBytes); return new String(b); } }
2 . 读取raw资源文件,并进行解密
public static String readShaderFromRawResource(final int resourceId) { final InputStream inputStream = CameraApplication.getInstance().getResources().openRawResource( resourceId); final InputStreamReader inputStreamReader; try { inputStreamReader = new InputStreamReader(inputStream, "utf-8"); final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String nextLine; final StringBuilder body = new StringBuilder(); try { while ((nextLine = bufferedReader.readLine()) != null) { body.append(nextLine); body.append('\n'); } } catch (IOException e) { return null; } //AESUtils.decode是解密方法,BuildConfig.AES_KEY,为gradle中配置的key String decrypt = AESUtils.decode(body.toString(), BuildConfig.AES_KEY); return decrypt; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return ""; }
第五步:大功告成,解压生成的apk,然后查看raw资源文件,即可看到文件内容为3134141425425 的十六进制构成,而代码中的raw文件还是原来的代码,没有发生任何变化
相关文章推荐
- Android Studio下通过Gradle配置实现资源文件的模块化
- 加密weblogic 用户名和口令到文件 来避免在脚本中使用硬编码来实现对资源的访问
- Android资源文件strings实现特殊字符转义
- Android Library 工程实现模块复用 (代码及资源文件)
- 一键自动发布ipa(更新svn,拷贝资源,压缩资源,加密图片资源,加密数据文件,加密lua脚本,编译代码,ipa签名,上传ftp)
- android studio重命名 string 资源的文件名字
- 动态加载资源属性文件实现方案
- 【Java】Swing+IO流实现一个简单的文件加密程序(demo版)
- 实现iOS图片等资源文件的热更新化(三):动态的资源文件夹
- cocos2d-x 对引擎修改,以实现加密资源
- res/raw下的资源文件读写
- 将应用raw里的文件copy到sd卡实现(转)
- 基于魔兽哈希算法的Ogre资源文件扩展的设计与实现
- Android Studio导入第三方包(资源)方法,ViewPager+TabLayout的使用,ViewPager单独使用实现无限循环
- 创建一个自定义类加载器实现class文件(字节码文件)的加密解密的实例
- android studio 如何清理没有用到的资源文件
- 使用AES加密游戏资源文件
- java实现将资源文件转化成sql语句导入数据库
- Java实现的读取资源文件工具类ResourcesUtil实例【可动态更改值的内容】
- Java字节码文件保护方法之字节码加密实现(方法及伪码)