public class ByteUtil {
/**
* 将byte数组报文(根据ASCII码值)转换为字符串
* @param bs
* @return
*/
public static String byteArray2String(byte[] bs){
StringBuffer sbLogRet = new StringBuffer();
for(int i=0; i<bs.length; i++)
{
String inTmp = String.format("%02x", bs[i]);
sbLogRet.append(inTmp);
}
return sbLogRet.toString();
}
/**
* 16进制字符串到byte数组的转换
* @param hex 需要转换的字符串(只包含0~9,a~f字符)
* @return
*/
public static byte[] AscToBcd(String hex)
{
//A null string returns an empty array
if (hex == null || hex.length() == 0) {
return new byte[0];
} else if (hex.length() < 3) {
return new byte[]{ (byte)(Integer.parseInt(hex, 16) & 0xff) };
}
//Adjust accordingly for odd-length strings
int count = hex.length();
int nibble = 0;
if (count % 2 != 0) {
count++;
nibble = 1;
}
byte[] buf = new byte[count / 2];
char c = 0;
int holder = 0;
int pos = 0;
for (int i = 0; i < buf.length; i++) {
for (int z = 0; z < 2 && pos<hex.length(); z++) {
c = hex.charAt(pos++);
if (c >= 'A' && c <= 'F') {
c -= 55;
} else if (c >= '0' && c <= '9') {
c -= 48;
} else if (c >= 'a' && c <= 'f') {
c -= 87;
}
if (nibble == 0) {
holder = c << 4;
} else {
holder |= c;
buf[i] = (byte)holder;
}
nibble = 1 - nibble;
}
}
return buf;
}
/**
*
* @param String
* @return
* @description 16进制字符串到byte数组的转换(2个16进制字符转换为1个带符号10进制byte)
*/
public static byte[] hexStringToByte(String s) {
byte[] baKeyword = new byte[s.length() / 2];
for (int i = 0; i < baKeyword.length; i++) {
try {
baKeyword[i] = (byte) (0xff & Integer.parseInt(
s.substring(i * 2, i * 2 + 2), 16));
} catch (Exception e) {
LogUtil.error("十六进制转byte发生错误!!!"+s);
}
}
return baKeyword;
}
}
import java.nio.channels.FileChannel;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
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.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.coyote.http2.ByteUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* AES加解密Util
*/
public class AESUtil {
private static final Logger log = LoggerFactory.getLogger(AESUtil.class);
private static final String DEFAULT_ENCODING = "UTF-8";
private static final int KEY_SIZE = 128;
public static final String KEY_ALGORITHM = "AES";
public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";
public static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding";
public static final byte[] iv = { (byte) 0xf9, (byte) 0x5B, (byte) 0xC3, (byte) 0x34,
(byte) 0x94, (byte) 0x1e, (byte) 0xD8, (byte) 0xa7,
(byte) 0xA6, (byte) 0x61, (byte) 0xFF, (byte) 0x2B,
(byte) 0x56, (byte) 0xcB, (byte) 0x47, (byte) 0x03};
public static final AlgorithmParameterSpec spec =new IvParameterSpec(iv);
public static SecretKeySpec getSecretKeyWithSHA256(String key) throws Exception {
return new SecretKeySpec(key.getBytes(), KEY_ALGORITHM);
}
/**
* 加密
* @param plainText 待加密字符串
* @param key 秘钥
* @return 加密结果字符串
*/
public static String encrypt(String plainText, String key) {
String encryptedText = null;
if (StringUtils.isBlank(plainText)||"null".equals(plainText)) {
return plainText;
}
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
cipher.init(Cipher.ENCRYPT_MODE, getSecretKeyWithSHA256(key), spec);
byte[] encrypted = cipher.doFinal(plainText.getBytes(DEFAULT_ENCODING));
encryptedText = Base64.encodeBase64URLSafeString(encrypted);
} catch (Exception e) {
log.error("AES加密异常!!!",e);
}
return encryptedText;
}
/**
* 解密
* @param cryptedText 待解密字符串
* @param key 秘钥
* @return 解密结果字符串
*/
public static String decrypt(String cryptedText, String key) {
String decryptedText = null;
if (StringUtils.isBlank(cryptedText)||"null".equals(cryptedText)) {
return cryptedText;
}
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
cipher.init(Cipher.DECRYPT_MODE, getSecretKeyWithSHA256(key), spec);
byte[] bytes = Base64.decodeBase64(cryptedText);
byte[] decrypted = cipher.doFinal(bytes);
decryptedText = new String(decrypted, DEFAULT_ENCODING);
} catch (Exception e) {
log.error("AES解密异常!!!",e);
}
return decryptedText;
}
/**
* 生成指定长度的对称密钥
* @param length 密钥的bit位数,默认为128位
* @return
* @throws Exception
*/
public static byte[] generateKey(int length, String keyAlg) throws Exception {
//实例化密钥生成器
Security.addProvider(new BouncyCastleProvider());
KeyGenerator kg = null;
try {
kg = KeyGenerator.getInstance(keyAlg, "BC");
} catch (NoSuchAlgorithmException e) {
log.error("不存在此种对称密钥算法:" + keyAlg);
throw new Exception("不存在此种对称密钥算法:" + keyAlg, e);
} catch (NoSuchProviderException e) {
log.error("NoSuchProviderException:BouncyCastleProvider");
throw new Exception("NoSuchProviderException:BouncyCastleProvider", e);
}
//初始化密钥生成器,AES要求密钥长度为128位、192位、256位
kg.init(length);
//生成密钥
SecretKey secretKey = kg.generateKey();
//log.debug("生成的AES密钥:" + ByteUtil.byteArray2String(secretKey.getEncoded()));
//获取二进制密钥编码形式
return secretKey.getEncoded();
}
/**
* 转换密钥
* @param key 十六进制编码格式密钥
* @return
* @throws Exception
*/
public static Key toKey(byte[] key, String keyAlg) throws Exception {
SecretKey secretKey = new SecretKeySpec(key, keyAlg);
return secretKey;
}
/**
* 对称密钥加密
* @param byteContent 需要加密的内容
* @param key AES密钥
* @param keyAlg 对称密钥算法密钥算法 (java6支持56位密钥,bouncycastle支持64位)
* @param cipherAlg 加解密算法/工作模式/填充方式 (JAVA6 支持PKCS5PADDING填充方式 ,Bouncy castle支持PKCS7Padding填充方式)
* @return
*/
public static byte[] encrypt(byte[] byteContent, byte[] key, String keyAlg, String cipherAlg) throws Exception {
try {
//还原密钥
Key k = toKey(key, keyAlg);
//实例化 ,使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现 Cipher.getInstance(CIPHER_ALGORITHM,"BC")
Security.addProvider(new BouncyCastleProvider());
Cipher cipher=Cipher.getInstance(cipherAlg, "BC");
//Cipher cipher = Cipher.getInstance(keyAlg);
//初始化,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
//执行操作
return cipher.doFinal(byteContent);
} catch (NoSuchAlgorithmException e) {
log.error("不存在此种对称密钥算法:" + keyAlg);
throw new Exception("不存在此种对称密钥算法:" + keyAlg, e);
} catch (NoSuchPaddingException e) {
log.error("NoSuchPaddingException");
throw new Exception("NoSuchPaddingException", e);
} catch (InvalidKeyException e) {
//log.error("无效的Key:" + Base64Utils.encode(key));
throw new Exception("无效的Key:", e);
} catch (IllegalBlockSizeException e) {
log.error("被加密内容长度无效");
throw new Exception("被加密内容长度无效", e);
} catch (BadPaddingException e) {
log.error("BadPaddingException");
throw new Exception("BadPaddingException", e);
}
}
/**
* 对称密钥解密
* @param content 待解密内容
* @param key 解密密钥
* @param keyAlg 对称密钥算法密钥算法 (java6支持56位密钥,bouncycastle支持64位)
* @param cipherAlg 加解密算法/工作模式/填充方式 (JAVA6 支持PKCS5PADDING填充方式 ,Bouncy castle支持PKCS7Padding填充方式)
* @return
*/
public static byte[] decrypt(byte[] content, byte[] key, String keyAlg, String cipherAlg) throws Exception {
try {
//还原密钥
Key k = toKey(key, keyAlg);
//实例化 ,使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现 Cipher.getInstance(CIPHER_ALGORITHM,"BC")
Security.addProvider(new BouncyCastleProvider());
Cipher cipher=Cipher.getInstance(cipherAlg, "BC");
//Cipher cipher = Cipher.getInstance(keyAlg);
//初始化,设置为加密模式
cipher.init(Cipher.DECRYPT_MODE, k);
//执行操作
return cipher.doFinal(content);
} catch (NoSuchAlgorithmException e) {
log.error("不存在此种对称密钥算法:" + keyAlg);
throw new Exception("不存在此种对称密钥算法:" + keyAlg, e);
} catch (NoSuchPaddingException e) {
log.error("NoSuchPaddingException");
throw new Exception("NoSuchPaddingException", e);
} catch (InvalidKeyException e) {
//log.error("无效的Key:" + ByteUtil.byteArray2String(key));
throw new Exception("无效的Key:" , e);
} catch (IllegalBlockSizeException e) {
log.error("被加密内容长度无效");
throw new Exception("被加密内容长度无效", e);
} catch (BadPaddingException e) {
log.error("BadPaddingException");
throw new Exception("BadPaddingException", e);
}
}
/**
* 固定IV偏移向量的AES加密算法
* 用于前后端全加密 慎用
* @author PENGKANGKANG620
* @param content
* @param key
* @return
*/
public static String encryptWithIV(String content, String key){
try{
Key keySpec = new SecretKeySpec(key.getBytes(), KEY_ALGORITHM);//两个参数,第一个为私钥字节数组, 第二个为加密方式 AES或者DES
//String iv = key;//初始化向量参数,AES 为16bytes. DES 为8bytes.
IvParameterSpec ivSpec = new IvParameterSpec(key.getBytes());
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
cipher.init(Cipher.ENCRYPT_MODE, keySpec,ivSpec);
byte[] byteResult = cipher.doFinal(content.getBytes("UTF-8"));
return new Base64().encodeToString(byteResult);
}catch(Exception e){
log.error("AES加密异常!!!");
}
return null;
}
/**
* 固定IV偏移向量的AES解密算法
* 用于前后端全加密
* @author PENGKANGKANG620
* @param content
* @param key
* @return
*/
public static String decryptWithIV(String content, String key){
try{
Key keySpec = new SecretKeySpec(key.getBytes(), KEY_ALGORITHM); //两个参数,第一个为私钥字节数组, 第二个为加密方式 AES或者DES
// String iv = key;//初始化向量参数,AES 为16bytes. DES 为8bytes.
IvParameterSpec ivSpec = new IvParameterSpec(key.getBytes());
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
cipher.init(Cipher.DECRYPT_MODE, keySpec,ivSpec);
byte[] tmp = new Base64().decode(content.getBytes("UTF-8"));
byte[] result = cipher.doFinal(tmp);
return new String(result,"UTF-8");
}catch(Exception e){
log.error("AES解密异常!!!");
}
return null;
}
/**
* 创建文件
* @param fileName
* @param filePath
* @param data
*/
public static void writeFile(String fileName,String filePath, byte[] data){
BufferedOutputStream bufferOut = null;
try{
File f = new File(filePath);
if (!f.exists()) {
f.mkdirs();
}
bufferOut = new BufferedOutputStream(new FileOutputStream(filePath+fileName));
bufferOut.write(data);
bufferOut.flush();
}catch(Exception e){
log.error(e.getClass().getName() + "生成文件失败:"
+ e.getMessage());
// e.printStackTrace();
} finally{
if(null != bufferOut){
try {
bufferOut.close();
} catch (IOException e) {
log.error(e.getClass().getName() + "输出流关闭失败:"
+ e.getMessage());
}
}
}
}
/**
* 生成随机密钥
*
* @return
* @throws Exception
*/
public static String getSecretKey() throws Exception {
return getSecretKey(null);
}
/**
* 生成密钥
* @param seed 密钥种子
* @return
* @throws Exception
*/
public static String getSecretKey(String seed) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom;
if (seed != null && !"".equals(seed)) {
secureRandom = new SecureRandom(seed.getBytes());
} else {
secureRandom = new SecureRandom();
}
keyGenerator.init(KEY_SIZE, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
return Base64Utils.encode(secretKey.getEncoded());
}
/**
* 加密
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encrypt(byte[] data, String key) throws Exception {
Key k = toKey(Base64Utils.decode(key));
byte[] raw = k.getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(data);
}
/**
* 解密
* @param base64data
* @param key
* @throws Exception
*/
public static byte[] decrypt(byte[] base64data, String key) throws Exception {
Key k = toKey(Base64Utils.decode(key));
byte[] raw = k.getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return cipher.doFinal(base64data);
}
/**
* 转换密钥
* @param key
* @return
* @throws Exception
*/
private static Key toKey(byte[] key) throws Exception {
SecretKey secretKey = new SecretKeySpec(key, KEY_ALGORITHM);
return secretKey;
}
/**
*
* @param sSrc
* @param sKey
* @param ivParameter
* @return
* @throws Exception
*/
public static String encrypt(String sSrc,String sKey, String ivParameter) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
byte[] raw = sKey.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(sSrc.getBytes(DEFAULT_ENCODING));
return Base64Utils.encode(encrypted);// 此处使用BASE64做转码。
}
public static void main(String[] args) throws Exception {
byte[] AESkey = generateKey(128, KEY_ALGORITHM);
AESkey = ByteUtil.AscToBcd("FA4246228215E27F03628A507296A2FC");
byte[] needEncryptData = "hello".getBytes();
byte[] dataAfterEnctypt = encrypt(needEncryptData, AESkey, KEY_ALGORITHM, CIPHER_ALGORITHM);
System.out.println("dataAfterEnctypt:" + ByteUtil.byteArray2String(dataAfterEnctypt));
System.out.println("dataAfterDectypt:" + new String(decrypt(dataAfterEnctypt, AESkey, KEY_ALGORITHM, CIPHER_ALGORITHM)));
System.out.println(getSecretKey());
System.out.println(decryptWithIV("do5vVB8IJVnK9+pK416AMg==", "NgzIKRmsV8ZtOw=="));
String aes_key_Acc_Pri="NgzIKRmsV8ZtOw==";
String accountId="123456";
accountId = AESUtil.encryptWithIV(accountId, aes_key_Acc_Pri);
System.out.println(accountId);
accountId = AESUtil.decrypt("5XyVSoDM0qlrASG9QwnBeg", aes_key_Acc_Pri);
System.out.println(accountId);
System.out.println(decrypt(ByteUtil.AscToBcd("edde9e971337665ef05aedcbb86d3ee6"), AESkey, KEY_ALGORITHM, CIPHER_ALGORITHM));
System.out.println(Arrays.toString(decrypt(ByteUtil.AscToBcd("edde9e971337665ef05aedcbb86d3ee6"), AESkey, KEY_ALGORITHM, CIPHER_ALGORITHM)));
long startTime = System.currentTimeMillis();
File file = new File("ss_j2ee/src/java/com/paic/cfs/test.jpg");
FileInputStream fis= new FileInputStream(file);
FileChannel fc= fis.getChannel();
int fileSize = (int)fc.size();
System.out.println("文件大小:" + fileSize);
System.out.println("读取文件大小耗时:" + (System.currentTimeMillis() - startTime));
byte[] bs_ogin = new byte[fileSize];
fis.read(bs_ogin);
dataAfterEnctypt = encrypt(bs_ogin, AESkey, KEY_ALGORITHM, CIPHER_ALGORITHM);
System.out.println("dataAfterEnctypt:" + ByteUtil.byteArray2String(dataAfterEnctypt));
writeFile("test.txt", "ss_j2ee/src/java/com/paic/cfs/", ByteUtil.byteArray2String(dataAfterEnctypt).getBytes());
byte[] dataAfterDecrypt = decrypt(dataAfterEnctypt, AESkey, KEY_ALGORITHM, CIPHER_ALGORITHM);
System.out.println("dataAfterDectypt:" + new String(dataAfterDecrypt));
System.out.println((ByteUtil.byteArray2String(bs_ogin)).equals(ByteUtil.byteArray2String(dataAfterDecrypt)));
writeFile("test_plain.jpg", "ss_j2ee/src/java/com/paic/cfs/", dataAfterDecrypt);*/
File file1 = new File("ss_j2ee/src/java/com/paic/cfs/renlian.txt");
BufferedReader br = new BufferedReader(new FileReader(file1));
String fileContent = br.readLine();
byte[] dataAfterDecrypt = decrypt(ByteUtil.AscToBcd(fileContent), AESkey, KEY_ALGORITHM, CIPHER_ALGORITHM);
writeFile("renlian.jpg", "ss_j2ee/src/java/com/paic/cfs/", dataAfterDecrypt);
}
}