常见的对称加密解密算法
目录
常见的对称加密解密算法
转载至[博客](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));
//
// }
}