admin管理员组文章数量:1639675
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); } })
- projectsEvaluated()方法执行在生成apk前。
第二步:在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实现raw资源文件加密 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1729293190a1194424.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论