3DES
DES
- DESCoder
package com.example.demo.util;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.Key;
public class DESCoder {
public static final String KEY_ALGORITHM = "DES";
public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
/**
* 转换密钥<br>
*
* @param key
* @return
* @throws Exception
*/
private static Key toKey(byte[] key) throws Exception {
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(dks);
return secretKey;
}
/**
* 解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
Key k = toKey(key);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, k);
return cipher.doFinal(data);
}
/**
* 加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
Key k = toKey(key);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, k);
return cipher.doFinal(data);
}
/**
* 生成密钥
*
* @return
* @throws Exception
*/
public static byte[] initKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
kg.init(56);
SecretKey secretKey = kg.generateKey();
return secretKey.getEncoded();
}
}
- DesController
package com.example.demo.controller;
import com.example.demo.util.DESCoder;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Encoder;
import javax.crypto.KeyGenerator;
@RestController
public class DesController {
@RequestMapping("/des")
/*public static void test() throws Exception{
KeyGenerator kg = KeyGenerator.getInstance("DESede");
kg.init(168);//must be equal to 112 or 168
System.out.println("SecretKey:");
System.out.println(new BASE64Encoder().encode(kg.generateKey().getEncoded()));
}*/
public final void test() throws Exception {
String inputStr = "DES";
byte[] inputData = inputStr.getBytes();
System.err.println("原文:\t" + inputStr);
//初始化秘钥
byte[] key = DESCoder.initKey();
System.err.println("秘钥:\t" + Base64.encodeBase64String(key));
//加密
inputData = DESCoder.encrypt(inputData, key);
System.err.println("秘钥:\t" + Base64.encodeBase64String(inputData));
//解密
byte[] outputData = DESCoder.decrypt(inputData, key);
String outputStr = new String(outputData);
System.err.println("解密后:\t" + outputStr);
//assertEquals(inputStr,outputStr);
}
}
原文: DES
秘钥: KXD0O5QxbtU=
加密: h6a1uDbqtOg=
解密后: DES
3DES(DESede)
- DesUtil
package com.example.demo.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
public class DesUtil {
private final static Logger logger = LoggerFactory.getLogger(_3DesUtil.class);
//定义加密算法,有DES、DESede(即3DES)、Blowfish
private static final String Algorithm = "DESede";
/**
* 加密方法
* @param src 源数据的字节数组
* @return
*/
public static byte[] encryptMode(byte[] src, String key) {
try {
SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm); //生成密钥
Cipher c1 = Cipher.getInstance(Algorithm); //实例化负责加密/解密的Cipher工具类
c1.init(Cipher.ENCRYPT_MODE, deskey); //初始化为加密模式
return c1.doFinal(src);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return null;
}
/**
* 加密方法
* @param src 源数据的字节数组(src:mds加密后的密码,key:随机盐值)
* @return
*/
public static String encryptMode(String src, String key) {
byte[] encryptArr = encryptMode(src.getBytes(), key);
return Base64.encodeBase64String(encryptArr);
}
/**
* 解密函数
* @param src 密文的字节数组
* @return
*/
public static byte[] decryptMode(byte[] src, String key) {
try {
SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm);
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE, deskey); //初始化为解密模式
return c1.doFinal(src);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return null;
}
/**
* 解密函数
* @param src 密文的字节数组
* @return
*/
public static String decryptMode(String src, String key) {
byte[] decryptArr = decryptMode(Base64.decodeBase64(src.getBytes()), key);
if (decryptArr == null){
return null;
}
return new String(decryptArr);
}
/*
* 根据字符串生成密钥字节数组
* @param keyStr 密钥字符串
* @return
* @throws UnsupportedEncodingException
*/
public static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException {
byte[] key = new byte[24]; //声明一个24位的字节数组,默认里面都是0
byte[] temp = keyStr.getBytes("UTF-8"); //将字符串转成字节数组
/*
* 执行数组拷贝
* System.arraycopy(源数组,从源数组哪里开始拷贝,目标数组,拷贝多少位)
*/
if(key.length > temp.length){
//如果temp不够24位,则拷贝temp数组整个长度的内容到key数组中
System.arraycopy(temp, 0, key, 0, temp.length);
}else{
//如果temp大于24位,则拷贝temp数组24个长度的内容到key数组中
System.arraycopy(temp, 0, key, 0, key.length);
}
return key;
}
/***
* 3Des加密,标准base64编码的结果中会包含:字母,数字,+ / = ,由于+ /在url中都有特殊含义,
* 所以一般浏览器或者http组件会对其进行编码,在对应接收端可能会引起没有正确解析
* 解决方法:Base64编码以后,再手动将 + /替换成 - _ ,然后解码端相同
* @param src
* @param key
* @return
*/
public static String encrypt(String src, String key){
String encrypt = encryptMode(src, key);
return specialCharReplace(encrypt);
}
/***
* 3Des解密,3Des加密后对密文进行特殊字符的替换,所以在3Des解密之前需要对特殊字符替换回来
* @param src
* @param key
* @return
*/
public static String decrypt(String src, String key) {
String replace = specialCharReplaceBack(src);
return decryptMode(replace, key);
}
/***
* 将+ /替换成 - _ 这样
* @param data
* @return
*/
public static String specialCharReplace(String data){
if(StringUtils.isBlank(data)){
return null;
}
String replace = data.replaceAll("\\+", "-")
.replaceAll("/", "_");
return replace;
}
/***
* 特殊字符替换回来
* @param data
* @return
*/
public static String specialCharReplaceBack(String data){
if(StringUtils.isBlank(data)){
return null;
}
String replace = data.replaceAll("-", "+")
.replaceAll("_", "/");
return replace;
}
}
2.Des4Controller
package com.example.demo.controller;
import com.example.demo.util.DESCoder;
import com.example.demo.util.DESedeCoder;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.util.DesUtil;
@RestController
public class Des4Controller {
@RequestMapping("/des4")
public final void test() throws Exception {
String str = "{\"merId\":\"410081200000001\",\"ordId\":\"20211022A259289237\"}";
String pwd = "110101198701019999";
String salt = "秘钥";
//String ss = encryptMode(str,salt);
// String ss = DesUtil.encryptMode(str,salt);
//System.out.println(ss);
String str1 = "待解密数据";
String aa = DesUtil.decrypt(str1,salt);
System.out.println(aa);
//
//byte[] key = DESedeCoder.initKey();
}
}
php 3DES
- "-"转换为"+","_"转换为"/";
标准base64编码的结果中会包含:字母,数字,+ / = ,由于+ /在url中都有特殊含义,
所以一般浏览器或者http组件会对其进行编码,在对应接收端可能会引起没有正确解析
解决方法:Base64编码以后,再手动将 + /替换成 - _ ,然后解码端相同
class Desede
{
function des3_encrypt($str,$des_key="",$des_iv="")
{
return @base64_encode(openssl_encrypt($str, 'des-ede3-cbc', $des_key, OPENSSL_RAW_DATA, $des_iv));
}
public function decrypt($data, $key)
{
$data = base64_decode($data);
$decData = openssl_decrypt($data, 'DES-EDE3', $key, OPENSSL_RAW_DATA);
return $decData;
}
public function strback($str){
$str = str_replace('-', '+', $str);
$str = str_replace('_', '/', $str);
return $str;
}
}
/**
*$param['data'] 待解密数据
*/
$d = new Desede();
//dump($param['data']);
//dump($d->strback($param['data']));die;
$param['data'] = $d->strback($param['data']);
$dres = $d->decrypt($param['data'],$deskey);