/* Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface) This program is distributed under the terms of the GNU General Public License. This file is part of xFace. xFace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. xFace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with xFace. If not, see <http://www.gnu.org/licenses/>. */ package com.polyvi.xface.util; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactory; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.DESedeKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import com.polyvi.xface.exception.XCryptionException; //该类文件的加密和解密 public class XCryptor { private static final String CLASS_NAME = XCryptor.class.getSimpleName(); // 加密算法名称 private static final String RSA_ALGORITHM = "RSA"; // 处理解密数组的片段长度 private static final int DECRYPT_PART_LENGTH = 128; // 处理加密数组的片段长度 private static final int ENCRYPT_PART_LENGTH = 100; // AES加密算法 private static final String AES_ALGORITHM = "AES"; // DES加密算法 private static final String DES_ALGORITHM = "DES"; // 3DES加密算法 private static final String TRIPLE_DES_ALGORITHM = "DESede/CBC/PKCS5Padding"; private static final String KEY_ALOGRITHEM = "DESede"; // 生成的密钥的长度 private static final int KEY_SIZE = 128; /** 加解密报错提示 */ private static final String KEY_EMPTY_ERROR = "Error:key null or empty"; private static final String DATA_EMPTY_ERROR = "Error:data null or empty"; private static final String CONVERTION_ERROR = "Error: Preparing Convertion"; private static final String CRYPTION_ERROR = "Error:cryption error"; private static final String OUT_OF_MEMORY_ERROR = "Error:out of memory error"; /** * md5算法 * * @param content * [in] 需要求出md5值的内容 * * @return 返回md5值 */ public String calMD5Value(byte[] content) { if (null == content) { return null; } MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); } catch (Exception e) { XLog.e(CLASS_NAME, "Can't get instance of MD5!"); e.printStackTrace(); return null; } byte[] md5Bytes = md5.digest(content); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } /** * 计算md5值 * * @param is * [in] 需要求出md5值的内容,输入流形式 * @return */ public String calMD5Value(InputStream is) { if (null == is) { return null; } try { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] bytes = new byte[XConstant.BUFFER_LEN]; int byteCount; while ((byteCount = is.read(bytes)) > 0) { md5.update(bytes, 0, byteCount); } byte[] digest = md5.digest(); // byte[] to String StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < digest.length; i++) { int val = ((int) digest[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } catch (NoSuchAlgorithmException e) { XLog.e(CLASS_NAME, "calMD5Value(InputStream is): Can't get instance of MD5!"); e.printStackTrace(); } catch (IOException e) { XLog.e(CLASS_NAME, "calMD5Value(InputStream is): IOException"); e.printStackTrace(); } return null; } /** * 实例化Cipher * * @param key * [in] 密钥 * * @return 返回实例化的Cipher */ private Cipher instanceOfCipher(Key key) { Cipher cipher = null; try { cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, key); } catch (NoSuchAlgorithmException e) { XLog.e(CLASS_NAME, "No RSA Algorithm!"); e.printStackTrace(); return null; } catch (NoSuchPaddingException e) { XLog.e(CLASS_NAME, "Cipher init failed!"); e.printStackTrace(); return null; } catch (InvalidKeyException e) { XLog.e(CLASS_NAME, "key is a invalid key!"); e.printStackTrace(); return null; } return cipher; } /** * 通过公钥加密 * * @param data * @param publicKey * @return * @throws XCryptionException */ public byte[] encryptRSA(byte[] data, byte[] publicKey) throws XCryptionException, IllegalArgumentException { if (null == data || null == publicKey) { XLog.e(CLASS_NAME, "encryptRSA param is null!"); throw new IllegalArgumentException(); } byte[] encryptData = null; try { X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey); KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); RSAPublicKey pubKey = (RSAPublicKey) keyFactory .generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); if (null == cipher) { throw new XCryptionException(CRYPTION_ERROR); } cipher.init(Cipher.ENCRYPT_MODE, pubKey); ByteBuffer rawBuffer = ByteBuffer.wrap(data); ByteBuffer encryptBuffer = ByteBuffer.allocate(data.length * 4); // 由于cipher.doFinal方法对加密的数组长度有要求,不能超过100位,故采取分段解密的方法 byte[] encryptPart = new byte[ENCRYPT_PART_LENGTH]; byte[] doFinalBytes = null; int encryptDataLen = 0; int encryptPartLen = 0; for (int i = 0; i < data.length; i += ENCRYPT_PART_LENGTH) { if ((i + ENCRYPT_PART_LENGTH) <= data.length) { encryptPartLen = ENCRYPT_PART_LENGTH; } else { encryptPartLen = data.length - i; encryptPart = new byte[encryptPartLen]; } rawBuffer.get(encryptPart, 0, encryptPartLen); doFinalBytes = cipher.doFinal(encryptPart); encryptDataLen += doFinalBytes.length; encryptBuffer.put(doFinalBytes, 0, doFinalBytes.length); } encryptData = new byte[encryptDataLen]; encryptBuffer.position(0); encryptBuffer.get(encryptData, 0, encryptDataLen); } catch (NoSuchAlgorithmException e) { XLog.e(CLASS_NAME, "encryptRSA : NoSuchAlgorithmException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (InvalidKeySpecException e) { XLog.e(CLASS_NAME, "encryptRSA : InvalidKeySpecException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (InvalidKeyException e) { XLog.e(CLASS_NAME, "encryptRSA : InvalidKeyException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (IllegalBlockSizeException e) { XLog.e(CLASS_NAME, "encryptRSA : IllegalBlockSizeException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (BadPaddingException e) { XLog.e(CLASS_NAME, "encryptRSA : BadPaddingException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (NoSuchPaddingException e) { XLog.e(CLASS_NAME, "encryptRSA : NoSuchPaddingException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } return encryptData; } /** * 通过私钥加密 * * @param data * @param privateKey * @return * @throws XCryptionException */ public byte[] decryptRSA(byte[] data, byte[] privateKey) throws XCryptionException, IllegalArgumentException { if (null == data || null == privateKey) { XLog.e(CLASS_NAME, "decryptRAS param is null!"); throw new IllegalArgumentException(); } byte[] decryptData = null; try { PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec( privateKey); KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); RSAPrivateKey priKey = (RSAPrivateKey) keyFactory .generatePrivate(pkcs8KeySpec); Cipher cipher = instanceOfCipher(priKey); if (null == cipher) { throw new XCryptionException(CRYPTION_ERROR); } cipher.init(Cipher.ENCRYPT_MODE, priKey); ByteBuffer encryptBuffer = ByteBuffer.wrap(data); ByteBuffer decryptBuffer = ByteBuffer.allocate(data.length * 2); byte[] encryptPart = new byte[DECRYPT_PART_LENGTH]; byte[] doFinalBytes = null; int decryptDataLen = 0; int decryptPartLen = 0; for (int i = 0; i < data.length; i += DECRYPT_PART_LENGTH) { if ((i + DECRYPT_PART_LENGTH) <= data.length) { decryptPartLen = DECRYPT_PART_LENGTH; } else { decryptPartLen = data.length - i; encryptPart = new byte[decryptPartLen]; } encryptBuffer.get(encryptPart, 0, decryptPartLen); doFinalBytes = cipher.doFinal(encryptPart); decryptDataLen += doFinalBytes.length; decryptBuffer.put(doFinalBytes, 0, doFinalBytes.length); } // 由于android平台doFinal方法问题,需要对生成出来的数组进行特殊处理 decryptData = handleDoFinalBytes(decryptBuffer, decryptDataLen); } catch (NoSuchAlgorithmException e) { XLog.e(CLASS_NAME, "decryptRAS : NoSuchAlgorithmException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (InvalidKeySpecException e) { XLog.e(CLASS_NAME, "decryptRAS : InvalidKeySpecException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (InvalidKeyException e) { XLog.e(CLASS_NAME, "decryptRAS : InvalidKeyException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (IllegalBlockSizeException e) { XLog.e(CLASS_NAME, "decryptRAS : IllegalBlockSizeException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } catch (BadPaddingException e) { XLog.e(CLASS_NAME, "decryptRAS : BadPaddingException!"); e.printStackTrace(); throw new XCryptionException(CRYPTION_ERROR); } return decryptData; } /** * 通过公钥解密 * * @param encryptData * [in] 加密数据 * @param publicKey * [in] 解密公钥 * @return 返回解密后的数据输入流 */ public InputStream decryptByPublicKey(byte[] encryptData, RSAPublicKey publicKey) { Cipher cipher = instanceOfCipher(publicKey); if (null == encryptData || null == publicKey || null == cipher) { return null; } ByteBuffer encryptBuffer = ByteBuffer.wrap(encryptData); ByteBuffer decryptBuffer = ByteBuffer.allocate(encryptData.length * 2); // 由于cipher.doFinal方法对解密的数组长度有要求,不能超过128位,故采取分段解密的方法 byte[] decryptPart = new byte[DECRYPT_PART_LENGTH]; byte[] doFinalBytes = null; // 记录解密后的数组长度 int decryptDataLen = 0; int decryptPartLen = 0; for (int i = 0; i < encryptData.length; i += DECRYPT_PART_LENGTH) { try { if ((i + DECRYPT_PART_LENGTH) <= encryptData.length) { decryptPartLen = DECRYPT_PART_LENGTH; } else { decryptPartLen = encryptData.length - i; decryptPart = new byte[decryptPartLen]; } encryptBuffer.get(decryptPart, 0, decryptPartLen); doFinalBytes = cipher.doFinal(decryptPart); decryptDataLen += doFinalBytes.length; decryptBuffer.put(doFinalBytes, 0, doFinalBytes.length); } catch (IllegalBlockSizeException e) { XLog.e(CLASS_NAME, "Data of decryption is over blockSize!"); e.printStackTrace(); return null; } catch (BadPaddingException e) { XLog.e(CLASS_NAME, "Decrypt data failed!"); e.printStackTrace(); return null; } } // 由于android平台doFinal方法问题,需要对生成出来的数组进行特殊处理 byte[] decryptDataBytes = handleDoFinalBytes(decryptBuffer, decryptDataLen); return new ByteArrayInputStream(decryptDataBytes); } /** * 由于android平台的doFinal方法解密出的二进制数组 会多出-1和0和1的无效数字,平台自身错误,在java平台上不会遇到这种情况。 * 需要处理掉-1和0和1 * * TODO:以后android的doFinal方法解决此问题后该函数可以删除 * * @param decryptBuffer * [in] 需要处理的二进制缓存 * @param decryptDataLen * [in] 需要处理的二进制数组长度 * @return 去掉-1、0、1的二进制数组 */ private byte[] handleDoFinalBytes(ByteBuffer decryptBuffer, int decryptDataLen) { byte decryptData = 0; int handledArrayLen = 0; for (int i = 0; i < decryptDataLen; i++) { decryptData = decryptBuffer.get(i); if (decryptData != 0 && decryptData != -1 && decryptData != 1) { decryptBuffer.put(decryptData); handledArrayLen++; } } byte[] handledArray = new byte[handledArrayLen]; decryptBuffer.position(decryptDataLen); decryptBuffer.get(handledArray, 0, handledArrayLen); return handledArray; } /** * 初始化密钥 * * @param key * 密钥 * @return 根据key生成的密钥 * @throws NoSuchAlgorithmException */ // FIXME:AES的算法应该放到security中,以后添加到扩展中 private SecretKeySpec initKeyForAES(String key) throws NoSuchAlgorithmException { if (null == key || key.length() == 0) { throw new NullPointerException("key can't be null"); } SecretKeySpec secretKeySpec = null; try { KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM); keyGenerator.init(KEY_SIZE, new SecureRandom(key.getBytes())); SecretKey secretKey = keyGenerator.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); secretKeySpec = new SecretKeySpec(enCodeFormat, AES_ALGORITHM); } catch (NoSuchAlgorithmException e) { throw new NoSuchAlgorithmException(); } return secretKeySpec; } /** * 用AES算法对字符串加密 * * @param content * 需要加密的字符串的内容 * @param key * 密钥 * @return 加密过后得到byte数组 */ public byte[] encryptBytesForAES(byte[] byteContent, String key) { try { SecretKeySpec secretKeySpec = initKeyForAES(key); Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器 cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);// 初始化 byte[] result = cipher.doFinal(byteContent); return result; } catch (Exception e) { e.printStackTrace(); XLog.d(CLASS_NAME, e.getMessage()); } return null; } /** * 通过AES算法对文件加密 * * @param filePath * 文件的绝对路径 * @param key * 密钥 * @return 成功返回true,失败返回false */ public Boolean encryptFileForAES(String filePath, String key) { byte[] contentBytes = XFileUtils.readBytesFromFile(filePath); if (null == contentBytes) { return false; } byte[] encryptContent = encryptBytesForAES(contentBytes, key); if (null == encryptContent) { return false; } return XFileUtils.writeFileByByte(filePath, encryptContent); } /** * 对byte数组进行解密 * * @param content * 经过加密的byte数组的内容 * @param key * 密钥 * @return 解密过后得到的字符串 */ public byte[] decryptBytesForAES(byte[] content, String key) { try { SecretKeySpec secretKeySpec = initKeyForAES(key); Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器 cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);// 初始化 byte[] result = cipher.doFinal(content); return result; // 解密 } catch (Exception e) { e.printStackTrace(); } return null; } /** * 对文件进行AES解密 * * @param filePath * 文件的绝对路径 * @param key * 密钥 * @return 成功返回true,失败返回false */ public boolean decryptFileForAES(String filePath, String key) { if (null == key) { return false; } byte[] encryptContent = XFileUtils.readBytesFromFile(filePath); byte[] fileContent = decryptBytesForAES(encryptContent, key); if (null == encryptContent || null == fileContent) { return false; } return XFileUtils.writeFileByString(filePath, new String(fileContent)); } /** * 用DES算法对字符串加密 * * @param content * 需要加密的字符串的内容 * @param key * 密钥 * @return 加密过后得到byte数组 * @throws XCryptionException */ public byte[] encryptBytesForDES(byte[] content, byte[] key) throws XCryptionException { return cryptBytes(DES_ALGORITHM, DES_ALGORITHM, content, key, true); } /** * 通过DES算法对文件加密 * * @param filePath * 文件的绝对路径 * @param key * 密钥 * @return 成功返回true,失败返回false * @throws XCryptionException * @throws NullPointerException */ public boolean encryptFileForDES(byte[] key, String sourceFilePath, String targetFilePath) throws NullPointerException, XCryptionException { return cryptFile(DES_ALGORITHM, DES_ALGORITHM, key, sourceFilePath, targetFilePath, true); } /** * 通过DES算法对输入流加密,并返回加密后的二进制数组 * * @param key * 密钥 * @param sourceIs * 输入流 * @return 加密后的二进制数组 * @throws XCryptionException * @throws NullPointerException */ public byte[] encryptStreamForDES(byte[] key, InputStream sourceIs) throws NullPointerException, XCryptionException { return cryptStream(DES_ALGORITHM, DES_ALGORITHM, key, sourceIs, true); } /** * 用DES算法对字符串解密 * * @param content * 需要解密的字符串的内容 * @param key * 密钥 * @return 解密过后得到byte数组 * @throws XCryptionException */ public byte[] decryptBytesForDES(byte[] content, byte[] key) throws XCryptionException { return cryptBytes(DES_ALGORITHM, DES_ALGORITHM, content, key, false); } /** * 通过DES算法对输入流解密,并返回解密后的二进制数组 * * @param key * 密钥 * @param sourceIs * 输入流 * @return 解密后的二进制数组 * @throws XCryptionException * @throws NullPointerException */ public byte[] decryptStreamForDES(byte[] key, InputStream sourceIs) throws NullPointerException, XCryptionException { return cryptStream(DES_ALGORITHM, DES_ALGORITHM, key, sourceIs, false); } /** * 通过DES算法对文件解密 * * @param filePath * 文件的绝对路径 * @param key * 密钥 * @return 成功返回true,失败返回false * @throws XCryptionException * @throws NullPointerException */ public boolean decryptFileForDES(byte[] key, String sourceFilePath, String targetFilePath) throws NullPointerException, XCryptionException { return cryptFile(DES_ALGORITHM, DES_ALGORITHM, key, sourceFilePath, targetFilePath, false); } /** * 用3DES算法对字符串加密 * * @param content * 需要加密的字符串的内容 * @param key * 密钥 * @return 加密过后得到byte数组 * @throws XCryptionException */ public byte[] encryptBytesFor3DES(byte[] content, byte[] key) throws XCryptionException { return cryptBytes(TRIPLE_DES_ALGORITHM, KEY_ALOGRITHEM, content, key, true); } /** * 用3DES算法对字符串解密 * * @param content * 需要解密的字符串的内容 * @param key * 密钥 * @return 解密过后得到byte数组 * @throws XCryptionException */ public byte[] decryptBytesFor3DES(byte[] content, byte[] key) throws XCryptionException { return cryptBytes(TRIPLE_DES_ALGORITHM, KEY_ALOGRITHEM, content, key, false); } /** * 对称加解密字节数组并返回经过解密的数据 * * @param content * 需要加解密的数据 * @param sKey * 密钥 * @param isEncrypt * 标示加密还是解密,true:加密,false:解密。 * @return 经过加解密的数据 * @throws Exception */ private byte[] cryptBytes(String cryptAlogrithem, String keyAlogrithem, byte[] content, byte[] sKey, boolean isEncrypt) throws XCryptionException { if (null == sKey || XStringUtils.isEmptyString(new String(sKey))) { XLog.e(CLASS_NAME, KEY_EMPTY_ERROR); throw new NullPointerException(KEY_EMPTY_ERROR); } if (null == content || 0 == content.length) { XLog.e(CLASS_NAME, DATA_EMPTY_ERROR); throw new NullPointerException(DATA_EMPTY_ERROR); } try { Cipher cipher = prepareConvertion(cryptAlogrithem, keyAlogrithem, sKey, isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE); if (null == cipher) { XLog.e(CLASS_NAME, CRYPTION_ERROR); throw new XCryptionException(CRYPTION_ERROR); } return cipher.doFinal(content); } catch (Exception e) { XLog.e(CLASS_NAME, CRYPTION_ERROR); throw new XCryptionException(CRYPTION_ERROR); } catch (OutOfMemoryError e) { XLog.e(CLASS_NAME, OUT_OF_MEMORY_ERROR); throw new XCryptionException(CRYPTION_ERROR); } } /** * 对称加解密输入流操作,并返回处理后的二进制数组 * * @param cryptAlogrithem * 加解密算法 * @param keyAlogrithem * key的算法 * @param sKey * 密钥 * @param sourceIs * 待加解密的输入流 * @param isEncrypt * 标示加密还是解密,true:加密,false:解密。 * @return 加解密处理后的二进制数组 */ private byte[] cryptStream(String cryptAlogrithem, String keyAlogrithem, byte[] sKey, InputStream sourceIs ,boolean isEncrypt) throws IllegalArgumentException, XCryptionException { // 检查要加解密的key为空 if (null == sKey || XStringUtils.isEmptyString(new String(sKey))) { XLog.e(CLASS_NAME, KEY_EMPTY_ERROR); throw new IllegalArgumentException(KEY_EMPTY_ERROR); } try { byte[] inOutb = XUtils.readBytesFromInputStream(sourceIs); // TODO:目前为了和服务器兼容,文件加解密有base64转码操作,以后考虑去掉。 if (!isEncrypt) { inOutb = XBase64.decode(inOutb, XBase64.NO_WRAP); } // 解密缓冲区数据 byte[] result = cryptBytes(cryptAlogrithem, keyAlogrithem, inOutb, sKey, isEncrypt); if (isEncrypt) { result = XBase64.encode(result, XBase64.NO_WRAP); } return result; } catch (Exception e) { XLog.e(CLASS_NAME, CRYPTION_ERROR); throw new XCryptionException(CRYPTION_ERROR); } catch (OutOfMemoryError e) { XLog.e(CLASS_NAME, OUT_OF_MEMORY_ERROR); throw new XCryptionException(CRYPTION_ERROR); } } /** * 对称加解密文件操作并返回操作后的文件绝对路径 * * @param sKey * 密钥 * @param sourceFilePath * 需要解密的文件的绝对路径de * @param targetFilePath * 经过解密得到的文件的绝对路径 * @param isEncrypt * 标示加密还是解密,true:加密,false:解密。 * @return 解密后文件的绝对路径 */ private boolean cryptFile(String cryptAlogrithem, String keyAlogrithem, byte[] sKey, String sourceFilePath, String targetFilePath, boolean isEncrypt) throws NullPointerException, XCryptionException { // 检查要加解密的key为空 if (null == sKey || XStringUtils.isEmptyString(new String(sKey))) { XLog.e(CLASS_NAME, KEY_EMPTY_ERROR); throw new NullPointerException(KEY_EMPTY_ERROR); } try { // 从解密前文件读入数据到缓冲区 byte[] inOutb = XFileUtils.readBytesFromFile(sourceFilePath); // TODO:目前为了和服务器兼容,文件加解密有base64转码操作,以后考虑去掉。 if (!isEncrypt) { inOutb = XBase64.decode(inOutb, XBase64.NO_WRAP); } // 解密缓冲区数据 byte[] result = cryptBytes(cryptAlogrithem, keyAlogrithem, inOutb, sKey, isEncrypt); if (isEncrypt) { result = XBase64.encode(result, XBase64.NO_WRAP); } // 把缓冲区数据写入解密后文件 return XFileUtils.writeFileByByte(targetFilePath, result); } catch (Exception e) { XLog.e(CLASS_NAME, CRYPTION_ERROR); throw new XCryptionException(CRYPTION_ERROR); } catch (OutOfMemoryError e) { XLog.e(CLASS_NAME, OUT_OF_MEMORY_ERROR); throw new XCryptionException(CRYPTION_ERROR); } } /** * 为加解密转换做准备 * * @param sKey * 密钥 * @param mode * 加解密的模式:ENCRYPT_MODE 和 DECRYPT_MODE * @return Cipher */ private Cipher prepareConvertion(String cryptAlogrithem, String keyAlogrithem, byte[] sKey, int mode) throws XCryptionException { // 检查要加解密的key为空 if (null == sKey || XStringUtils.isEmptyString(new String(sKey))) { XLog.e(CLASS_NAME, KEY_EMPTY_ERROR); throw new NullPointerException(KEY_EMPTY_ERROR); } Cipher cipher = null; try { SecretKeyFactory keyFactory = SecretKeyFactory .getInstance(keyAlogrithem); byte[] keyData = sKey; KeySpec keySpec = keyAlogrithem == KEY_ALOGRITHEM ? new DESedeKeySpec( keyData) : new DESKeySpec(keyData); Key key = keyFactory.generateSecret(keySpec); cipher = Cipher.getInstance(cryptAlogrithem); if (keyAlogrithem == KEY_ALOGRITHEM) { IvParameterSpec ivSpec = new IvParameterSpec(new byte[8]); cipher.init(mode, key, ivSpec); } else { cipher.init(mode, key); } } catch (Exception e) { XLog.e(CLASS_NAME, CONVERTION_ERROR); throw new XCryptionException(CONVERTION_ERROR); } return cipher; } }