介绍
密码学中,三重数据加密算法(英语:Triple Data Encryption Algorithm,缩写为TDEA,Triple DEA),或称3DES(Triple DES),是一种对称密钥加密块密码,相当于是对每个数据块应用三次数据加密标准(DES)算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。
要求
q字符串__o_s=ec4867af19b00ba67f3b2c83058cc41a%23LATEST&__o_v=0.1.0&arg1=4&arg2=123456789&__o_r=1453355520149.751
对字符串进行加密
- 首先对原始密钥(上文准备参数中的key)做MD5算hash值得到16位字节数组,再用前8位数据对应补全后8位 ,计算出24位长的密码byte值。
- 使用上一步24位字节数组,构造一个算法为DESede的密钥。
- 获取模式为“DESede/CBC/PKCS5Padding”的Cipher 对象
- 以加密模式,上面生成的密钥,初始向量IV( 8字节空数组)作为算法参数,初始化Cipher 对象
- q的字节数组作为缓存区, Cipher 按单部分操作进行加密(doFinal)
- 对加密后的byte[]数组转换为0-9a-f 16进制ASCII字符q
加密与解密
public class TripleDESUtil {
private static final Pattern pattern = Pattern.compile("[0-9a-fA-F]+");
public TripleDESUtil() {
}
/**
* 签名
* @param dataStr
* @param keyStr
* @param saltStr
* @return
*/
public static String hmac(String dataStr, String keyStr, String saltStr) {
try {
byte[] data = (dataStr + saltStr).getBytes("UTF-8");
byte[] key = keyStr.getBytes("UTF-8");
SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA1");
Mac e = Mac.getInstance("HmacSHA1");
e.init(keySpec);
return toHexString(e.doFinal(data));
} catch (Exception var7) {
throw new RuntimeException("Signature calculation error");
}
}
/**
* 加密
* @param message
* @param key
* @return
*/
public static String encrypt(String message, String key) {
try {
SecretKeySpec var10 = new SecretKeySpec(toKeyBytes(key), "DESede");
IvParameterSpec var11 = new IvParameterSpec(new byte[8]);
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(1, var10, var11);
byte[] plainTextBytes = message.getBytes("utf-8");
return toHexString(cipher.doFinal(plainTextBytes));
} catch (Exception var6) {
throw new RuntimeException("Fail");
}
}
/**
* 解密
* @param cypher
* @param key
* @return
*/
public static String decrypt(String cypher, String key) {
try {
Map<String, String> map = toMap(cypher, false);
String salt = (String)map.get("s");
String expSig = (String)map.get("h");
String dataStr = (String)map.get("d");
String actSig = hmac(dataStr, key, salt);
if (!actSig.equals(expSig)) {
throw new RuntimeException("Fail to validate signatures, potentialdatacorruption");
} else {
Matcher match = pattern.matcher(dataStr);
if (!match.matches()) {
throw new IllegalArgumentException("Invalid hex string: " + dataStr);
} else if (dataStr.length() % 2 != 0) {
throw new IllegalArgumentException("Invalid hex string length:" + dataStr);
} else {
int len = dataStr.length();
byte[] data = new byte[len / 2];
for(int i = 0; i < len; i += 2) {
data[i / 2] = (byte)((Character.digit(dataStr.charAt(i), 16) << 4) + Character.digit(dataStr.charAt(i + 1), 16));
}
SecretKeySpec keySpec = new SecretKeySpec(toKeyBytes(key), "DESede");
IvParameterSpec iv = new IvParameterSpec(new byte[8]);
Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
decipher.init(2, keySpec, iv);
byte[] plainText = decipher.doFinal(data);
String token = (String)toMap(new String(plainText, "UTF-8"), true).get("__o_o");
if (token != null && token.length() >= 3) {
return token;
} else {
throw new RuntimeException("Get invalid ticket: " + (token == null ? "null" : token));
}
}
}
} catch (Exception var15) {
throw new RuntimeException("Fail to decrypt");
}
}
public static Map<String, String> toMap(String data, boolean doUrlDecode) {
try {
Map<String, String> paramMap = new HashMap();
if (data != null && data.trim().length() != 0) {
data = data.trim();
String[] cipher = data.split("&");
String[] var4 = cipher;
int var5 = cipher.length;
for(int var6 = 0; var6 < var5; ++var6) {
String aCipher = var4[var6];
String[] pairs = aCipher.split("=");
if (doUrlDecode) {
paramMap.put(pairs[0], URLDecoder.decode(pairs[1], "UTF-8"));
} else {
paramMap.put(pairs[0], pairs[1]);
}
}
}
return paramMap;
} catch (UnsupportedEncodingException var9) {
throw new RuntimeException("Fail to url decode");
}
}
public static String toHexString(byte[] data) {
StringBuilder buffer = new StringBuilder();
byte[] var2 = data;
int var3 = data.length;
for(int var4 = 0; var4 < var3; ++var4) {
byte aData = var2[var4];
buffer.append(String.format("%02x", 255 & aData));
}
return buffer.toString();
}
public static byte[] toKeyBytes(String key) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("md5");
byte[] digestOfPassword = md.digest(key.getBytes("utf-8"));
byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
System.arraycopy(keyBytes, 0, keyBytes, 16, 8);
return keyBytes;
}
}