3DES

DES

  1. DESCoder
    image
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();
    }
}

  1. 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)

  1. 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

  1. "-"转换为"+","_"转换为"/";

标准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);
posted @ 2022-03-09 09:03  子岚天羽卿怜水  阅读(170)  评论(0编辑  收藏  举报