常见的对称加密解密算法

常见的对称加密解密算法

转载至[博客](https://blog.csdn.net/qq_40687809/article/details/107231822#:~:text=13种加密与解密算法【一】 1 【1、MD5加密解密】 2,【2、Base64加密解密】 3 【3、对称之AES加密解密】 4 【4、对称之DES加密解密】)

AES

package cn.com.wuhm.common.encoded;

import cn.com.wuhm.common.util.ConverterUtil;
import cn.com.wuhm.common.util.GeneratorCodeUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

/**
 * AES
 * @Description
 * @Author wuhuaming
 * @Date 2023/9/2
 */
@Slf4j
public class AESUtil {

    private final String ALGORITHM = "AES";

    /**
     * 是否初始化
     */
    private boolean initialized;

    /**
     * 加密/解密模式:CBC,FBC,ECB
     */
    private final Model mode;

    public AESUtil() {
        this.mode = Model.ECB;
        this.initialized = false;
    }

    public AESUtil(Model mode) {
        this.mode = mode;
        this.initialized = false;
    }



    /**
     * 也可以通过这种方式获取密钥
     *
     * @param key
     * @return
     */
    private SecretKey getSecretKey(String key) {
        try {
            //获取指定的密钥生成器
            KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
            //加密强随机数
            SecureRandom secureRandom = new SecureRandom();
            secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8));
            //这里可以是128、192、256、越大越安全
            keyGen.init(256, secureRandom);
            return keyGen.generateKey();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("AES获取密钥出现错误,算法异常");
        }
    }

    /**
     * @param key 密钥,key长度必须大于等于 3*8 = 24,并且是8的倍数
     * @param keyIv 初始化向量,keyIv长度必须等于16
     * @param data 明文
     * @return 密文
     */
    public String encoded(String key, String keyIv, String data){
        initialize();
        try {
            //获取SecretKey对象,也可以使用getSecretKey()方法
            Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
            //获取指定转换的密码对象Cipher(参数:算法/工作模式/填充模式)
            Cipher cipher = Cipher.getInstance(this.mode.getCode());
            if(StringUtils.isNotEmpty(keyIv)){
                //创建向量参数规范也就是初始化向量
                IvParameterSpec ips = new IvParameterSpec(keyIv.getBytes(StandardCharsets.UTF_8));
                //用密钥和一组算法参数规范初始化此Cipher对象(加密模式)
                cipher.init(Cipher.ENCRYPT_MODE, secretKey, ips);
            }else{
                //用密钥和一组算法参数规范初始化此Cipher对象(加密模式)
                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            }
            //执行加密操作
            byte[] bytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            // 将二进制转换转为base64编码返回
            Base64.Encoder encoder = Base64.getEncoder();
            return encoder.encodeToString(bytes);
        }catch (Exception e){
            throw new RuntimeException(e);
        }

    }

    /**
     * @param key 密钥,key长度必须大于等于 3*8 = 24,并且是8的倍数
     * @param keyIv 初始化向量,keyIv长度必须等于16
     * @param data 密文
     * @return 明文
     */
    public String decoded(String key, String keyIv, String data){
        this.initialize();
        try {
            //获取SecretKey对象,也可以使用getSecretKey()方法
            Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
            //获取指定转换的密码对象Cipher(参数:算法/工作模式/填充模式)
            Cipher cipher = Cipher.getInstance(this.mode.getCode());
            if(StringUtils.isNotEmpty(keyIv)){
                //创建向量参数规范也就是初始化向量
                IvParameterSpec ips = new IvParameterSpec(keyIv.getBytes(StandardCharsets.UTF_8));
                //用密钥和一组算法参数规范初始化此Cipher对象(加密模式)
                cipher.init(Cipher.DECRYPT_MODE, secretKey, ips);
            }else{
                cipher.init(Cipher.DECRYPT_MODE, secretKey);
            }
            // 将base64编码转为二进制数组
            Base64.Decoder decoder = Base64.getDecoder();
            byte[] bytes = decoder.decode(data);
            //执行解密操作
            return new String(cipher.doFinal(bytes));
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }


    /**
     * 初始化
     */
    private void initialize(){
        if (initialized) {
            return;
        }
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
        log.debug("org.bouncycastle.jce.provider.BouncyCastleProvider:初始化成功");
    }


    @Getter
    public enum Model {

        /**
         * ECB 模式:不需要偏移量iv
         */
        ECB("AES/ECB/PKCS7Padding"),

        /**
         * CBC: 需要偏移量
         */
        CBC("AES/CBC/PKCS7Padding"),

        /**
         * CFB:需要偏移量
         */
        CFB("AES/CFB/PKCS7Padding"),

        ;

        private final String code;

        Model(String code) {
            this.code = code;
        }
    }

//
//    public static void main(String[] args) {
//        String aesKey = GeneratorCodeUtil.getRandomStr(24);
//        String iv = GeneratorCodeUtil.getRandomStr(16);
////        String iv = null;
//        String password = "abcd1234";
//        AESUtil aesUtil = new AESUtil(Model.CBC);
//        String encoded = aesUtil.encoded(aesKey, iv, password);
//        System.out.println(encoded);
//        System.out.println(aesUtil.decoded(aesKey, iv, encoded));
//    }

}

RC4

package cn.com.wuhm.common.encoded;

import lombok.extern.slf4j.Slf4j;

/**
 * RC4加密/解密工具
 * @Description blowfish加密函数迭代执行16轮,分组长度64位,密钥长度从32位到448位。算法由两部分组成,密钥扩展部分和数据加密部分。RC4算法的特点是算法简单,运行速度快,而且密钥长度是可变的,可变范围为1-256字节(8-2048比特)。
 * @Author wuhuaming
 * @Date 2023/9/12
 */
@Slf4j
public class RC4Util {

    /**
     * RC4加密
     * @param data 需要加密的内容
     * @param key 自定义密钥
     * @return 加密后的内容
     */
    public String encrypt(String data, String key) {
        if (data == null || key == null) {
            return null;
        }
        return toHexString(asString(encryptByte(data, key)));
    }

    private String toHexString(String s) {
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            int ch = s.charAt(i);
            String s4 = Integer.toHexString(ch & 0xFF);
            if (s4.length() == 1) {
                s4 = '0' + s4;
            }
            str.append(s4);
        }
        // 0x表示十六进制
        return str.toString();
    }
    private byte[] encryptByte(String data, String key) {
        if (data == null || key == null) {
            return null;
        }
        byte[] bData = data.getBytes();
        return RC4Base(bData, key);
    }
    private String asString(byte[] buf) {
        StringBuilder strBuf = new StringBuilder(buf.length);
        for (int i = 0; i < buf.length; i++) {
            strBuf.append((char) buf[i]);
        }
        return strBuf.toString();
    }
    private byte[] RC4Base(byte[] input, String mKkey) {
        int x = 0;
        int y = 0;
        byte[] key = this.initKey(mKkey);
        int xorIndex;
        byte[] result = new byte[input.length];

        for (int i = 0; i < input.length; i++) {
            x = (x + 1) & 0xff;
            assert key != null;
            y = ((key[x] & 0xff) + y) & 0xff;
            byte tmp = key[x];
            key[x] = key[y];
            key[y] = tmp;
            xorIndex = ((key[x] & 0xff) + (key[y] & 0xff)) & 0xff;
            result[i] = (byte) (input[i] ^ key[xorIndex]);
        }
        return result;
    }

    /**
     * RC4解密
     * @param data 需要解密的内容
     * @param key 自定义密钥
     * @return 解密后的内容
     */
    public String decrypt(String data, String key) {
        if (data == null || key == null) {
            return null;
        }
        return new String(RC4Base(hexString2Bytes(data), key));
    }

    /**
     * 私钥转为二进制数组
     * @param aKey
     * @return
     */
    private byte[] initKey(String aKey) {
        byte[] bKey = aKey.getBytes();
        byte[] state = new byte[256];

        for (int i = 0; i < 256; i++) {
            state[i] = (byte) i;
        }
        int index1 = 0;
        int index2 = 0;
        if (bKey.length == 0) {
            return null;
        }
        for (int i = 0; i < 256; i++) {
            index2 = ((bKey[index1] & 0xff) + (state[i] & 0xff) + index2) & 0xff;
            byte tmp = state[i];
            state[i] = state[index2];
            state[index2] = tmp;
            index1 = (index1 + 1) % bKey.length;
        }
        return state;
    }
    private byte[] hexString2Bytes(String src) {
        int size = src.length();
        byte[] ret = new byte[size / 2];
        byte[] tmp = src.getBytes();
        for (int i = 0; i < size / 2; i++) {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }

    private byte uniteBytes(byte src0, byte src1) {
        char _b0 = (char) Byte.decode("0x" + new String(new byte[] { src0 })).byteValue();
        _b0 = (char) (_b0 << 4);
        char _b1 = (char) Byte.decode("0x" + new String(new byte[] { src1 })).byteValue();
        return (byte) (_b0 ^ _b1);
    }

//    public static void main(String[] args) {
//        RC4Util rc4Util = new RC4Util();
//        String key = "abcd123";
//        String encrypted = rc4Util.encrypt("hello rc4", key);
//        System.out.println(encrypted);
//        System.out.println(rc4Util.decrypt(encrypted, key));
//    }
}

IDEA

package cn.com.wuhm.common.encoded;

import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.Security;

/**
 * 对称之IDEA加密解密
 *
 * @Description idea 加密和解密过程中,明文和密文是分成64比特的块来处理的。但是秘钥宽度是128比特,加密是依赖三种代数群运算,每个代数群都是16比特数的运算。
 * @Author wuhuaming
 * @Date 2023/9/12
 */
@Slf4j
public class IDEAUtil {
    /**
     * Idea生成的秘钥
     *
     * @return
     */
    public String getKey() {
        String result = null;
        try {
            result = (new BASE64Encoder()).encodeBuffer(this.initKey());
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("随机::Idea生成的秘钥是:" + result);
        return result;
    }

    /**
     * 生成密钥,只有bouncycastle支持
     *
     * @return byte[] 二进制密钥
     */
    private byte[] initKey() throws Exception {
        //加入bouncyCastle支持
        Security.addProvider(new BouncyCastleProvider());
        //实例化密钥生成器
        KeyGenerator kg = KeyGenerator.getInstance("IDEA");
        //初始化密钥生成器,IDEA要求密钥长度为128位
        kg.init(128);
        //生成密钥
        SecretKey secretKey = kg.generateKey();
        //获取二进制密钥编码形式
        return secretKey.getEncoded();
    }

    /**
     * 转换密钥
     *
     * @param key 二进制密钥
     * @return Key 密钥
     */
    private Key toKey(byte[] key) {
        //实例化DES密钥
        //生成密钥
        return new SecretKeySpec(key, "IDEA");
    }

    /**
     * idea 加密返回base64编码
     *
     * @param data
     * @param key
     * @return
     */
    public String ideaEncrypt(String data, String key) {
        String result = null;
        try {
            byte[] dataEn = encrypt(data.getBytes(), (new BASE64Decoder()).decodeBuffer(key));//Base64.decodeBase64(key)
            //Base64.encodeBase64String(data_en);
            result = (new BASE64Encoder()).encodeBuffer(dataEn);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 加密数据
     *
     * @param data 待加密数据
     * @param key  密钥
     * @return byte[] 加密后的数据
     */
    private byte[] encrypt(byte[] data, byte[] key) throws Exception {
        //加入bouncyCastle支持
        Security.addProvider(new BouncyCastleProvider());
        //还原密钥
        Key k = this.toKey(key);
        //实例化
        Cipher cipher = Cipher.getInstance("IDEA/ECB/ISO10126Padding");
        //初始化,设置为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, k);
        //执行操作
        return cipher.doFinal(data);
    }

    /**
     * 解密数据转String
     * @param data
     * @param key
     * @return
     */
    public String ideaDecrypt(String data, String key) {
        String result = null;
        try {
            byte[] dataDe = this.decrypt((new BASE64Decoder()).decodeBuffer(data), (new BASE64Decoder()).decodeBuffer(key));;
            result = new String(dataDe);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    /**
     * 解密数据
     * @param data 待解密数据
     * @param key 密钥
     * @return byte[] 解密后的数据
     * */
    public byte[] decrypt(byte[] data,byte[] key) throws Exception{
        //加入bouncyCastle支持
        Security.addProvider(new BouncyCastleProvider());
        //还原密钥
        Key k =toKey(key);
        Cipher cipher=Cipher.getInstance("IDEA/ECB/ISO10126Padding");
        //初始化,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, k);
        //执行操作
        return cipher.doFinal(data);
    }


//    public static void main(String[] args) {
//        IDEAUtil ideaUtil = new IDEAUtil();
//        String key = ideaUtil.getKey();
//        String ideaEncrypt = ideaUtil.ideaEncrypt("hello idea", key);
//        System.out.println(ideaEncrypt);
//
//        System.out.println(ideaUtil.ideaDecrypt(ideaEncrypt, key));
//
//    }
}
0%