前言
最近公司需要对本公司的一些下载文件进行加密解密需求,也就尝试去实现下,其实需要借助第三方的jar包:bcprov-jdk15on-155.jar,下载这个可以到网上搜或者下载本人的demo即可,注意:需要加密和解密的key是一致的才可以解密,不然就会解密失败。不多说,直接上代码。
效果图
代码:
实现加密解密逻辑代码
- package com.vsoontech.p2p.sample;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.security.InvalidKeyException;
- import java.security.Key;
- import java.security.NoSuchAlgorithmException;
- import java.security.SecureRandom;
- import javax.crypto.BadPaddingException;
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.KeyGenerator;
- import javax.crypto.NoSuchPaddingException;
- import javax.crypto.ShortBufferException;
- /**
- * @author zhou
- * @since 2016/9/26
- */
- public enum AES {
- INSTANCE;
- private Key key;
- /**
- * 生成AES对称秘钥
- */
- public String generateKey() throws NoSuchAlgorithmException {
- KeyGenerator keygen = KeyGenerator.getInstance("AES");
- SecureRandom random = new SecureRandom();
- keygen.init(random);
- this.key = keygen.generateKey();
- return "Algorithm Format Encoded:" + key.getAlgorithm() + " - " + key.getFormat() + " - " + new String(key.getEncoded());
- }
- /**
- * 加密
- */
- public void encrypt(InputStream in) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
- this.crypt(in, null, Cipher.ENCRYPT_MODE);
- }
- /**
- * 解密
- */
- public String decrypt(InputStream in) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
- return this.crypt(in, Cipher.DECRYPT_MODE);
- }
- /**
- * 加密
- */
- public void encrypt(InputStream in, OutputStream out) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
- this.crypt(in, out, Cipher.ENCRYPT_MODE);
- }
- /**
- * 解密
- */
- public void decrypt(InputStream in, OutputStream out) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
- this.crypt(in, out, Cipher.DECRYPT_MODE);
- }
- /**
- * 实际的加密解密过程
- */
- public void crypt(InputStream in, OutputStream out, int mode) throws IOException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
- Cipher cipher = Cipher.getInstance("AES");
- cipher.init(mode, this.key);
- int blockSize = cipher.getBlockSize();
- int outputSize = cipher.getOutputSize(blockSize);
- byte[] inBytes = new byte[blockSize];
- byte[] outBytes = new byte[outputSize];
- int inLength = 0;
- boolean more = true;
- while (more) {
- inLength = in.read(inBytes);
- if (inLength == blockSize) { //只要输入数据块具有全长度(长度可被8整除),调用update方法
- int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
- if (out != null) out.write(outBytes, 0, outLength);
- } else {
- more = false;
- }
- }
- if (inLength > 0) //不具有全长度,调用doFinal方法
- outBytes = cipher.doFinal(inBytes, 0, inLength);
- else
- outBytes = cipher.doFinal();
- if (out != null) {
- out.write(outBytes);
- out.flush();
- }
- }
- /**
- * 实际的加密解密过程
- */
- public String crypt(InputStream in, int mode) throws IOException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
- Cipher cipher = Cipher.getInstance("AES");
- cipher.init(mode, this.key);
- int blockSize = cipher.getBlockSize();
- int outputSize = cipher.getOutputSize(blockSize);
- byte[] inBytes = new byte[blockSize];
- byte[] outBytes = new byte[outputSize];
- int inLength = 0;
- boolean more = true;
- StringBuilder sb = new StringBuilder();
- while (more) {
- inLength = in.read(inBytes);
- if (inLength == blockSize) { //只要输入数据块具有全长度(长度可被8整除),调用update方法
- int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
- } else {
- more = false;
- }
- }
- if (inLength > 0) //不具有全长度,调用doFinal方法
- outBytes = cipher.doFinal(inBytes, 0, inLength);
- else
- outBytes = cipher.doFinal();
- sb.append(new String(outBytes));
- return sb.toString();
- }
- public void setKey(Key key) {
- this.key = key;
- }
- public Key getKey() {
- return key;
- }
- }
生成秘钥代码
- package com.vsoontech.p2p.sample;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.security.Key;
- import java.security.NoSuchAlgorithmException;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.IvParameterSpec;
- import javax.crypto.spec.SecretKeySpec;
- /**
- * @author zhou
- * @since 2016/9/26
- */
- public class AESKeyModel {
- public static final String KEY_ALGORITHM = "AES";
- private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
- private String srcFile = "", destionFile = "";
- /**
- * 初始化密钥
- *
- * @return byte[] 密钥
- * @throws Exception
- */
- public byte[] initSecretKey() {
- //返回生成指定算法的秘密密钥的 KeyGenerator 对象
- KeyGenerator kg = null;
- try {
- kg = KeyGenerator.getInstance(KEY_ALGORITHM);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- return new byte[0];
- }
- //初始化此密钥生成器,使其具有确定的密钥大小
- //AES 要求密钥长度为 128
- kg.init(128);
- //生成一个密钥
- SecretKey secretKey = kg.generateKey();
- return secretKey.getEncoded();
- }
- public void setDestionFile(String destionFile) {
- this.destionFile = destionFile;
- }
- public void setSrcFile(String srcFile) {
- this.srcFile = srcFile;
- }
- /**
- * 转换密钥
- *
- * @param key 二进制密钥
- * @return 密钥
- */
- private static Key toKey(byte[] key) {
- //生成密钥
- return new SecretKeySpec(key, KEY_ALGORITHM);
- }
- /**
- * 加密
- *
- * @param data 待加密数据
- * @param key 密钥
- * @return byte[] 加密数据
- * @throws Exception
- */
- public static byte[] encrypt(byte[] data, Key key) throws Exception {
- return encrypt(data, key, DEFAULT_CIPHER_ALGORITHM);
- }
- /**
- * 加密
- *
- * @param data 待加密数据
- * @param key 二进制密钥
- * @return byte[] 加密数据
- * @throws Exception
- */
- public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
- return encrypt(data, key, DEFAULT_CIPHER_ALGORITHM);
- }
- /**
- * 加密
- *
- * @param data 待加密数据
- * @param key 二进制密钥
- * @param cipherAlgorithm 加密算法/工作模式/填充方式
- * @return byte[] 加密数据
- * @throws Exception
- */
- public static byte[] encrypt(byte[] data, byte[] key, String cipherAlgorithm) throws Exception {
- //还原密钥
- Key k = toKey(key);
- return encrypt(data, k, cipherAlgorithm);
- }
- /**
- * 加密
- *
- * @param data 待加密数据
- * @param key 密钥
- * @param cipherAlgorithm 加密算法/工作模式/填充方式
- * @return byte[] 加密数据
- * @throws Exception
- */
- public static byte[] encrypt(byte[] data, Key key, String cipherAlgorithm) throws Exception {
- //实例化
- Cipher cipher = Cipher.getInstance(cipherAlgorithm);
- //使用密钥初始化,设置为加密模式
- cipher.init(Cipher.ENCRYPT_MODE, key);
- //执行操作
- return cipher.doFinal(data);
- }
- /**
- * 解密
- *
- * @param data 待解密数据
- * @param key 二进制密钥
- * @return byte[] 解密数据
- * @throws Exception
- */
- public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
- return decrypt(data, key, DEFAULT_CIPHER_ALGORITHM);
- }
- /**
- * 解密
- *
- * @param data 待解密数据
- * @param key 密钥
- * @return byte[] 解密数据
- * @throws Exception
- */
- public static byte[] decrypt(byte[] data, Key key) throws Exception {
- return decrypt(data, key, DEFAULT_CIPHER_ALGORITHM);
- }
- /**
- * 解密
- *
- * @param data 待解密数据
- * @param key 二进制密钥
- * @param cipherAlgorithm 加密算法/工作模式/填充方式
- * @return byte[] 解密数据
- * @throws Exception
- */
- public static byte[] decrypt(byte[] data, byte[] key, String cipherAlgorithm) throws Exception {
- //还原密钥
- Key k = toKey(key);
- return decrypt(data, k, cipherAlgorithm);
- }
- /**
- * 解密
- *
- * @param data 待解密数据
- * @param key 密钥
- * @param cipherAlgorithm 加密算法/工作模式/填充方式
- * @return byte[] 解密数据
- * @throws Exception
- */
- public static byte[] decrypt(byte[] data, Key key, String cipherAlgorithm) throws Exception {
- //实例化
- Cipher cipher = Cipher.getInstance(cipherAlgorithm);
- //使用密钥初始化,设置为解密模式
- cipher.init(Cipher.DECRYPT_MODE, key);
- //执行操作
- return cipher.doFinal(data);
- }
- public void encryptionFile(Key sessionKey) throws Exception {
- int len = 0;
- byte[] buffer = new byte[1024];
- byte[] cipherbuffer = null;
- // 使用会话密钥对文件加密。
- Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM, new BouncyCastleProvider());
- IvParameterSpec iv = new IvParameterSpec("0000000000123456".getBytes());
- cipher.init(Cipher.ENCRYPT_MODE, sessionKey, iv);
- FileInputStream fis = new FileInputStream(new File(srcFile));
- FileOutputStream fos = new FileOutputStream(new File(destionFile));
- // 读取原文,加密并写密文到输出文件。
- while ((len = fis.read(buffer)) != -1) {
- cipherbuffer = cipher.update(buffer, 0, len);
- fos.write(cipherbuffer);
- fos.flush();
- }
- cipherbuffer = cipher.doFinal();
- fos.write(cipherbuffer);
- fos.flush();
- if (fis != null)
- fis.close();
- if (fos != null)
- fos.close();
- }
- public void descryptionFile(Key sessionKey) throws Exception {
- int len = 0;
- byte[] buffer = new byte[5 * 1024];
- byte[] plainbuffer = null;
- Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM, new BouncyCastleProvider());
- IvParameterSpec iv = new IvParameterSpec("0000000000123456".getBytes());
- cipher.init(Cipher.DECRYPT_MODE, sessionKey, iv);
- FileInputStream fis = new FileInputStream(new File(srcFile));
- FileOutputStream fos = new FileOutputStream(new File(destionFile));
- while ((len = fis.read(buffer)) != -1) {
- plainbuffer = cipher.update(buffer, 0, len);
- fos.write(plainbuffer);
- fos.flush();
- }
- plainbuffer = cipher.doFinal();
- fos.write(plainbuffer);
- fos.flush();
- if (fis != null)
- fis.close();
- if (fos != null)
- fos.close();
- }
- }
- /**
- * 加密
- *
- * @param path
- * @param destionFile
- */
- private void aes(String path, String destionFile) {
- try {
- Log.d(TAG, "aes Key: " + AES.INSTANCE.generateKey());
- FileInputStream fis = new FileInputStream(new File(path));
- FileOutputStream fos = new FileOutputStream(new File(destionFile));
- AES.INSTANCE.encrypt(fis, fos);
- } catch (Exception e) {
- Log.d(TAG, "Exception: " + e.toString());
- e.printStackTrace();
- }
- }
解密逻辑示例代码:
- /**
- * AES解密文件
- *
- * @param path 需要解密的文件目录
- */
- private void aesJieMi(String path) {
- File f = new File(path);
- if (!f.exists() || f.isDirectory())
- Toast.makeText(getApplicationContext(), "该文件不合法!", Toast.LENGTH_SHORT).show();
- else {
- String prefix = f.getName().substring(0, f.getName().indexOf('.'));
- String suffix = f.getName().substring(f.getName().indexOf('.'));
- String outjiemiFile = Environment.getExternalStorageDirectory() + File.separator + prefix + "AES_jieMi" + suffix;
- AESKeyModel model_aes = new AESKeyModel();
- model_aes.setSrcFile(path);
- model_aes.setDestionFile(outjiemiFile);
- try {
- // model_aes.descryptionFile(key_AES);
- model_aes.descryptionFile(key_aes);
- // TODO: 加密后的文件
- RandomAccessFile raf = new RandomAccessFile(path, "rw");
- Log.d(TAG, "解密后 file length: " + raf.length());
- Log.d(TAG, "解密后 file content: " + raf.readLine());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
总结:
注意秘钥需要一致。
代码链接地址: 点击打开链接