最近在作一個項目,須要將資源文件(包括圖片、動畫等類型)進行簡單的加密後再上傳至雲上的服務器,而在應用程序中對該資源使用前先將讀取到的文件數據進行解密以獲得真正的文件信息。此策略的緣由與好處是將準備好的資源存儲在雲上,使用時經過網絡進行讀取便可,減小了應用程序自己的大小。這一點對於移動應用尤爲重要,特別是在資源量較大且須要對其進行保護的時候。畢竟在目前所處的大環境下,要想複製一款軟件不難,那真正寶貴的就是不容易找到的資源了。java
先對文件與加密的相關知識作一個極爲簡單的科普(知道的能夠跳過)。算法
文件與字串服務器
A、文件的操做流程通常爲:打開-->讀取-->對內容進行變換-->寫入-->關閉。網絡
B、常規性文件操做會用到的類有五個:File,InputStream,OutputStream,FileInoutStream,FileOutputStream,均包含在java.io下面。注意,在使用前必須對類文件進行導入,方法爲import java.io.File(實現時須要分號結尾)。函數
C、建立InputStream類和OutputStream類的對象時,new關鍵字後邊的類分別是FileInputStream和FileOutputStream(而不是其自身),如InputStream fin = new FileInputStream(File objectFile)。能夠看出構造參數是File類型對象,其建立方式爲File file = new File(String fileName)。測試
D、當String類對象做爲函數參數時,能夠直接傳入常量字符串,如「D:\\source.jpg」。String類對象構造方法中比較簡單也是最經常使用的一種是String string = 「string content」,固然,最終執行的是String string = new String(「string content」)。其實String是很是重要的類(能夠說無處不在),提供了一套完善、高效操做字串的方法,使得開發者受益不淺。動畫
E、常規性文件操做涉及到的方法有五個:exist(),read(),write(),flush(),close()。exist()判斷文件是否存在,調用者爲File類對象;read()讀取輸入流中的內容,調用者爲InputStream類對象;write()、flush()、close()的做用分別爲向輸出流中寫內容、強制發送緩衝區中數據、保存並關閉文件,調用者爲OutputStream類對象,不過InputStream類對象在操做完成後也須要close()。加密
加密算法spa
MD5:以512位分組來處理輸入的信息,且每一分組又被劃分爲16個32位子分組,通過了一系列的處理後,輸出由四個32位分組組成,將這四個32位分組級聯後將生成一個128位散列值。3d
SHA:接收一段明文,而後以一種不可逆的方式將它轉換成一段(一般更小)密文,也能夠簡單的理解爲取一串輸入碼(稱爲預映射或信息),並把它們轉化爲長度較短、位數固定的輸出序列即散列值(也稱爲信息摘要或信息認證代碼)的過程。
DES:把64位的明文輸入塊變爲64位的密文輸出塊,它所使用的密鑰也是64位,主要分爲兩步:
(1)初始置換,把輸入的64位數據塊按位從新組合,並把輸出分爲L0、R0兩部分,每部分各長32位,其置換規則爲將輸入的第58位換到第一位,第50位換到第2位......依此類推,最後一位是原來的第7位。L0、R0則是換位輸出後的兩部分,L0是輸出的左32位,R0是右32位。
(2)逆置換,通過16次迭代運算後,獲得L1六、R16,將此做爲輸入,進行逆置換,逆置換正好是初始置換的逆運算,由此即獲得密文輸出。
3-DES:使用3條56位的密鑰對數據進行三次加密,是DES向AES過渡的加密算法(1999年,NIST將3-DES指定爲過渡的加密標準)。
AES:使用12八、19二、和256位密鑰,而且用128位分組加密和解密數據。
異或:與其說這是一種加密算法,倒不如稱其爲文件信息的簡單變換,將每個數據與某給定數據進行異或操做便可完成加密或解密,如dataEncrypt = dataSource^dataSecret。
OK,是時候回到文件加密與解密的具體實現這個主題上來了。後續的舉例均採用圖片(包括GIF動畫)類型,而其餘類型資源的實現原理相同,就不一一給出了。首先來看對一幅JPG類型圖片進行異或加密的Java實現,因爲是第一次給出代碼,因此貼上了Java文件「FileEncAndDec.java」的全部內容。
1 import java.io.File; 2 import java.io.InputStream; 3 import java.io.OutputStream; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 7 public class FileEncAndDec { 8 private static final int numOfEncAndDec = 0x99; //加密解密祕鑰 9 private static int dataOfFile = 0; //文件字節內容 10 public static void main(String[] args) { 11 12 File srcFile = new File("桌面.jpg"); //初始文件 13 File encFile = new File("encFile.tif"); //加密文件 14 File decFile = new File("decFile.bmp"); //解密文件 15 16 try { 17 EncFile(srcFile, encFile); //加密操做 18 } catch (Exception e) { 19 e.printStackTrace(); 20 } 21 } 22 23 private static void EncFile(File srcFile, File encFile) throws Exception { 24 if(!srcFile.exists()){ 25 System.out.println("source file not exixt"); 26 return; 27 } 28 29 if(!encFile.exists()){ 30 System.out.println("encrypt file created"); 31 encFile.createNewFile(); 32 } 33 InputStream fis = new FileInputStream(srcFile); 34 OutputStream fos = new FileOutputStream(encFile); 35 36 while ((dataOfFile = fis.read()) > -1) { 37 fos.write(dataOfFile^numOfEncAndDec); 38 } 39 40 fis.close(); 41 fos.flush(); 42 fos.close(); 43 } 44 }
從代碼能夠看出,給定的加密祕鑰(異或數據,能夠在合法範圍內隨便定義)爲十六進制數0x99。圖片資源爲以中文命名的「桌面.jpg」,加密文件爲「encFile.png」,還有值爲「decFile.bmp」的String類對象做爲解密文件名稱。
相對應地,解密的實現幾乎和加密相同,只是輸入與輸出文件不一樣,看下面代碼。
1 private static void DecFile(File encFile, File decFile) throws Exception { 2 if(!encFile.exists()){ 3 System.out.println("encrypt file not exixt"); 4 return; 5 } 6 7 if(!decFile.exists()){ 8 System.out.println("decrypt file created"); 9 decFile.createNewFile(); 10 } 11 12 InputStream fis = new FileInputStream(encFile); 13 OutputStream fos = new FileOutputStream(decFile); 14 15 while ((dataOfFile = fis.read()) > -1) { 16 fos.write(dataOfFile^numOfEncAndDec); 17 } 18 19 fis.close(); 20 fos.flush(); 21 fos.close(); 22 }
因爲加密後的圖片文件(保存爲PNG類型)是不能直接在圖片查看器中打開的,由於其內容已經改變,因此其縮略圖標會顯示爲兩朵不一樣顏色的花。對於其餘類型的加密或損壞文件的縮略圖標:JPG爲山水畫,BMP和TIF爲畫刷塗鴉,GIF爲三個不一樣顏色的幾何圖形。固然,這些默認的圖標應該會因系統而異。
下面給出初始、加密及解密後的圖標截圖:
和預想的一致,經測試發現以上方法對GIF動畫(不是GIF圖片,而是能夠播放的動畫資源)的加密與解密一樣適用,代碼和截圖也就沒有區別了,不過仍是貼上來:
1 File srcFile = new File("srcFile.gif"); //初始文件 2 File encFile = new File("encFile.gif"); //加密文件 3 File decFile = new File("decFile.gif"); //解密文件
有兩點須要注意:
一、在調用加密與解密方法時,必須加上異常處理塊(try{...}catch{...},不然編譯不經過)。
二、對用來加密或解密的源文件進行打開(讀取)操做以前,最好判斷其是否存在,省得形成意想不到的錯誤和時間的浪費。由於若文件不存在,後續的操做都是沒有意義的。
今天就先寫到這,總結一下吧。文件加密簡單地說就是對數據進行變換,雖然一千種方法可能會有一千種一種結果,可是思想是通用的。關鍵是加密所採用的算法的難易,有時間會對文中提到的算法用Java進行實現。