在运营某些项目时,我们可能需要使用到第三方的服务器来存储数据和文件,对于文本的加密,我们可以用很多简单的对称算法,比如DES,加密后再在网络中传输,接收方再通过秘钥解密即可。但是对于文件的加密,却相对复杂一点。在实际业务中,我遇到了一个问题,不能让图片被第三方使用,存储到云服务器的图片也不能被相应的服务商查看。(国内的像阿里云,又拍云,七牛对是不会允许一些敏感文件存储的)。那怎么实现这些敏感文件的存储呢。以下是我提出的解决方案,以安卓为例。
文件头是位于文件开头的一段承担一定任务的数据,一般都在开头的部分,解决方案就是修改文件头的内容。关于文件头的内容可以自行百度。
1.文件实现加密后上传
- private static void encrypt(File file) throws IOException {
- int key=123456;
- RandomAccessFile raf = null;
- try {
- raf = new RandomAccessFile(file, "rw");
- raf.seek(0);
- byte[] b = new byte[8];
- raf.read(b,0,b.length);
- byte[] newbyte=new byte[8];
- for(int i=0;i<b.length;i++){
- newbyte[i]=(byte)(b[i]^key);
- }
- raf.seek(0);
- raf.write(newbyte,0,newbyte.length);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (raf != null) {
- try {
- raf.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
获取文件的前8个字节内容,通过与秘钥key进行与运算得到新值,然后再写入头部。这样子文件的信息就被打乱了,使用一般的软件是不能正确读取文件的。
2.显示解密。因为文件在从网络上获取的时候是以流的形式传输的,边传输边解密就不会影响程序性能。
在android应用程序中,我使用的 Universal Image Loader,这个插件支持用户扩展图片下载器(imageDownloader)和图片解析器(imageDecoder)。
- public class MyImageDownloader extends BaseImageDownloader {
- public MyImageDownloader (Context context) {
- super(context);
- }
- public MyImageDownloader (Context context, int connectTimeout, int readTimeout) {
- super(context, connectTimeout, readTimeout);
- }
- @Override
- protected InputStream getStreamFromNetwork(String imageUri, Object extra) throws IOException {
- return new MyInputSream(super.getStreamFromNetwork(imageUri, extra));
- }
- private class MyInputSream extends InputStream {
- private final InputStream inputStream;
- private int i=0;
- private int key=123456;
- private MyInputSream(InputStream inputStream) {
- this.inputStream = inputStream;
- }
- @Override
- public int read() throws IOException {
- int buffer = inputStream.read();
- i++;
- if(i<=8){
- buffer= buffer ^ key;
- }
- return buffer;
- }
- }
- }
解密只需要创建一个继承InputStream的类,重写 read方法,对前8个字节的内容再进行与操作,就得到了加密前的内容。