AES的CBC加密模式,默认iv是16个0(这个称为初始化向量),由于是分组加密,所以下一组的iv,就用前一组的加密的密文来充当,我们可以指定IV来进行加解密,加大破解难度。CFB、OFB模式类似,只不过更复杂。
废话不多说,直接上代码:
package com.irisking.scanner.util;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import android.os.Environment;
public class AesUtil {
private static int BUFFER_SIZE = 8192;
/**
* 从指定文件获取数据解密后存储到另外一个文件
*
* @param filePath 需解锁文件路径
* @param destFilePath 存储文件路径
*/
public static void decrypt(String filePath, String destFilePath) {
MoreAES aes = MoreAES.getInstances();
String keyPath = Environment.getExternalStorageDirectory().getAbsoluteFile() + "/key.dat";
byte[] byteArrays = getBytesFromDat(keyPath);
String ivPath = Environment.getExternalStorageDirectory().getAbsoluteFile() + "/iv.dat";
byte[] ivArray = getBytesFromDat(ivPath);
aes.decrypt(filePath, destFilePath, byteArrays,ivArray);
}
/**
* 获取密钥的byte数组
* @param keyPath
* @return
*/
private static byte[] getBytesFromDat(String keyPath) {
FileInputStream fis = null;
ByteArrayOutputStream baos = null;
byte[] byteArrays = null;
try {
fis = new FileInputStream(keyPath);
byte[] b = new byte[BUFFER_SIZE];
int len;
baos = new ByteArrayOutputStream();
while ((len = fis.read(b)) != -1) {
baos.write(b, 0, len);
}
byteArrays = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally{
if (fis != null) {
try {
fis.close();
} catch (IOException e) {}
}
if (baos != null) {
try {
baos.flush();
} catch (IOException e) {}
try {
baos.close();
} catch (IOException e) {}
}
}
return byteArrays;
}
}
package com.irisking.scanner.util;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.Key;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.os.Environment;
public class MoreAES {
private static String TYPE = "AES";
private static int BUFFER_SIZE = 8192;
private static MoreAES moreAes;
private MoreAES(){}
public synchronized static MoreAES getInstances(){
if(moreAes == null){
moreAes = new MoreAES();
}
return moreAes;
}
private static Cipher getCipher(int mode, byte[] key,byte[] iv) {
// mode =Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE
Cipher mCipher;
try {
mCipher = Cipher.getInstance(TYPE + "/CBC/PKCS5Padding");
Key keySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
mCipher.init(mode, keySpec, ivSpec);
return mCipher;
}catch (InvalidKeyException e) {
e.printStackTrace();
}catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}catch (NoSuchPaddingException e) {
e.printStackTrace();
}catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
/**
*
* 解密文件
* @param srcFile
* @param destFile
* @param privateKey
*/
public void decrypt(String srcFile, String destFile, byte[] privateKey,byte[] privateIv) {
byte[] readBuffer = new byte[BUFFER_SIZE];
Cipher deCipher = getCipher(Cipher.DECRYPT_MODE, privateKey,privateIv);
if (deCipher == null)
return; // init failed.
CipherInputStream fis = null;
BufferedOutputStream fos = null;
int size;
try {
fis = new CipherInputStream(new BufferedInputStream(new FileInputStream(srcFile)), deCipher);
fos = new BufferedOutputStream(new FileOutputStream(mkdirFiles(destFile)));
while ((size = fis.read(readBuffer, 0, BUFFER_SIZE)) >= 0) {
fos.write(readBuffer, 0, size);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {}
}
if (fos != null) {
try {
fos.flush();
} catch (IOException e) {}
try {
fos.close();
} catch (IOException e) {}
}
}
}
/**
* 加密文件
* @param srcFile
* @param destFile
* @param privateKey
*/
public void crypt(String srcFile, String destFile, byte[] privateKey,byte[] privateIv) {
byte[] readBuffer = new byte[BUFFER_SIZE];
Cipher enCipher = getCipher(Cipher.ENCRYPT_MODE, privateKey,privateIv);
if (enCipher == null)
return; // init failed.
CipherOutputStream fos = null;
BufferedInputStream fis = null;
int size;
try {
fos = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(destFile)), enCipher);
fis = new BufferedInputStream(new FileInputStream(mkdirFiles(srcFile)));
while ((size = fis.read(readBuffer, 0, BUFFER_SIZE)) >= 0) {
fos.write(readBuffer, 0, size);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
if (fos != null) {
try {
fos.flush();
} catch (IOException e) {
}
try {
fos.close();
} catch (IOException e) {
}
}
}
}
private static File mkdirFiles(String filePath) throws IOException {
File file = new File(filePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
return file;
}
}