parent
04f5e7e68a
commit
73fc97db5f
@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package opsli.plugins.crypto.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称算法类型
|
||||||
|
*
|
||||||
|
* @author Parker
|
||||||
|
* @date 2021年5月17日16:48:14
|
||||||
|
*/
|
||||||
|
public enum CryptoSymmetricType {
|
||||||
|
|
||||||
|
/** 对称算法类型 */
|
||||||
|
AES("AES", "AES 算法"),
|
||||||
|
DES("DES", "DES 算法"),
|
||||||
|
DE_SEDE("DESede", "DESede 算法"),
|
||||||
|
SM4("SM4", "SM4 算法"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
public static CryptoSymmetricType getCryptoType(String code) {
|
||||||
|
CryptoSymmetricType[] types = values();
|
||||||
|
for (CryptoSymmetricType type : types) {
|
||||||
|
if (type.code.equalsIgnoreCase(code)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return this.desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================
|
||||||
|
|
||||||
|
CryptoSymmetricType(final String code, final String desc) {
|
||||||
|
this.code = code;
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package opsli.plugins.crypto.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import opsli.plugins.crypto.enums.CryptoSymmetricType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称加密
|
||||||
|
*
|
||||||
|
* @author Parker
|
||||||
|
* @date 2021年5月17日15:59:52
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CryptoSymmetric {
|
||||||
|
|
||||||
|
/** 加解密类别 */
|
||||||
|
private CryptoSymmetricType cryptoType;
|
||||||
|
|
||||||
|
/** 私钥 */
|
||||||
|
private String privateKey;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package opsli.plugins.crypto.strategy;
|
||||||
|
|
||||||
|
import opsli.plugins.crypto.enums.CryptoAsymmetricType;
|
||||||
|
import opsli.plugins.crypto.enums.CryptoSymmetricType;
|
||||||
|
import opsli.plugins.crypto.model.CryptoAsymmetric;
|
||||||
|
import opsli.plugins.crypto.model.CryptoSymmetric;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称 加解密策略接口
|
||||||
|
*
|
||||||
|
* @author Parker
|
||||||
|
* @date 2021年5月17日15:49:15
|
||||||
|
*/
|
||||||
|
public interface CryptoSymmetricService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建空模型
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
CryptoSymmetric createNilModel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建公私钥
|
||||||
|
* @param cryptoSymmetricType 枚举
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
CryptoSymmetric createKeyModel(final CryptoSymmetricType cryptoSymmetricType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密数据
|
||||||
|
* @param model 加解密模型
|
||||||
|
* @param data 数据
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
String encrypt(final CryptoSymmetric model, final Object data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密数据
|
||||||
|
* @param model 加解密模型
|
||||||
|
* @param data 数据
|
||||||
|
* @return Object
|
||||||
|
*/
|
||||||
|
Object decryptToObj(final CryptoSymmetric model, final String data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密数据
|
||||||
|
* @param model 加解密模型
|
||||||
|
* @param data 数据
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
String decrypt(final CryptoSymmetric model, final String data);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,310 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package opsli.plugins.crypto.strategy.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.codec.Base64;
|
||||||
|
import cn.hutool.core.util.*;
|
||||||
|
import cn.hutool.crypto.KeyUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.crypto.SmUtil;
|
||||||
|
import cn.hutool.crypto.symmetric.AES;
|
||||||
|
import cn.hutool.crypto.symmetric.SymmetricCrypto;
|
||||||
|
import cn.hutool.json.JSONException;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import opsli.plugins.crypto.enums.CryptoSymmetricType;
|
||||||
|
import opsli.plugins.crypto.exception.CryptoException;
|
||||||
|
import opsli.plugins.crypto.model.CryptoSymmetric;
|
||||||
|
import opsli.plugins.crypto.msg.CryptoMsg;
|
||||||
|
import opsli.plugins.crypto.strategy.CryptoSymmetricService;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 非对称加密
|
||||||
|
*
|
||||||
|
* @author Parker
|
||||||
|
* @date 2021年5月18日10:53:27
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class CryptoSymmetricServiceImpl implements CryptoSymmetricService {
|
||||||
|
|
||||||
|
/** 默认缓存个数 超出后流量自动清理 */
|
||||||
|
private static final int DEFAULT_CACHE_COUNT = 1000;
|
||||||
|
/** 默认缓存时效 超出后自动清理 */
|
||||||
|
private static final int DEFAULT_CACHE_TIME = 20;
|
||||||
|
/** 加解密执行器缓存 防止多次创建 */
|
||||||
|
private static final Map<CryptoSymmetricType, Cache<String, SymmetricCrypto>> LFU_CACHE_MAP;
|
||||||
|
|
||||||
|
static{
|
||||||
|
// 初始化缓存类对象
|
||||||
|
LFU_CACHE_MAP = Maps.newConcurrentMap();
|
||||||
|
for (CryptoSymmetricType asymmetricType : CryptoSymmetricType.values()) {
|
||||||
|
LFU_CACHE_MAP.put(asymmetricType,
|
||||||
|
CacheBuilder
|
||||||
|
.newBuilder().maximumSize(DEFAULT_CACHE_COUNT)
|
||||||
|
.expireAfterWrite(DEFAULT_CACHE_TIME, TimeUnit.MINUTES).build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建空模型
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CryptoSymmetric createNilModel() {
|
||||||
|
return new CryptoSymmetric();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建公私钥
|
||||||
|
* @param cryptoSymmetricType 枚举
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CryptoSymmetric createKeyModel(final CryptoSymmetricType cryptoSymmetricType){
|
||||||
|
SymmetricCrypto cryptoHandler =
|
||||||
|
this.createCryptoHandler(cryptoSymmetricType);
|
||||||
|
CryptoSymmetric model = this.createNilModel();
|
||||||
|
|
||||||
|
if(cryptoHandler != null){
|
||||||
|
SecretKey secretKey = cryptoHandler.getSecretKey();
|
||||||
|
String privateKey = Base64.encode(secretKey.getEncoded());
|
||||||
|
model.setCryptoType(cryptoSymmetricType);
|
||||||
|
model.setPrivateKey(privateKey);
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密数据
|
||||||
|
* @param model 加解密模型
|
||||||
|
* @param data 数据
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String encrypt(final CryptoSymmetric model, final Object data){
|
||||||
|
// 非法验证
|
||||||
|
this.verify(model);
|
||||||
|
|
||||||
|
// 原始/加密 数据
|
||||||
|
String encryptedStr;
|
||||||
|
try {
|
||||||
|
encryptedStr = JSONUtil.toJsonStr(data);
|
||||||
|
|
||||||
|
// 创建执行器
|
||||||
|
SymmetricCrypto cryptoHandler =
|
||||||
|
this.createCryptoHandler(model);
|
||||||
|
if(cryptoHandler == null){
|
||||||
|
// 无法获得加解密执行器
|
||||||
|
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_HANDLER_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行加密操作
|
||||||
|
encryptedStr = cryptoHandler.encryptBase64(StrUtil.bytes(encryptedStr, CharsetUtil.CHARSET_UTF_8));
|
||||||
|
|
||||||
|
}catch (JSONException jse){
|
||||||
|
// 加密数据转换Json失败
|
||||||
|
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_TO_JSON);
|
||||||
|
}catch (CryptoException ce){
|
||||||
|
// 如果检测到已有异常 则直接抛出
|
||||||
|
throw ce;
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
// 加密失败
|
||||||
|
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_EN);
|
||||||
|
}
|
||||||
|
return encryptedStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密数据 - 反射Obj对象
|
||||||
|
* @param model 加解密模型
|
||||||
|
* @param data 数据
|
||||||
|
* @return Object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object decryptToObj(final CryptoSymmetric model, final String data){
|
||||||
|
Object obj;
|
||||||
|
// 解密数据
|
||||||
|
String decryptedData = decrypt(model, data);
|
||||||
|
// 反射对象
|
||||||
|
try{
|
||||||
|
obj = JSONUtil.parse(decryptedData);
|
||||||
|
}catch (Exception e){
|
||||||
|
// 非对称解密反射失败
|
||||||
|
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_REFLEX);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密数据
|
||||||
|
* @param model 加解密模型
|
||||||
|
* @param data 数据
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String decrypt(final CryptoSymmetric model, final String data){
|
||||||
|
// 非法验证
|
||||||
|
this.verify(model);
|
||||||
|
|
||||||
|
// 如果解密内容为空 则返回原内容
|
||||||
|
if(StringUtils.isEmpty(data)){
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
String decryptStr;
|
||||||
|
try {
|
||||||
|
// 创建执行器
|
||||||
|
SymmetricCrypto cryptoHandler =
|
||||||
|
this.createCryptoHandler(model);
|
||||||
|
if(cryptoHandler == null){
|
||||||
|
// 无法获得加解密执行器
|
||||||
|
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_HANDLER_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数据
|
||||||
|
String currData = data.replaceAll(" ", "+");
|
||||||
|
// 解密数据 - 返回Json 格式String
|
||||||
|
decryptStr = cryptoHandler.decryptStr(currData, CharsetUtil.CHARSET_UTF_8);
|
||||||
|
}catch (CryptoException ce){
|
||||||
|
// 如果检测到已有异常 则直接抛出
|
||||||
|
throw ce;
|
||||||
|
}catch (Exception e){
|
||||||
|
// 解密失败
|
||||||
|
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_DE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return decryptStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证
|
||||||
|
* @param model 加解密模型
|
||||||
|
*/
|
||||||
|
private void verify(CryptoSymmetric model){
|
||||||
|
// 非法验证
|
||||||
|
if(model == null ||
|
||||||
|
model.getCryptoType() == null ||
|
||||||
|
StringUtils.isEmpty(model.getPrivateKey())
|
||||||
|
){
|
||||||
|
// 配置信息未初始化
|
||||||
|
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_MODEL_NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 加解密执行器
|
||||||
|
* 这里使用了缓存池 来防止对象被疯狂创建 减少服务压力
|
||||||
|
*
|
||||||
|
* @param model 加解密模型
|
||||||
|
* @return 执行器
|
||||||
|
*/
|
||||||
|
private SymmetricCrypto createCryptoHandler(final CryptoSymmetric model){
|
||||||
|
// 非法验证
|
||||||
|
if(model == null ||
|
||||||
|
model.getCryptoType() == null ||
|
||||||
|
StringUtils.isEmpty(model.getPrivateKey())
|
||||||
|
){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache<String, SymmetricCrypto> cryptoCache =
|
||||||
|
LFU_CACHE_MAP.get(model.getCryptoType());
|
||||||
|
|
||||||
|
|
||||||
|
SymmetricCrypto cryptoHandler = null;
|
||||||
|
try {
|
||||||
|
// 查询并设置缓存
|
||||||
|
cryptoHandler = cryptoCache.get(model.getPrivateKey(), () -> {
|
||||||
|
SymmetricCrypto tmp = null;
|
||||||
|
byte[] keyBytes = Base64.decode(model.getPrivateKey());
|
||||||
|
switch (model.getCryptoType()) {
|
||||||
|
case AES:{
|
||||||
|
tmp = SecureUtil.aes(keyBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DES:{
|
||||||
|
tmp = SecureUtil.des(keyBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DE_SEDE:{
|
||||||
|
tmp = SecureUtil.desede(keyBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SM4:{
|
||||||
|
tmp = SmUtil.sm4(keyBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
});
|
||||||
|
}catch (ExecutionException e){
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cryptoHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 加解密执行器
|
||||||
|
* @param cryptoSymmetricType 枚举
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
private SymmetricCrypto createCryptoHandler(final CryptoSymmetricType cryptoSymmetricType){
|
||||||
|
SymmetricCrypto cryptoHandler = null;
|
||||||
|
switch (cryptoSymmetricType){
|
||||||
|
case AES:{
|
||||||
|
cryptoHandler = SecureUtil.aes();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DES:{
|
||||||
|
cryptoHandler = SecureUtil.des();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DE_SEDE:{
|
||||||
|
cryptoHandler = SecureUtil.desede();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SM4:{
|
||||||
|
cryptoHandler = SmUtil.sm4();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cryptoHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in new issue