package com.nova.sankuai.domain.api.jiniu;
|
|
import org.apache.commons.codec.binary.Base64;
|
|
import javax.crypto.Cipher;
|
import javax.crypto.SecretKey;
|
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.SecretKeySpec;
|
import java.nio.charset.Charset;
|
import java.util.Arrays;
|
|
/**
|
* 参数加密
|
*
|
* Created by an on 15/12/16.
|
*/
|
public class ParamAESCodec {
|
|
public static final Charset CHARSET = Charset.forName("utf-8");
|
|
public static final String ALGORITHM = "AES";
|
|
public static final String AES_CBC_NOPADDING = "AES/CBC/NoPadding";
|
|
|
/**
|
* 为了平台的通用,选择 AES/CBC/NoPadding 的模式,然后手动 padding
|
* 对应PHP 平台为 mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv)
|
* <p>
|
* AES/CBC/NoPadding encrypt
|
* 16 bytes secretKeyStr
|
* 16 bytes intVector
|
*
|
* @param secretKeyBytes
|
* @param intVectorBytes
|
* @param input
|
* @return
|
*/
|
public static byte[] encryptCBCNoPadding(byte[] secretKeyBytes, byte[] intVectorBytes, byte[] input) {
|
try {
|
IvParameterSpec iv = new IvParameterSpec(intVectorBytes);
|
SecretKey secretKey = new SecretKeySpec(secretKeyBytes, ALGORITHM);
|
int inputLength = input.length;
|
int srcLength;
|
|
Cipher cipher = Cipher.getInstance(AES_CBC_NOPADDING);
|
int blockSize = cipher.getBlockSize();
|
byte[] srcBytes;
|
if (0 != inputLength % blockSize) {
|
srcLength = inputLength + (blockSize - inputLength % blockSize);
|
srcBytes = new byte[srcLength];
|
System.arraycopy(input, 0, srcBytes, 0, inputLength);
|
} else {
|
srcBytes = input;
|
}
|
|
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
|
byte[] encryptBytes = cipher.doFinal(srcBytes);
|
return encryptBytes;
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
|
/**
|
* AES/CBC/NoPadding decrypt
|
* 16 bytes secretKeyStr
|
* 16 bytes intVector
|
*
|
* @param input
|
* @return
|
*/
|
public static byte[] decryptCBCNoPadding(byte[] secretKeyBytes, byte[] intVectorBytes, byte[] input) {
|
try {
|
IvParameterSpec iv = new IvParameterSpec(intVectorBytes);
|
SecretKey secretKey = new SecretKeySpec(secretKeyBytes, ALGORITHM);
|
|
Cipher cipher = Cipher.getInstance(AES_CBC_NOPADDING);
|
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
|
byte[] encryptBytes = cipher.doFinal(input);
|
return encryptBytes;
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
/**
|
* 用 AES 算法加密 inputStr。
|
* 使用 secretStr 作为 key,secretStr 的前 16 个字节作为 iv。
|
*
|
* @param secretStr
|
* @param inputStr
|
* @return
|
*/
|
public static byte[] encode(String secretStr, String inputStr) {
|
byte[] secretKeyBytes = secretStr.getBytes(CHARSET);
|
byte[] ivBytes = Arrays.copyOfRange(secretKeyBytes, 0, 16);
|
byte[] inputBytes = inputStr.getBytes(CHARSET);
|
|
byte[] outputBytes = encryptCBCNoPadding(secretKeyBytes, ivBytes, inputBytes);
|
return outputBytes;
|
}
|
|
public static void main(String[] args) {
|
|
}
|
|
/**
|
* 用 AES 算法加密 inputStr。
|
* 使用 secretStr 作为 key,secretStr 的前 16 个字节作为 iv。
|
* 并对加密后的字节数组调用 sun.misc.BASE64Encoder.encode 方法,
|
* 转换成 base64 字符串返回。
|
*
|
* @param secretStr
|
* @param inputStr
|
* @return
|
*/
|
public static String strEncodBase64(String secretStr, String inputStr) {
|
String base64Str = Base64.encodeBase64String(encode(secretStr, inputStr));
|
return base64Str;
|
}
|
|
/**
|
* 用 AES 算法加密 inputStr。
|
* 使用 secretStr 作为 key,secretStr 的前 16 个字节作为 iv。
|
*
|
* @param secretStr
|
* @return
|
*/
|
public static byte[] decode(String secretStr, byte[] inputBytes) {
|
byte[] secretKeyBytes = secretStr.getBytes(CHARSET);
|
byte[] ivBytes = Arrays.copyOfRange(secretKeyBytes, 0, 16);
|
|
byte[] outputBytes = decryptCBCNoPadding(secretKeyBytes, ivBytes, inputBytes);
|
return outputBytes;
|
}
|
|
/**
|
* 用 AES 算法加密 inputStr。
|
* 使用 secretStr 作为 key,secretStr 的前 16 个字节作为 iv。
|
* 并对加密后的字节数组调用 sun.misc.BASE64Encoder.encode 方法,
|
* 转换成 base64 字符串返回。
|
* <p>
|
* (仅作为测试用途,具体加密流程以接口文档为准)
|
*
|
* @param secretStr
|
* @param inputStr
|
* @return
|
*/
|
public static String base64StrDecode(String secretStr, String inputStr) {
|
byte[] inputBytes;
|
inputBytes = Base64.decodeBase64(inputStr);
|
String outputStr = new String(decode(secretStr, inputBytes), CHARSET).trim();
|
return outputStr;
|
}
|
|
|
// 加密(小赢卡贷h5流程回写合作结构接口)
|
public static String encrypt(String sSrc, String sKey) throws Exception {
|
if (sKey == null) {
|
System.out.print("Key为空null");
|
return null;
|
}
|
// 判断Key是否为16位
|
if (sKey.length() != 16) {
|
System.out.print("Key长度不是16位");
|
return null;
|
}
|
byte[] raw = sKey.getBytes("utf-8");
|
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
|
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
|
byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
|
|
return new Base64().encodeToString(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。
|
}
|
|
// 解密(小赢卡贷h5流程回写合作结构接口)
|
public static String decrypt(String sSrc, String sKey) throws Exception {
|
try {
|
// 判断Key是否正确
|
if (sKey == null) {
|
System.out.print("Key为空null");
|
return null;
|
}
|
// 判断Key是否为16位
|
if (sKey.length() != 16) {
|
System.out.print("Key长度不是16位");
|
return null;
|
}
|
byte[] raw = sKey.getBytes("utf-8");
|
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
|
byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密
|
try {
|
byte[] original = cipher.doFinal(encrypted1);
|
String originalString = new String(original, "utf-8");
|
return originalString;
|
} catch (Exception e) {
|
System.out.println(e.toString());
|
return null;
|
}
|
} catch (Exception ex) {
|
System.out.println(ex.toString());
|
return null;
|
}
|
}
|
}
|