AES和DES程式碼實現

YunSoul發表於2018-08-22

DES是一種對稱加密演算法,所謂對稱加密演算法即:加密和解密使用相同金鑰的演算法。因為DES使用56位金鑰,以現代計算能力,24小時內即可被破解。雖然如此,在某些簡單應用中,我們還是可以使用DES加密演算法。

AES已經變成目前對稱加密中最流行演算法之一;AES可以使用128、192、和256位金鑰,並且用128位分組加密和解密資料。

package com.zyt;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.lang.reflect.Array;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;

/**
/**
 * @ClassName: Test_DES_AES 
 * @Model : (所屬模組名稱)
 * @Description: (這裡用一句話描述這個類的作用) 
 * @author Administrator 
 * @date 2017年6月20日 下午3:02:45 
 */
public class Test_DES_AES {

    /**
    /**
     * main (這裡用一句話描述這個方法的作用) 
     * @param args
     * void 
     * @ModifiedPerson Administrator
     * @date 2017年6月20日 下午3:02:45 
     */
    public static void main(String[] args) {
        //*****************************AES或DES加密 解密字串*****************************
        //待加密內容  
        String str = "test";  
        //密碼,長度要是8的倍數  
        String password = "12345678aa";  
        
        byte[] desEncryptResult = DESEncrypt(str.getBytes(), password);
        System.out.println("DES加密‘測試內容’的結果是:" + new String(desEncryptResult));
        
        byte[] desDecrypt = DESDecrypt(desEncryptResult, password);
        System.out.println("DES解密的結果是:" + new String(desDecrypt));
        

        byte[] aesEncrypt = AESEncrypt(str, password);
        System.out.println("AES加密‘測試內容’的結果是:" + new String(aesEncrypt));
        
        byte[] aesDecrypt = AESDecrypt(aesEncrypt, password);
        System.out.println("AES解密的結果是:" + new String(aesDecrypt));
        
        //String srcFilePath = "D:\\11.txt";//原檔案
        String srcFilePath = "assets/11.txt";//原檔案

        //***************************** DES加密 解密檔案*****************************
        String encryptedFilePath = "assets/DES加密.txt";//加密後的檔案
        String decryptedFilePath = "assets/DES解密.txt";//解密後的檔案
        DESEncryptFile(srcFilePath, encryptedFilePath, password);
        DESDecryptFile(encryptedFilePath, decryptedFilePath, password);
        
        //***************************** AES加密 解密檔案  *****************************
        String AESencryptedFilePath = "assets/AES加密.txt";//加密後的檔案
        String AESdecryptedFilePath = "assets/AES解密.txt";//解密後的檔案
        AESEncryptFile(srcFilePath, AESencryptedFilePath, password);
        AESDecryptFile(AESencryptedFilePath, AESdecryptedFilePath, password);
    }
    
    //  注意:DES加密和解密過程中,金鑰password長度都必須是8的倍數
    public static byte[] DESEncrypt(byte[] datasource, String password){
        
        try {
            // DES演算法要求有一個可信任的隨機數源
            SecureRandom secureRandom = new SecureRandom();
            // 從原始密匙資料建立DESKeySpec物件
            DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
            // 建立一個密匙工廠,
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            //把DESKeySpec轉換成一個SecretKey物件
            SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
            // Cipher物件實際完成加密操作
            Cipher cipher = Cipher.getInstance("DES");
            //用密匙初始化Cipher物件  
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, secureRandom);
                                   
            // 執行加密操作
            return cipher.doFinal(datasource);
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return null;
    }
    
    //  注意:DES加密和解密過程中,金鑰password長度都必須是8的倍數
    public static byte[] DESDecrypt(byte[] encrypted, String password){
        try {
            // DES演算法要求有一個可信任的隨機數源
            SecureRandom secureRandom = new SecureRandom();
            // 建立一個DESKeySpec物件  
            DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
            // 建立一個密匙工廠  
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            // 將DESKeySpec物件轉換成SecretKey物件  
            SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
            // Cipher物件實際完成解密操作  
            Cipher cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher物件  
            cipher.init(Cipher.DECRYPT_MODE, secretKey, secureRandom);
            // 真正開始解密操作  
            return cipher.doFinal(encrypted);
            
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        
        return null;
    }
    
  //DES解密檔案
    public static void DESDecryptFile(String encryptedFilePath, String decryptedFilePath, String password) {
        try {
            
            // DES演算法要求有一個可信任的隨機數源
            SecureRandom secureRandom = new SecureRandom();
            // 從原始密匙資料建立DESKeySpec物件
            DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
            // 建立一個密匙工廠,
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            //把DESKeySpec轉換成一個SecretKey物件
            SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
            // Cipher物件實際完成加密操作
            Cipher cipher = Cipher.getInstance("DES");
            //用密匙初始化Cipher物件  
            cipher.init(Cipher.DECRYPT_MODE, secretKey, secureRandom);
            
            //將檔案中的資料讀入
            FileInputStream fis = new FileInputStream(encryptedFilePath);
            //輸出解密資料到檔案
            FileOutputStream fos = new FileOutputStream(decryptedFilePath);
            

            //方法一:
            /*CipherInputStream cis = new CipherInputStream(fis, cipher);
            byte[] b = new byte[1024];
            int i = 0;
            while( (i = cis.read(b)) != -1 ){
                fos.write(b, 0, i);
            }
            
            cis.close();
            */
            

            //方法二:
            byte[] bb = new byte[1024];
            int l = 0;
            while((l = fis.read(bb)) != -1){
                byte[] doFinal = cipher.doFinal(Arrays.copyOfRange(bb, 0, l));
                fos.write(doFinal, 0, doFinal.length);
            }
            
            fos.close();
            fis.close();

            System.out.println("DES解密檔案結束");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        
    }

    //DES加密檔案
    public static void DESEncryptFile(String srcFilePath, String desFilePath, String password) {
        try {
            
            // DES演算法要求有一個可信任的隨機數源
            SecureRandom secureRandom = new SecureRandom();
            // 從原始密匙資料建立DESKeySpec物件
            DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
            // 建立一個密匙工廠,
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            //把DESKeySpec轉換成一個SecretKey物件
            SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
            // Cipher物件實際完成加密操作
            Cipher cipher = Cipher.getInstance("DES");
            //用密匙初始化Cipher物件  
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, secureRandom);
            
            
            //將檔案中的資料讀入
            FileInputStream fis = new FileInputStream(srcFilePath);
            //輸出加密資料到檔案
            FileOutputStream fos = new FileOutputStream(desFilePath);
            
            //方法一:
            /*CipherInputStream cis = new CipherInputStream(fis, cipher);
            byte[] b = new byte[1024];
            int i = 0;
            while( (i = cis.read(b)) != -1 ){
                fos.write(b, 0, i);
            }
            cis.close();*/
            
            //方法二:
            byte[] bb = new byte[1024];
            int l = 0;
            while((l = fis.read(bb)) != -1){
                byte[] doFinal = cipher.doFinal(Arrays.copyOfRange(bb, 0, l));
                fos.write(doFinal, 0, doFinal.length);
            }
            
            fos.close();
            fis.close();

            System.out.println("DES加密檔案結束");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        
    }
    
    public static byte[] AESEncrypt(String content, String password){
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128, new SecureRandom(password.getBytes()));
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] encoded = secretKey.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(encoded, "AES");
            //建立密碼器
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            
            
            //真正的加密
            byte[] result = cipher.doFinal(content.getBytes("utf-8"));
            return result;
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return null;
    }
    
    public static byte[] AESDecrypt(byte[] content, String password){
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128, new SecureRandom(password.getBytes()));
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] encoded = secretKey.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(encoded, "AES");
            //建立解密器
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            
            
            //真正的解密
            byte[] result = cipher.doFinal(content);
            
            return result;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
        
    }
    

    //AES加密檔案
    public static void AESEncryptFile(String srcFilePath, String AESencryptedFilePath, String password) {
       
        try { SecureRandom secureRandom = new SecureRandom(password.getBytes());
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128, secureRandom);
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] encoded = secretKey.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(encoded, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            
            
            //將檔案中的資料讀入
            FileInputStream fis = new FileInputStream(srcFilePath);
            //輸出加密資料到檔案
            FileOutputStream fos = new FileOutputStream(AESencryptedFilePath);
            CipherInputStream cis = new CipherInputStream(fis, cipher);
            byte[] b = new byte[1024];
            int i = 0;
            while( (i = cis.read(b)) != -1 ){
                fos.write(b, 0, i);
            }
            
            fos.close();
            cis.close();
            fis.close();

            System.out.println("AES加密檔案結束");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }   


    //AES解密檔案
    public static void AESDecryptFile(String AESencryptedFilePath, String AESdecryptedFilePath, String password) {
        try { SecureRandom secureRandom = new SecureRandom(password.getBytes());
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128, secureRandom);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] encoded = secretKey.getEncoded();
        SecretKeySpec secretKeySpec = new SecretKeySpec(encoded, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        
        
        //將檔案中的資料讀入
        FileInputStream fis = new FileInputStream(AESencryptedFilePath);
        //輸出解密資料到檔案
        FileOutputStream fos = new FileOutputStream(AESdecryptedFilePath);
        CipherInputStream cis = new CipherInputStream(fis, cipher);
        byte[] b = new byte[1024];
        int i = 0;
        while( (i = cis.read(b)) != -1 ){
            fos.write(b, 0, i);
        }
        
        fos.close();
        cis.close();
        fis.close();

        System.out.println("AES解密檔案結束");
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
        
    }

}

複製程式碼

在Java專案中,上面的程式碼是完全能成功的,但在Android專案中,就會出現BadPaddingException: pad block corrupted in class SimpleCrypto in android,所以在Android中需要將祕鑰固定SHA1PRNG,否則會因為祕鑰不同而解密失敗。

//AES加密檔案
    public static void AESEncryptFile(InputStream is, String AESencryptedFilePath, String password) {
       
        try {
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", "Crypto");
            secureRandom.setSeed(password.getBytes());
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128, secureRandom);
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] encoded = secretKey.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(encoded, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            
            
            //輸出加密資料到檔案
            FileOutputStream fos = new FileOutputStream(AESencryptedFilePath);
            CipherInputStream cis = new CipherInputStream(is, cipher);
            byte[] b = new byte[1024];
            int i = 0;
            while( (i = cis.read(b)) != -1 ){
                fos.write(b, 0, i);
            }
            
            fos.close();
            cis.close();

            Log.i("?????", "AES加密檔案結束");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }   


    //AES解密檔案
    public static void AESDecryptFile(InputStream is, String AESdecryptedFilePath, String password) {
        try { 
            //在Android中需要將祕鑰固定SHA1PRNG,否則會因為祕鑰不同而解密失敗(BadPaddingException: pad block corrupted in class SimpleCrypto in android)
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", "Crypto");
            secureRandom.setSeed(password.getBytes());
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128, secureRandom);
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] encoded = secretKey.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(encoded, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            
            //輸出解密資料到檔案
            FileOutputStream fos = new FileOutputStream(AESdecryptedFilePath);
            CipherInputStream cis = new CipherInputStream(is, cipher);
            byte[] b = new byte[1024];
            int i = 0;
            while( (i = cis.read(b)) != -1 ){
                fos.write(b, 0, i);
            }
            
            //方法二:
            /*byte[] bb = new byte[1024];
            int l = 0;
            while((l = is.read(bb)) != -1){
                byte[] doFinal = cipher.doFinal(Arrays.copyOfRange(bb, 0, l));
                fos.write(doFinal, 0, doFinal.length);
            }
            */
            fos.close();
            cis.close();
    
            System.out.println("AES解密檔案結束");
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
        
    }
複製程式碼

#### YunSoul技術分享,掃碼關注微信公眾號##
    ——只要你學會了之前所不會的東西,只要今天的你強過了昨天的你,那你就一直是在進階的路上了。 AES和DES程式碼實現

相關文章