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技術分享,掃碼關注微信公眾號##
-
——只要你學會了之前所不會的東西,只要今天的你強過了昨天的你,那你就一直是在進階的路上了。