Browse Source

517 峰会免密登录

sprint/s4
董书康 7 months ago
parent
commit
59c56f4aa5
11 changed files with 598 additions and 5 deletions
  1. +1
    -0
      demo-athenaopt_backend/develop/conf/application.properties
  2. +103
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/constant/GlobalConstants.java
  3. +39
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/entity/DigiwinSummit.java
  4. +20
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/repository/DigiwinSummitRepository.java
  5. +7
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/service/DigiwinSummitService.java
  6. +16
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/service/Impl/DigiwinSummitServiceImpl.java
  7. +11
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/provider/BasicApiService.java
  8. +21
    -5
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/provider/impl/BasicApiServiceImpl.java
  9. +86
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/service/basic/AESUtils.java
  10. +176
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/service/basic/LoginService.java
  11. +118
    -0
      demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/service/basic/RSAUtils.java

+ 1
- 0
demo-athenaopt_backend/develop/conf/application.properties View File

@ -9,6 +9,7 @@ configGroup=@configGroup@
#SMALLVERSION=@SMALLVERSION@ #SMALLVERSION=@SMALLVERSION@
#springConfigFileNames=xxx.xml,xxx.xml #springConfigFileNames=xxx.xml,xxx.xml
iamApToken=@iamApToken@ iamApToken=@iamApToken@
iamApTokenForLogin=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzczMjY2ODk0NjEsInNpZCI6NDA3MTI4ODI1NTM0NDY0MSwiaWQiOiJEaWdpd2luQ2xvdWQifQ.XGPl3brNeNTCivWN_bIYj8TfcxqlkQ0sFV2woPOr0TY
dmcUserName=@dmcUserName@ dmcUserName=@dmcUserName@
dmcPwd=@dmcPwd@ dmcPwd=@dmcPwd@
dmcBucketName=@dmcBucketName@ dmcBucketName=@dmcBucketName@


+ 103
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/constant/GlobalConstants.java View File

@ -0,0 +1,103 @@
package com.digiwin.athena.app.infra.constant;
/**
* 全局常量
*
* @author fobgochod
* @date 2020/4/27
*/
public class GlobalConstants {
/**
* 访问凭证
*/
public static final String DIGI_MIDDLEWARE_AUTH_ACCESS = "digi-middleware-auth-access";
/**
* 在HttpHeader中传递的User信息
*/
public static final String AUTH_USER = "digi-middleware-auth-user-data";
/**
* 在HttpHeader中传递的App信息
*/
public static final String APP = "digi-middleware-auth-app-data";
/**
* 在HttpHeader中传递的OTA Token信息
*/
public static final String HTTP_HEADER_OTA_TOKEN_KEY = "digi-middleware-auth-ota";
/**
* 在HttpHeader中传递的Access Token信息
*/
public static final String HTTP_HEADER_ACCESS_TOKEN_KEY = "digi-middleware-auth-access";
/**
* 在HttpHeader中传递的User Token信息
*/
public static final String HTTP_HEADER_USER_TOKEN_KEY = "digi-middleware-auth-user";
/**
* 在HttpHeader中传递的APP Token信息
*/
public static final String HTTP_HEADER_APP_TOKEN_KEY = "digi-middleware-auth-app";
/**
* 在HttpHeader中传递的Driver Token信息
*/
public static final String HTTP_HEADER_DRIVE_TOKEN_KEY = "digi-middleware-drive-access";
/**
* 在HttpHeader中传递 是都需要加密
*/
public static final String HTTP_HEADER_DATA_MASK = "digi-middleware-data-mask";
/**
* 在HttpHeader中传递 租户ID
*/
public static final String HTTP_HEADER_TENANT_ID = "tenantId";
/**
* 在HttpHeader中传递 设备信息
*/
public static final String HTTP_HEADER_CLIENT_AGENT = "Client-Agent";
/**
* 查询时若為歸戶資料請填入固定值: iam-mapping
*/
public static final String QUERY_PARAMETER_MAPPING = "iam-mapping";
public static final String ZONE_OFF_SET = "+8";
public static final String DEV_ACTIVE = "dev";
public static final String EMPTY_STR = "[empty]";
public static final String UPDATE_ALL = "all";
public static final String UPDATE_ONLY_APPEND = "onlyAppend";
public static final String ADMINISTRATORS = "administrators";
public static final String ADMINISTRATOR = "administrator";
public static final String INTEGRATION = "integration";
public static final String SUPERADMIN = "superadmin";
public static final String GUEST = "guest";
public static final String ERROR_MESSAGE = "Server internal error";
public static final String ENV_DEV = "dev";
public static final String ENV_PROD = "prod";
public static final String ENV_TEST = "test";
public static final char AT = '@';
public static final char DOT = '.';
public static final char TAB = '\t';
public static final char DASH = '-';
public static final char COLON = ':';
public static final char COMMA = ',';
public static final char DOLLAR = '$';
public static final char PERCENT = '%';
public static final char ESCAPE = '\\';
public static final char ASTERISK = '*';
public static final char SEMICOLON = ';';
public static final char CURLY_LEFT = '{';
public static final char CURLY_RIGHT = '}';
public static final char DOUBLE_QUOTE = '"';
public static final char SINGLE_QUOTE = '\'';
public static final char LEFT_PARENTHESIS = '(';
public static final char RIGHT_PARENTHESIS = ')';
public static final String EMPTY = "";
public static final String TRUE = "true";
public static final String FALSE = "false";
public static final String DEFAULT_VALUE_SEPARATOR = ":-";
public static final String DEFAULT_CONTEXT_NAME = "default";
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static final String ACCEPT_LANGUAGE = "Accept-Language";
public static final String LOCALE = "Locale";
}

+ 39
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/entity/DigiwinSummit.java View File

@ -0,0 +1,39 @@
/*
* Author: DONGSK
* Datetime: 2024/4/25 16:43
* Description:
* History:
* 作者姓名 --修改时间 --版本号--描述
*/
package com.digiwin.athena.app.infra.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import java.io.Serializable;
/**
* DigiwinSummit
*
* @author DONGSK 2024/4/25 16:43
* @since 1.0.0
*/
@Data
@TableName(value = "digiwin_summit", autoResultMap = true)
public class DigiwinSummit extends Model<DigiwinSummit> implements Serializable {
Long id;
@TableField(value = "user_id")
String userId;
@TableField(value = "tenant_id")
String tenantId;
@TableField(value = "ref_prod")
String refProd;
@TableField(value = "ref_user_id")
String refUserId;
@TableField(value = "ref_tenant_sid")
String refTenantSid;
@TableField(value = "ref_user_password")
String refUserPassword;
}

+ 20
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/repository/DigiwinSummitRepository.java View File

@ -0,0 +1,20 @@
/*
* Author: DONGSK
* Datetime: 2024/4/25 16:49
* Description:
* History:
* 作者姓名 --修改时间 --版本号--描述
*/
package com.digiwin.athena.app.infra.repository;
import com.digiwin.athena.app.infra.entity.DigiwinSummit;
import com.digiwin.athena.opt.persistence.repository.BaseRepository;
/**
* DigiwinSummitRepository
*
* @author DONGSK 2024/4/25 16:49
* @since 1.0.0
*/
public interface DigiwinSummitRepository extends BaseRepository<DigiwinSummit> {
}

+ 7
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/service/DigiwinSummitService.java View File

@ -0,0 +1,7 @@
package com.digiwin.athena.app.infra.service;
import com.digiwin.athena.app.infra.entity.DigiwinSummit;
import com.digiwin.athena.opt.persistence.service.IBaseService;
public interface DigiwinSummitService extends IBaseService<DigiwinSummit> {
}

+ 16
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/infra/service/Impl/DigiwinSummitServiceImpl.java View File

@ -0,0 +1,16 @@
package com.digiwin.athena.app.infra.service.Impl;
import com.digiwin.athena.app.infra.entity.DigiwinSummit;
import com.digiwin.athena.app.infra.repository.DigiwinSummitRepository;
import com.digiwin.athena.app.infra.service.DigiwinSummitService;
import com.digiwin.athena.opt.persistence.service.impl.AbsBaseService;
import org.springframework.stereotype.Service;
/**
* @author zhenggl
* create: 2023-04-28
* Description:
*/
@Service
public class DigiwinSummitServiceImpl extends AbsBaseService<DigiwinSummitRepository, DigiwinSummit> implements DigiwinSummitService {
}

+ 11
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/provider/BasicApiService.java View File

@ -32,4 +32,15 @@ public interface BasicApiService extends DWService {
@DWRequestMapping(path = "/EAIService/{serviceName}", method = DWRequestMethod.POST) @DWRequestMapping(path = "/EAIService/{serviceName}", method = DWRequestMethod.POST)
Object mockEAIExecutor(@DWPathVariable String serviceName, Map<String, Object> requestParameter) throws Exception; Object mockEAIExecutor(@DWPathVariable String serviceName, Map<String, Object> requestParameter) throws Exception;
@AllowAnonymous
@DWRequestMapping(path = "/api/default/login", method = DWRequestMethod.POST)
Object login(String userId, String tenantId, String productKey) throws Exception;
@AllowAnonymous
@DWRequestMapping(path = "/api/clear/login", method = DWRequestMethod.GET)
Object clearLogin() throws Exception;
} }

+ 21
- 5
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/provider/impl/BasicApiServiceImpl.java View File

@ -11,6 +11,7 @@ package com.digiwin.athena.app.provider.impl;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.digiwin.app.service.DWServiceContext; import com.digiwin.app.service.DWServiceContext;
import com.digiwin.athena.app.provider.BasicApiService; import com.digiwin.athena.app.provider.BasicApiService;
import com.digiwin.athena.app.service.basic.LoginService;
import com.digiwin.athena.opt.common.eai.service.EAIServiceContext; import com.digiwin.athena.opt.common.eai.service.EAIServiceContext;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -28,6 +29,9 @@ public class BasicApiServiceImpl implements BasicApiService {
@Resource @Resource
EAIServiceContext eaiServiceContext; EAIServiceContext eaiServiceContext;
@Resource
LoginService loginService;
@Override @Override
public String helloWord(String name) throws Exception { public String helloWord(String name) throws Exception {
return "hello ," + name; return "hello ," + name;
@ -41,10 +45,22 @@ public class BasicApiServiceImpl implements BasicApiService {
}); });
DWServiceContext.getContext().setStandardResult(false); DWServiceContext.getContext().setStandardResult(false);
/** 直接返回不再包装入参可以体现 serviceName /** 直接返回不再包装入参可以体现 serviceName
Map<String, Object> eaiResult = new HashMap<>();
eaiResult.put("service", serviceName);
eaiResult.put("response", eaiServiceContext.execute(serviceName, headers, JSON.toJSONString(requestParameter)));
*/
return eaiServiceContext.execute(serviceName, headers, JSON.toJSONString(requestParameter));
Map<String, Object> eaiResult = new HashMap<>();
eaiResult.put("service", serviceName);
eaiResult.put("response", eaiServiceContext.execute(serviceName, headers, JSON.toJSONString(requestParameter)));
*/
return eaiServiceContext.execute(serviceName, headers, JSON.toJSONString(requestParameter));
}
@Override
public Object login(String userId, String tenantId, String productKey) throws Exception {
return loginService.login(userId, tenantId, productKey);
} }
@Override
public Object clearLogin() throws Exception {
loginService.clearLoginMap();
return "ok";
}
} }

+ 86
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/service/basic/AESUtils.java View File

@ -0,0 +1,86 @@
package com.digiwin.athena.app.service.basic;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class AESUtils {
private static final Logger logger = LoggerFactory.getLogger(AESUtils.class);
private static final String IV_STRING = "ghUb#er57HBh(u%g";
/**
* 加密
* 加密失败返回原文 2021-7-21
*
* @param src 加密字段
* @param aesKey aesKey 长度16
* @return 密文 string
*/
public static String aesEncryptByBase64(String src, String aesKey) {
try {
SecretKeySpec key = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
byte[] initParam = IV_STRING.getBytes(StandardCharsets.UTF_8);
IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
byte[] cleartext = src.getBytes(StandardCharsets.UTF_8);
byte[] ciphertextBytes = cipher.doFinal(cleartext);
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(ciphertextBytes);
} catch (Exception ex) {
logger.error("AES加密失败[{}]", src);
return src;
}
}
public static String aesEncrypt(String src, String aesKey) {
try {
// 生成和mysql一致的加密数据
SecretKeySpec key = generateMySQLAESKey(aesKey);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cleartext = src.getBytes(StandardCharsets.UTF_8);
byte[] ciphertextBytes = cipher.doFinal(cleartext);
return new String(Hex.encodeHexString(ciphertextBytes)).toUpperCase();
} catch (Exception ex) {
logger.error("AES加密失败[{}]", src);
return src;
}
}
public static String aesDecrypt(String content, String aesKey) {
try {
SecretKey key = generateMySQLAESKey(aesKey);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] cleartext = Hex.decodeHex(content.toCharArray());
byte[] ciphertextBytes = cipher.doFinal(cleartext);
return new String(ciphertextBytes, StandardCharsets.UTF_8);
} catch (Exception ex) {
logger.error("AES解密失败[{}]", content);
return content;
}
}
public static SecretKeySpec generateMySQLAESKey(final String key) {
final byte[] finalKey = new byte[16];
int i = 0;
for (byte b : key.getBytes(StandardCharsets.UTF_8)) {
finalKey[i++ % 16] ^= b;
}
return new SecretKeySpec(finalKey, "AES");
}
}

+ 176
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/service/basic/LoginService.java View File

@ -0,0 +1,176 @@
/*
* Author: DONGSK
* Datetime: 2024/4/25 14:08
* Description: 登录服务
* History:
* 作者姓名 --修改时间 --版本号--描述
*/
package com.digiwin.athena.app.service.basic;
import com.digiwin.athena.app.infra.constant.GlobalConstants;
import com.digiwin.athena.app.infra.entity.DigiwinSummit;
import com.digiwin.athena.app.infra.service.DigiwinSummitService;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
/**
* LoginService
* 登录服务
*
* @author DONGSK 2024/4/25 14:08
* @since 1.0.0
*/
@Service
public class LoginService {
private static final Logger logger = LoggerFactory.getLogger(LoginService.class);
public static final Map<String, DigiwinSummit> loginDataMap = new HashMap<>();
public static final String mapKey = "%s_%s_%s";
@Value("${iamApTokenForLogin}")
private String iamApToken;
@Value("${iamUrl}")
private String iamURL;
@Resource
RestTemplate restTemplate;
@Resource
DigiwinSummitService digiwinSummitService;
public Object login(String userId, String tenantId, String productKey) {
String uri = iamURL + "/api/iam/v2/identity/login";
try {
initLoginMap();
String mapKey = String.format(LoginService.mapKey, userId, tenantId, productKey);
DigiwinSummit digiwinSummit = loginDataMap.get(mapKey);
if (digiwinSummit == null) {
return null;
}
// password
String password = digiwinSummit.getRefUserPassword();
//1.客户端生成公私钥
HashMap<String, String> keyMap = getKeyPairMap();
String clientPublicKey = keyMap.get("publicKey");
String privateKey = keyMap.get("privateKey");
//2.获取服务端公钥
String serverPublicKey = getServerPublicKey();
//3.根据服务端公钥加密客户端公钥
String encryptPublicKey = RSAUtils.encryptByPublicKey(clientPublicKey, serverPublicKey);
//4.获取加密后的AES的key值
String encryptAesKey = getAesPublicKey(encryptPublicKey);
//5.根据客户端私有解密加密的aes的key值
String aesKey = new String(RSAUtils.decryptByPrivateKey(Base64.decodeBase64(encryptAesKey), privateKey));
String passwordHash = AESUtils.aesEncryptByBase64(password, aesKey);
//6.登录
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add(GlobalConstants.HTTP_HEADER_APP_TOKEN_KEY, iamApToken);
Map<String, String> requestEntity = new HashMap<>(3);
requestEntity.put("identityType", "token");
requestEntity.put("userId", digiwinSummit.getRefUserId());
requestEntity.put("passwordHash", passwordHash);
requestEntity.put("clientEncryptPublicKey", encryptPublicKey);
HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(requestEntity, headers);
ResponseEntity<Map> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, Map.class);
// 切租户
return changeTenant(Long.valueOf(digiwinSummit.getRefTenantSid()), response.getBody().get("token").toString());
} catch (Exception ex) {
logger.error("登录失败:{}", ex.getMessage(), ex);
}
return null;
}
private Object changeTenant(Long sid, String userToken) {
String uri = iamURL + "/api/iam/v2/identity/token/refresh/tenant";
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add(GlobalConstants.HTTP_HEADER_APP_TOKEN_KEY, iamApToken);
headers.add(GlobalConstants.HTTP_HEADER_USER_TOKEN_KEY, userToken);
Map<String, Long> requestEntity = new HashMap<>();
requestEntity.put("tenantSid", sid);
HttpEntity<Map<String, Long>> httpEntity = new HttpEntity<>(requestEntity, headers);
ResponseEntity<Map> exchange = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, Map.class);
return exchange.getBody();
} catch (Exception e) {
logger.error("切换失败:{}", e.getMessage(), e);
}
return "";
}
private HashMap<String, String> getKeyPairMap() throws NoSuchAlgorithmException {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
KeyPair keyPair = generator.generateKeyPair();
String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
HashMap<String, String> keyMap = new HashMap<>();
keyMap.put("privateKey", privateKey);
keyMap.put("publicKey", publicKey);
return keyMap;
}
private String getServerPublicKey() {
String uri = iamURL + "/api/iam/v2/identity/publickey";
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add(GlobalConstants.HTTP_HEADER_APP_TOKEN_KEY, iamApToken);
HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(headers);
ResponseEntity<Map> response = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, Map.class);
return String.valueOf(response.getBody().get("publicKey"));
} catch (Exception e) {
logger.error("登录失败:{}", e.getMessage(), e);
}
return "";
}
private String getAesPublicKey(String encryptPublicKey) {
String uri = iamURL + "/api/iam/v2/identity/aeskey";
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add(GlobalConstants.HTTP_HEADER_APP_TOKEN_KEY, iamApToken);
Map<String, String> requestEntity = new HashMap<>(1);
requestEntity.put("clientEncryptPublicKey", encryptPublicKey);
HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(requestEntity, headers);
ResponseEntity<Map> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, Map.class);
return String.valueOf(response.getBody().get("encryptAesKey"));
} catch (Exception e) {
logger.error("登录失败:{}", e.getMessage(), e);
}
return "";
}
private void initLoginMap() {
if (loginDataMap.isEmpty()) {
digiwinSummitService.list().forEach(item -> {
loginDataMap.put(String.format(mapKey, item.getUserId(), item.getTenantId(), item.getRefProd()), item);
});
}
}
public void clearLoginMap() {
loginDataMap.clear();
}
}

+ 118
- 0
demo-athenaopt_backend/develop/src/main/java/com/digiwin/athena/app/service/basic/RSAUtils.java View File

@ -0,0 +1,118 @@
package com.digiwin.athena.app.service.basic;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* @author zhuzcz
*/
public class RSAUtils {
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 245;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 256;
/** */
/**
* <P>
* 私钥解密
* </p>
*
* @param encryptedData 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/** */
/**
* <p>
* 公钥加密
* </p>
*
* @param data 源数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
public static String encryptByPublicKey(String data, String clientPublicKey) throws Exception {
data = Base64.encodeBase64String(encryptByPublicKey(data.getBytes(), clientPublicKey));
return data;
}
}

Loading…
Cancel
Save