package com.github.hunter0x7c7.sync.utils;
|
|
|
import javax.crypto.Cipher;
|
import javax.crypto.SecretKey;
|
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.SecretKeySpec;
|
|
/**
|
* AES加解密
|
*/
|
public class AesUtil {
|
//填充类型
|
public static final String AES_TYPE_CBC_PKCS5 = "AES/CBC/PKCS5Padding";// AES/CBC/PKCS7Padding
|
public static final String AES_TYPE_ECB_PKCS5 = "AES/ECB/PKCS5Padding";
|
public static final String AES_TYPE_ECB_PKCS7 = "AES/ECB/PKCS7Padding";
|
//此类型 加密内容,密钥必须为16字节的倍数位,否则抛异常,需要字节补全再进行加密
|
public static final String AES_TYPE_ECB_NO = "AES/ECB/NoPadding";
|
//java 不支持ZeroPadding
|
public static final String AES_TYPE_CBC_ZERO = "AES/CBC/ZeroPadding";
|
//填充类型
|
public static final String AES_DEF_TYPE = AES_TYPE_CBC_PKCS5;
|
|
//编码方式
|
public static final String CODE_TYPE = "UTF-8";//"GBK";
|
//私钥
|
private static final String AES_DEF_KEY = "110037d640411e09e76dd00e207d09f3";//AES固定格式为128/192/256 bits.即:16/24/32bytes。DES固定格式为128bits,即8bytes。
|
//偏移量
|
private static final String VIPARA = "1234567890123456";//CBC密钥默认偏移,可更改
|
|
private static AesUtil mAesUtil;
|
|
public static AesUtil getInstance() {
|
if (mAesUtil == null) {
|
synchronized (AesUtil.class) {
|
if (mAesUtil == null) {
|
mAesUtil = new AesUtil();
|
}
|
}
|
}
|
return mAesUtil;
|
}
|
|
/**
|
* 加密
|
*/
|
public String encrypt(String plaintext) {
|
return encrypt(plaintext, AES_DEF_KEY);
|
}
|
|
/**
|
* 加密
|
*/
|
public String encrypt(String plaintext, String privateKey) {
|
return encrypt(AES_DEF_TYPE, plaintext, privateKey);
|
}
|
|
/**
|
* 加密
|
*/
|
public String encrypt(String type, String plaintext, String privateKey) {
|
//加密方式: AES128(ECB/PKCS5Padding) + Base64, 私钥:privateKey
|
try {
|
if (plaintext != null && plaintext.length() > 0) {
|
byte[] cipherText;
|
if (type != null && privateKey != null) {
|
//两个参数,第一个为私钥字节数组, 第二个为加密方式 AES或者DES
|
SecretKeySpec secretKey = new SecretKeySpec(privateKey.getBytes(), "AES");
|
byte[] bytes = plaintext.getBytes(CODE_TYPE);
|
if (AES_TYPE_CBC_PKCS5.equals(type)) {
|
IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
|
cipherText = encrypt(type, secretKey, zeroIv, bytes);
|
} else {
|
cipherText = encrypt(type, secretKey, bytes);
|
}
|
} else {
|
cipherText = null;
|
}
|
return Base64Encoder.encode(cipherText);
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
/**
|
* 解密
|
*/
|
public String decrypt(String cipherTextBase64) {
|
return decrypt(cipherTextBase64, AES_DEF_KEY);
|
}
|
|
/**
|
* 解密
|
*/
|
public String decrypt(String plaintext, String privateKey) {
|
return decrypt(AES_DEF_TYPE, plaintext, privateKey);
|
}
|
|
/**
|
* 解密
|
*/
|
public String decrypt(String type, String plaintext, String privateKey) {
|
try {
|
if (plaintext != null && plaintext.length() > 0) {
|
byte[] decrypt;
|
if (type != null && privateKey != null) {
|
//两个参数,第一个为私钥字节数组, 第二个为加密方式 AES或者DES
|
SecretKeySpec secretKey = new SecretKeySpec(privateKey.getBytes(), "AES");
|
byte[] bytes = Base64Decoder.decodeToBytes(plaintext);
|
if (AES_TYPE_CBC_PKCS5.equals(type)) {
|
IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
|
decrypt = decrypt(type, secretKey, zeroIv, bytes);
|
} else {
|
decrypt = decrypt(type, secretKey, bytes);
|
}
|
} else {
|
decrypt = null;
|
}
|
return decrypt != null ? new String(decrypt, CODE_TYPE) : null;
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
/**
|
* 加密
|
*/
|
private byte[] encrypt(String type, SecretKey key, byte[] msg) {
|
try {
|
Cipher c = Cipher.getInstance(type);
|
c.init(Cipher.ENCRYPT_MODE, key);
|
return c.doFinal(msg);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return new byte[0];
|
}
|
|
/**
|
* 加密
|
*/
|
private byte[] encrypt(String type, SecretKey secretKey, IvParameterSpec params, byte[] msg) {
|
try {
|
//实例化加密类,参数为加密方式,要写全
|
Cipher c = Cipher.getInstance(type);//PKCS5Padding比PKCS7Padding效率高,PKCS7Padding可支持IOS加解密
|
//初始化,此方法可以采用三种方式,按加密算法要求来添加。
|
// (1)无第三个参数
|
// (2)第三个参数为SecureRandom random = new SecureRandom();中random对象,随机数。(AES不可采用这种方法)
|
// (3)采用此代码中的IVParameterSpec
|
//加密时使用:ENCRYPT_MODE; 解密时使用:DECRYPT_MODE;
|
c.init(Cipher.ENCRYPT_MODE, secretKey, params);//CBC类型的可以在第三个参数传递偏移量zeroIv,ECB没有偏移量
|
//加密操作,返回加密后的字节数组,然后需要编码。主要编解码方式有Base64, HEX, UUE,7bit等等。此处看服务器需要什么编码方式
|
return c.doFinal(msg);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return new byte[0];
|
}
|
|
/**
|
* 解密
|
*/
|
private byte[] decrypt(String type, SecretKey secretKey, IvParameterSpec params, byte[] cipherText) {
|
try {
|
Cipher c = Cipher.getInstance(type);
|
c.init(Cipher.DECRYPT_MODE, secretKey, params);
|
return c.doFinal(cipherText);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
/**
|
* 解密
|
*/
|
private byte[] decrypt(String type, SecretKey secretKey, byte[] cipherText) {
|
try {
|
Cipher c = Cipher.getInstance(type);
|
c.init(Cipher.DECRYPT_MODE, secretKey);
|
return c.doFinal(cipherText);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
}
|