Commit 971d4435 authored by AfirSraftGarrier's avatar AfirSraftGarrier

Merge branch 'master' into for-yx-test

# Conflicts:
#	license/src/main/java/iot/sixiang/license/controller/ResourceContrller.java
#	license/src/main/java/iot/sixiang/license/device/DeviceProtocol.java
#	license/src/main/java/iot/sixiang/license/device/DeviceServerHandler.java
#	license/src/main/java/iot/sixiang/license/event/CreateForwardClientEvent.java
#	license/src/main/java/iot/sixiang/license/event/CreateForwardClientEventHandler.java
#	license/src/main/java/iot/sixiang/license/forward/ForwardClient.java
#	license/src/main/java/iot/sixiang/license/forward/ForwardClientHandler.java
#	license/src/main/java/iot/sixiang/license/net/TcpClient.java
#	license/src/main/java/iot/sixiang/license/net/TcpServer.java
#	license/src/main/java/iot/sixiang/license/util/CommonUtil.java
parents ecd85242 b72f3c12
......@@ -169,7 +169,6 @@
</dependencies>
<build>
<finalName>license</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
......
package iot.sixiang.license.consts;
public class Consts {
public static final int CMD_LICENSE = 1;//授权消息的cmd,十进制
public static final int EXECUTOR_THREAD_NUM = 30;
public static final int FORWARD_THREAD_NUM = 30;
public static final int OPERATE_THREAD_NUM = 5;
public static final int DEVICE_STATE_ONLINE = 1;// 设备在线
public static final int DEVICE_STATE_OFFLINE = 0;// 设备离线
public static final int SERVICE_DX_THRESHOLD_NORMAL = 100;
public static final int SERVICE_DX_THRESHOLD_BUSY = 500;
public static final int SERVICE_DX_STATUS_FLUENT = 0;//流畅
public static final int SERVICE_DX_STATUS_NORMAL = 1;//正常
public static final int SERVICE_DX_STATUS_BUSY = 2;//繁忙
public static final int CMD_LICENSE = 1;// 授权消息的cmd,十进制
public static final int EXECUTOR_THREAD_NUM = 30;
public static final int FORWARD_THREAD_NUM = 30;
public static final int OPERATE_THREAD_NUM = 5;
public static final int DEVICE_STATE_ONLINE = 1;// 设备在线
public static final int DEVICE_STATE_OFFLINE = 0;// 设备离线
public static final int SERVICE_DX_THRESHOLD_NORMAL = 100;
public static final int SERVICE_DX_THRESHOLD_BUSY = 500;
public static final int SERVICE_DX_STATUS_FLUENT = 0;// 流畅
public static final int SERVICE_DX_STATUS_NORMAL = 1;// 正常
public static final int SERVICE_DX_STATUS_BUSY = 2;// 繁忙
}
......@@ -3,11 +3,10 @@ package iot.sixiang.license.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import iot.sixiang.license.jwt.UserUtils;
import iot.sixiang.license.log.BusinessType;
import iot.sixiang.license.log.MyLog;
import iot.sixiang.license.resource.ResourceManager;
import iot.sixiang.license.xss.XssUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -15,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
......@@ -26,6 +24,7 @@ public class ResourceContrller {
@Autowired
ResourceManager resourceManager;
@SneakyThrows
@ApiOperation(value = "资源下载接口", notes = "用于下载资源")
@GetMapping("/download")
@MyLog(title = "下载资源", optParam = "#{userId}", businessType = BusinessType.OTHER)
......
......@@ -39,7 +39,7 @@ public class DeviceDecoder extends ByteToMessageDecoder {
return;
}
// buffer.resetReaderIndex();
// buffer.resetReaderIndex();
byte[] content = new byte[real_len - cmd_ack_len];
buffer.readBytes(content);
......
......@@ -4,7 +4,6 @@ import lombok.Data;
@Data
public class DeviceProtocol {
// |STX |LEN |CMD |ACK |DATA |END
private short stx;//
......@@ -24,5 +23,4 @@ public class DeviceProtocol {
this.content = content;
this.end = end;
}
}
\ No newline at end of file
......@@ -36,14 +36,15 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
log.info("read...");
SocketChannel channel = (SocketChannel) ctx.channel();
InetSocketAddress socketAddr = (InetSocketAddress) ctx.channel().remoteAddress();
String remoteIp = socketAddr.getHostString();
int remotePort = socketAddr.getPort();
DeviceProtocol protocol = (DeviceProtocol) msg;
String channelId = channel.id().asLongText();
log.debug("设备服务器,channelRead0:{},{}", channelId, HexUtil.bytes2hex(protocol.getContent()));
/* TODO: 1.透传前先进行鉴权 2.鉴权通过后,创建桥接客户端,非鉴权消息全部放行 3.未鉴权的不能进行透传,强制下线 */
log.info("设备服务器,channelRead0:{},{}", channelId, HexUtil.bytes2hex(protocol.getContent()));
/* 1.透传前先进行鉴权 2.鉴权通过后,创建桥接客户端,非鉴权消息全部放行 3.未鉴权的不能进行透传,强制下线 */
byte cmd = protocol.getCmd();
int cmdInt = cmd & 0xFF;
......@@ -53,18 +54,21 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
} else {
auth = handlerCheckAuthStatus(channel);
if (auth) {
log.info("auth valid...");
handlerForward(channel, protocol);
}
}
// TODO 以下为正式代码
// 以下为正式代码
if (auth == false) {
log.info("close");
channel.close();
}
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
log.debug("设备服务器,channelRegistered:{}", ctx.channel().id().asLongText());
}
......@@ -72,7 +76,7 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
@Override
public synchronized void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
log.debug("设备服务器,channelActive:{}", ctx.channel().id().asLongText());
log.info("设备服务器,channelActive:{}", ctx.channel().id().asLongText());
}
@Override
......@@ -80,7 +84,7 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
super.channelInactive(ctx);
SocketChannel channel = (SocketChannel) ctx.channel();
String channelId = channel.id().asLongText();
log.debug("设备服务器,channelInactive:{}", channelId);
log.info("设备服务器,channelInactive:{}", channelId);
DeviceClientInactiveEvent deviceClientInactiveEvent = new DeviceClientInactiveEvent();
deviceClientInactiveEvent.setChannelId(channelId);
......@@ -91,18 +95,18 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
super.channelReadComplete(ctx);
log.debug("设备服务器,channelReadComplete:{}", ctx.channel().id().asLongText());
log.info("设备服务器,channelReadComplete:{}", ctx.channel().id().asLongText());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
log.debug("设备服务器,exceptionCaught:{}", ctx.channel().id().asLongText());
log.info("设备服务器,exceptionCaught:{}", ctx.channel().id().asLongText());
ctx.close();
}
private boolean handlerCheckAuth(SocketChannel channel, String remoteIp, int remotePort, DeviceProtocol protocol) {
// TODO 正式代码要放开
// 正式代码要放开
LibHelper libHelper = SpringUtil.getBean(LibHelper.class);
byte[] bytes = libHelper.decodeExtendedPayload(protocol.getContent(), 0, protocol.getContent().length);
if (bytes == null) {
......@@ -110,6 +114,7 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
}
String decodeInfo = CommonUtil.bytesToStr(bytes);
log.info("byte to string:" + decodeInfo);
if (decodeInfo == null) {
return false;
}
......@@ -137,7 +142,7 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
DeviceManager deviceManager = SpringUtil.getBean(DeviceManager.class);
deviceManager.putSession(appId, session);
// TODO 创建透传的客户端
// 创建透传的客户端
CreateForwardClientEvent event = new CreateForwardClientEvent();
event.setAppId(appId);
eventPublisher.publishEvent(event);
......
package iot.sixiang.license.event;
import lombok.Data;
@Data
public class CreateForwardClientEvent extends BaseEvent {
private String appId;
private String appId;
}
......@@ -24,7 +24,6 @@ public class CreateForwardClientEventHandler {
@EventListener
public void handlerEvent(CreateForwardClientEvent event) {
String appId = event.getAppId();
Server balanceServer = balanceManager.getBalanceServer();
if (balanceServer != null) {
String serverIp = balanceServer.getServerIp();
......
......@@ -11,7 +11,6 @@ import org.springframework.stereotype.Component;
@Component
@Slf4j
public class DeviceClientLicenseEventHandler {
@Autowired
DeviceManager deviceManager;
@Autowired
......@@ -33,10 +32,6 @@ public class DeviceClientLicenseEventHandler {
} else {
session.getClientChannel().writeAndFlush(protocol);
log.debug("device client license success ...");
}
}
}
......@@ -11,7 +11,6 @@ import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ForwardClientInactiveEventHandler {
@Autowired
DeviceManager deviceManager;
@Autowired
......@@ -20,7 +19,6 @@ public class ForwardClientInactiveEventHandler {
EventPublisher eventPublisher;
public ForwardClientInactiveEventHandler() {
}
@EventListener
......@@ -35,14 +33,12 @@ public class ForwardClientInactiveEventHandler {
String appId = session.getAppId();
boolean result = forwardManager.removeSessionByChannelId(channelId);
if (result) {
// TODO forward client 离线需要强制中断该设备对应的 device client
// forward client 离线需要强制中断该设备对应的 device client
DeviceClientBeForcedOfflineEvent deviceClientBeForcedOfflineEvent = new DeviceClientBeForcedOfflineEvent();
deviceClientBeForcedOfflineEvent.setAppId(appId);
eventPublisher.publishEvent(deviceClientBeForcedOfflineEvent);
log.debug("forward client inactive success ...");
}
}
}
}
......@@ -6,7 +6,7 @@ import lombok.Data;
@Data
public class ForwardMessageResponseEvent extends BaseEvent {
// private String appId;
// private String appId;
private String channelId;
private SocketChannel channel;
private DeviceProtocol protocol;
......
......@@ -17,7 +17,6 @@ import org.springframework.stereotype.Component;
@ChannelHandler.Sharable
@Slf4j
public class ForwardClientHandler extends SimpleChannelInboundHandler<Object> {
@Autowired
EventPublisher eventPublisher;
......@@ -26,45 +25,40 @@ public class ForwardClientHandler extends SimpleChannelInboundHandler<Object> {
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg){
// TODO Auto-generated method stub
// TODO 中转客户端收到消息后,将消息原封不动的发送给设备客户端
protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
// 中转客户端收到消息后,将消息原封不动的发送给设备客户端
log.info("read message...");
SocketChannel channel = (SocketChannel) ctx.channel();
DeviceProtocol protocol = (DeviceProtocol) msg;
String channelId = channel.id().asLongText();
log.debug("桥接客户端,channelRead0:{},{}", channelId, HexUtil.bytes2hex(protocol.getContent()));
log.info("桥接客户端,channelRead0:{},{}", channelId, HexUtil.bytes2hex(protocol.getContent()));
ForwardMessageResponseEvent forwardMessageResponseEvent = new ForwardMessageResponseEvent();
forwardMessageResponseEvent.setChannelId(channelId);
forwardMessageResponseEvent.setChannel(channel);
forwardMessageResponseEvent.setProtocol(protocol);
eventPublisher.publishEvent(forwardMessageResponseEvent);
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
log.debug("桥接客户端,channelRegistered:{}", ctx.channel().id().asLongText());
log.info("桥接客户端,channelRegistered:{}", ctx.channel().id().asLongText());
}
@Override
public synchronized void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
log.debug("桥接客户端,channelActive:{}", ctx.channel().id().asLongText());
log.info("桥接客户端,channelActive:{}", ctx.channel().id().asLongText());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
SocketChannel channel = (SocketChannel) ctx.channel();
String channelId = channel.id().asLongText();
log.debug("桥接客户端,channelInactive:{}", channelId);
log.info("桥接客户端,channelInactive:{}", channelId);
ForwardClientInactiveEvent forwardClientInactiveEvent = new ForwardClientInactiveEvent();
forwardClientInactiveEvent.setChannelId(channelId);
......@@ -74,23 +68,19 @@ public class ForwardClientHandler extends SimpleChannelInboundHandler<Object> {
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelReadComplete(ctx);
log.debug("桥接客户端,channelReadComplete:{}", ctx.channel().id().asLongText());
log.info("桥接客户端,channelReadComplete:{}", ctx.channel().id().asLongText());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
log.debug("桥接客户端,exceptionCaught:{}", ctx.channel().id().asLongText());
log.info("桥接客户端,exceptionCaught:{}", ctx.channel().id().asLongText());
ctx.close();
}
@Override
public synchronized void userEventTriggered(ChannelHandlerContext ctx, Object obj) {
log.debug("桥接客户端,userEventTriggered:{}", ctx.channel().id().asLongText());
log.info("桥接客户端,userEventTriggered:{}", ctx.channel().id().asLongText());
}
}
......@@ -20,7 +20,7 @@ public class ForwardConnectionListener extends BaseConnectionListener {
public void operationComplete(ChannelFuture channelFuture) {
AlarmService alarmService = SpringUtil.getBean(AlarmService.class);
if (!channelFuture.isSuccess()) {
//TODO 失败进行告警
// 失败进行告警
log.debug("桥接客户端,连接服务器失败:{},{},{}", this.host, this.port, this.appId);
int typeId = 1;
......@@ -28,8 +28,7 @@ public class ForwardConnectionListener extends BaseConnectionListener {
String content = "连接服务器:" + this.host + ":" + this.port + "失败";
alarmService.addAlarm(typeId, title, content);
//TODO forward client连接失败,则强制踢掉设备客户端
// forward client连接失败,则强制踢掉设备客户端
DeviceClientBeForcedOfflineEvent deviceClientBeForcedOfflineEvent = new DeviceClientBeForcedOfflineEvent();
deviceClientBeForcedOfflineEvent.setAppId(this.appId);
EventPublisher eventPublisher = SpringUtil.getBean(EventPublisher.class);
......@@ -49,7 +48,6 @@ public class ForwardConnectionListener extends BaseConnectionListener {
EventPublisher eventPublisher = SpringUtil.getBean(EventPublisher.class);
eventPublisher.publishEvent(forwardClientConnectEvent);
short stx = 21930;
byte ack = 0x0;
int len = 3;
......@@ -58,7 +56,6 @@ public class ForwardConnectionListener extends BaseConnectionListener {
content[0] = 0x7e;
byte end = 0x1;
DeviceProtocol protocol = new DeviceProtocol(stx, len, cmd, ack, content, end);
......@@ -69,5 +66,4 @@ public class ForwardConnectionListener extends BaseConnectionListener {
eventPublisher.publishEvent(deviceClientLicenseEvent);
}
}
}
......@@ -6,7 +6,6 @@ import lombok.Data;
@Data
public class SessionContext {
private String remoteIp;
private int remotePort;
private String appId;
......@@ -18,6 +17,4 @@ public class SessionContext {
private String offline;//下线时间
private String channelId;
private SocketChannel clientChannel;
}
......@@ -8,13 +8,12 @@ import lombok.extern.slf4j.Slf4j;
@Data
@Slf4j
public class BaseConnectionListener implements ChannelFutureListener {
public String appId;
public String host;
public int port;
public String appId;
public String host;
public int port;
@Override
public void operationComplete(ChannelFuture future) {
// TODO Auto-generated method stub
log.info("重写了operationComplete方法");
}
@Override
public void operationComplete(ChannelFuture future) {
log.info("重写了operationComplete方法");
}
}
......@@ -22,7 +22,7 @@ public class TcpServer {
//创建两个线程组 bossGroup、workerGroup
EventLoopGroup bossGroup = new NioEventLoopGroup(4);
EventLoopGroup workerGroup = new NioEventLoopGroup(4);
log.debug("Tcp服务,开始监听端口:{}", port);
log.info("Tcp服务,开始监听端口:{}", port);
//创建服务端的启动对象,设置参数
ServerBootstrap b = new ServerBootstrap();
//设置两个线程组boosGroup和workerGroup
......@@ -40,10 +40,9 @@ public class TcpServer {
f = b.bind(port).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
log.error("Tcp服务异常,端口:{}", port);
} finally {
log.debug("Tcp服务,停止退出");
log.info("Tcp服务,停止退出");
if (workerGroup != null) {
workerGroup.shutdownGracefully();
}
......
......@@ -8,7 +8,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Component
@Slf4j
......@@ -43,7 +47,7 @@ public class OperateManager {
return result;
}
public int getCount(){
public int getCount() {
return this.count;
}
......@@ -69,8 +73,8 @@ public class OperateManager {
this.putSamMonitorMap(serverIp, samMonitor);
}
// createProxyClient();
// test();
// createProxyClient();
// test();
}
......@@ -89,8 +93,8 @@ public class OperateManager {
private void test() {
String serverIp = "192.168.1.56";
int port = 18889;
// serverIp = "172.17.115.81";
// port = 777;
// serverIp = "172.17.115.81";
// port = 777;
this.startTcpClient(serverIp, port);
}
......
......@@ -300,4 +300,17 @@ public class CommonUtil {
}
}
public static String getLibFilePathByFileName(String fileName) {
String os = System.getProperty("os.name");
String serverParentDirectory = getServerParentDirectory();
if (os != null) {
if (os.toLowerCase(Locale.ENGLISH).startsWith("win")) {
return serverParentDirectory + File.separator + "license/file/libs" + File.separator + fileName + ".dll";
} else {
return serverParentDirectory + File.separator + "license/file/libs" + File.separator + fileName + ".so";
}
}
return "";
}
}
package iot.sixiang.license.controller;
import com.alibaba.fastjson2.JSON;
import iot.sixiang.license.object.data.AuthData;
import iot.sixiang.license.util.HmacUtil;
import iot.sixiang.license.util.sm4.SM4;
import iot.sixiang.license.util.sm4.SM4Context;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Random;
/**
* Created by M=54G
* Date 11/11/22 9:54 AM
* Description
*/
public class DeviceControllerTest {
@Test
void auth() {
String appId = "ebsh71dp5t1ck948l5";
String sn = "ERE54S619LNYMPKVN9";
String appKey = "110801";
//byte[] baseKeyBytes = "nAOq38p4bGQyF4FG".getBytes();
//System.out.println(baseKeyBytes.length);
byte[] allBytes = getAuthSendBytes(appId, sn, appKey);
System.out.println(bytes2Hex(allBytes));
}
@Test
void testSocket() {
String serverIp = "112.74.57.111";
int serverPort = 18889;
String appId = "ebsh71dp5t1ck948l5";
String sn = "ERE54S619LNYMPKVN9";
String appKey = "110801";
socket(serverIp, serverPort, appId, sn, appKey);
}
@Test
void yxSocket() {
String serverIp = "14.116.221.61";
int serverPort = 18889;
String appId = "mny3i9pgg0xxs520qf";
String sn = "IU23404BR1CQJOC63Q";
String appKey = "20221114";
socket(serverIp, serverPort, appId, sn, appKey);
}
@SneakyThrows
void socket(String serverIp, int serverPort, String appId, String sn, String appKey) {
Socket socket = new Socket(serverIp, serverPort);
socket.setKeepAlive(true);
System.out.println("connect success...");
// 事先组装好要发送的鉴权信息
byte[] authSendBytes = getAuthSendBytes(appId, sn, appKey);
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = socket.getInputStream();
// 鉴权
sendAndReceive(socket, outputStream, inputStream, "auth", authSendBytes);
Thread.sleep(1000);
// 鉴权后做动作
String request = "55AA340090000156F43D4D806827D1BB8F78C00D2B5488479CEB172C5D477C4D3023CE7B111621D4AD2C11ACAC4D876A3AC66A82F5F19000EF";
byte[] actionSendBytes = hex2Byte(request);
byte[] actionResultBytes = sendAndReceive(socket, outputStream, inputStream, "action", actionSendBytes);
//String result = "55AA1500A40035414E7DB5B3EDE72BC6BA44203F52EA0000005B";
//String result = "55aa1500a4008926834e684c4c6911b02304b3a0ce9c00000000";
//Assert.assertEquals(bytes2Hex(actionResultBytes), result);
inputStream.close();
outputStream.close();
socket.close();
}
@SneakyThrows
private byte[] sendAndReceive(Socket socket, OutputStream outputStream, InputStream inputStream, String tag, byte[] requestBytes) {
System.out.println(tag + " send:" + bytes2Hex(requestBytes));
outputStream.write(requestBytes);
outputStream.flush();
byte[] bytes = new byte[1024];
int count = inputStream.read(bytes);
while (count < 0) {
Thread.sleep(200);
count = inputStream.read(bytes);
}
byte[] resultBytes = new byte[count];
for (int i = 0; i < count; i++) {
resultBytes[i] = bytes[i];
}
System.out.println(tag + " receive:" + bytes2Hex(resultBytes));
return requestBytes;
}
private byte[] getAuthSendBytes(String appId, String sn, String appKey) {
byte[] stxBytes = {(byte) 0x55, (byte) 0xaa};
// 这部分生成内容
// 用于SM4
byte[] randomBytes = new byte[16];
Random random = new Random();
for (int i = 0; i < randomBytes.length; i++) {
randomBytes[i] = (byte) (random.nextInt());
}
byte[] sm4KeyBytes = new byte[16];
byte[] baseKeyBytes = "nAOq38p4bGQyF4FG".getBytes();
for (int i = 0; i < randomBytes.length; i++) {
sm4KeyBytes[i] = (byte) (randomBytes[i] ^ baseKeyBytes[i]);
}
String string = "app_id=" + appId + "&sn=" + sn;
String sign = HmacUtil.encrypt(string, appKey, HmacUtil.HMAC_SHA1);
// 组装
AuthData authData = new AuthData();
authData.setApp_id(appId);
authData.setSn(sn);
authData.setSign(sign);
byte[] dataBytes = encryptData_ECB(JSON.toJSONString(authData), sm4KeyBytes);
dataBytes = byteMerger(randomBytes, dataBytes);
int length = dataBytes.length + stxBytes.length;
byte[] lenBytes = {(byte) length, (byte) (length >> 8)};
// 这部分是命令
byte cmdByte = (byte) 0x01;
byte ackByte = (byte) 0x00;
// 结束符
byte endByte = (byte) 0x00;
// 加密最后字段
endByte = (byte) (endByte ^ cmdByte);
endByte = (byte) (endByte ^ ackByte);
for (int i = 0; i < length - 2; i++) {
endByte = (byte) (endByte ^ dataBytes[i]);
}
return byteMerger(stxBytes, lenBytes, new byte[]{cmdByte, ackByte}, dataBytes, new byte[]{endByte});
}
public byte[] encryptData_ECB(String string, byte[] keyBytes) {
try {
SM4Context ctx = new SM4Context();
ctx.mode = SM4.SM4_ENCRYPT;
SM4 sm4 = new SM4();
sm4.sm4_setkey_enc(ctx, keyBytes);
byte[] encrypted = sm4_crypt_ecb(sm4, ctx, string.getBytes("UTF-8"));
return encrypted;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public byte[] sm4_crypt_ecb(SM4 sm4, SM4Context ctx, byte[] input) throws Exception {
int length = input.length;
ByteArrayInputStream bins = new ByteArrayInputStream(input);
ByteArrayOutputStream bous = new ByteArrayOutputStream();
for (; length > 0; length -= 16) {
byte[] in = new byte[16];
byte[] out = new byte[16];
bins.read(in);
sm4.sm4_one_round(ctx.sk, in, out);
bous.write(out);
}
byte[] output = bous.toByteArray();
bins.close();
bous.close();
return output;
}
@Test
void authDevice() {
}
public static byte[] byteMerger(byte[]... byteList) {
int lengthByte = 0;
for (int i = 0; i < byteList.length; i++) {
lengthByte += byteList[i].length;
}
byte[] allByte = new byte[lengthByte];
int countLength = 0;
for (int i = 0; i < byteList.length; i++) {
byte[] b = byteList[i];
System.arraycopy(b, 0, allByte, countLength, b.length);
countLength += b.length;
}
return allByte;
}
public static String bytes2Hex(byte[] bytes) {
if (bytes == null) {
return null;
}
StringBuilder builder = new StringBuilder();
// 遍历byte[]数组,将每个byte数字转换成16进制字符,再拼接起来成字符串
for (int i = 0; i < bytes.length; i++) {
// 每个byte转换成16进制字符时,bytes[i] & 0xff如果高位是0,输出将会去掉,所以+0x100(在更高位加1),再截取后两位字符
builder.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
return builder.toString();
}
public static byte[] hex2Byte(String string) {
if (string == null || string.length() < 1) {
return null;
}
// 因为一个byte生成两个字符,长度对应1:2,所以byte[]数组长度是字符串长度一半
byte[] bytes = new byte[string.length() / 2];
// 遍历byte[]数组,遍历次数是字符串长度一半
for (int i = 0; i < string.length() / 2; i++) {
// 截取没两个字符的前一个,将其转为int数值
int high = Integer.parseInt(string.substring(i * 2, i * 2 + 1), 16);
// 截取没两个字符的后一个,将其转为int数值
int low = Integer.parseInt(string.substring(i * 2 + 1, i * 2 + 2), 16);
// 高位字符对应的int值*16+低位的int值,强转成byte数值即可
// 如dd,高位13*16+低位13=221(强转成byte二进制11011101,对应十进制-35)
bytes[i] = (byte) (high * 16 + low);
}
return bytes;
}
//public static void main(String[] args) {
// byte[] stxbyte = {(byte) 0x7E};
// byte[] typebyte = {(byte) 0x01};
// RespDevDataDto build = RespDevDataDto.builder().seqNo("0")
// .deviceSn("FSDF32FFZV").command("decodeconnectnorth")
// .timeStamp("1652233401604")
// .data(toStringHex("55AA34009000AB752BE54B0B05796E4C5E60060D99B79A37A534B4D081A6184C105FD7EABDBFE5ECE7EF08F933ED415CCD6DA82157059000FE")).build();
// String serverRespSign = DecodeHmacShaUtils.terminalReqSign(build);
// build.setSign(serverRespSign);
// byte[] resultbyte = JSONProvider.toJSONString(build).getBytes();
// Integer len = resultbyte.length + typebyte.length;
// String strlen = Integer.toString(len, 16);
// byte[] lenbyte = ByteHelper.hexStrToBytes(strlen, 2);
// byte[] databyte = ByteHelper.byteMerger(stxbyte, lenbyte, typebyte, resultbyte);
// System.out.println(byte2Hex(databyte));
// //7e0100017b22636f6d6d616e64223a226465636f6465636f6e6e6563746e6f727468222c2264617461223a2255efbfbd345c7530303030efbfbd5c7530303030efbfbd752befbfbd4b5c75303030425c7530303035796e4c5e605c75303030365c72efbfbdefbfbdefbfbd37efbfbd34efbfbdd081efbfbd5c75303031384c5c75303031305fefbfbdeabdbfefbfbdefbfbdefbfbdefbfbd5c62efbfbd33efbfbd415c5cefbfbd6defbfbd21575c7530303035efbfbd5c7530303030efbfbd222c22646576696365536e223a2246534446333246465a56222c227365714e6f223a2230222c227369676e223a2244344245393930333539343346454331323345354132414534443145353231304236413541463635222c2274696d655374616d70223a2231363532323333343031363034227d
//}
// 转化十六进制编码为字符串
//public static String toStringHex(String s) {
// byte[] baKeyword = new byte[s.length() / 2];
// for (int i = 0; i < baKeyword.length; i++) {
// try {
// baKeyword[i] = (byte) Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16);
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// try {
// s = new String(baKeyword, "utf-8");//UTF-16le:Not
// } catch (Exception e1) {
// e1.printStackTrace();
// }
// return s;
//}
//public static String bytes2hex(byte[] bytes) {
// StringBuilder sb = new StringBuilder();
// String tmp;
// sb.append("[");
// for (byte b : bytes) {
// // 将每个字节与0xFF进行与运算,然后转化为10进制,然后借助于Integer再转化为16进制
// //tmp = Integer.toHexString(b);
// tmp = Integer.toString((b & 0xff) + 0x100, 16).substring(1);
// if (tmp.length() == 1) {
// tmp = "0" + tmp;//只有一位的前面补个0
// }
// sb.append(tmp).append(",");//每个字节用空格断开
// }
// sb.delete(sb.length() - 1, sb.length());//删除最后一个字节后面对于的空格
// sb.append("]");
// return sb.toString();
//}
}
\ No newline at end of file
package iot.sixiang.license.object.data;
import lombok.Data;
/**
* Created by M=54G
* Date 11/11/22 10:08 AM
* Description
*/
@Data
public class AuthData {
private String app_id;
private String sn;
private String sign;
}
\ No newline at end of file
package iot.sixiang.license.util;
import org.apache.http.util.TextUtils;
public class ByteHelper {
/**
* src:源数组
* srcPos:源数组要复制的起始位置
* dest:目的数组
* destPos:目的数组放置的起始位置
* length:要复制的长度
*
* @param src
* @param begin
* @param count
* @return
*/
public static byte[] subBytes(byte[] src, int begin, int count) {
byte[] bs = new byte[count];
System.arraycopy(src, begin, bs, 0, count);
return bs;
}
/**
* 字节码转化十六进制
*
* @author xzb
*/
public static String fromBytesToHex(byte[] resultBytes) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < resultBytes.length; i++) {
if (Integer.toHexString(0xFF & resultBytes[i]).length() == 1) {
builder.append("0").append(Integer.toHexString(0xFF & resultBytes[i]));
} else {
builder.append(Integer.toHexString(0xFF & resultBytes[i]));
}
}
return builder.toString();
}
/**
* byte[] 转为16进制String
*/
public static String Bytes2HexString(byte[] b) {
String ret = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase();
}
return ret;
}
/**
* 转化十六进制编码为字符串
*
* @param s
* @return
*/
public static String toStringHex(String s) {
byte[] baKeyword = new byte[s.length() / 2];
for (int i = 0; i < baKeyword.length; i++) {
try {
baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
} catch (Exception e) {
e.printStackTrace();
}
}
try {
s = new String(baKeyword, "utf-8");//UTF-16le:Not
} catch (Exception e1) {
e1.printStackTrace();
}
return s;
}
/***
* 合并数组
* @param byteList
* @return
*/
public static byte[] byteMerger(byte[]... byteList) {
int lengthByte = 0;
for (int i = 0; i < byteList.length; i++) {
lengthByte += byteList[i].length;
}
byte[] allByte = new byte[lengthByte];
int countLength = 0;
for (int i = 0; i < byteList.length; i++) {
byte[] b = byteList[i];
System.arraycopy(b, 0, allByte, countLength, b.length);
countLength += b.length;
}
return allByte;
}
/**
* 字符串转16进制
*
* @param string
* @return
*/
public static String stringToHexString(String string) {
char[] c = new char[string.length()];
c = string.toCharArray();
String hesStr = "";
for (int i = 0; i < c.length; i++) {
hesStr = hesStr + Integer.toHexString(c[i]);
}
return hesStr;
}
/**
* 字符串转化成为16进制字符串
*
* @param s
* @return
*/
public static String strTo16(String s) {
String str = "";
for (int i = 0; i < s.length(); i++) {
int ch = (int) s.charAt(i);
String s4 = Integer.toHexString(ch);
str = str + s4;
}
return str;
}
/**
* hex字符串转byte数组
*
* @param inHex 待转换的Hex字符串
* @return 转换后的byte数组结果
*/
public static byte[] hexToByteArray(String inHex, int len) {
int hexlen = inHex.length();
byte[] result;
if (hexlen % 2 == 1) {
//奇数
hexlen++;
result = new byte[(hexlen / 2)];
inHex = "0" + inHex;
} else {
//偶数
result = new byte[(hexlen / 2)];
}
int j = 0;
for (int i = 0; i < hexlen; i += 2) {
result[j] = hexToByte(inHex.substring(i, i + 2));
j++;
}
return result;
}
public static long bytes2long(byte[] bs) throws Exception {
int bytes = bs.length;
if (bytes > 1) {
if ((bytes % 2) != 0 || bytes > 8) {
throw new Exception("not support");
}
}
switch (bytes) {
case 0:
return 0;
case 1:
return (long) ((bs[0] & 0xff));
case 2:
return (long) ((bs[0] & 0xff) << 8 | (bs[1] & 0xff));
case 4:
return (long) ((bs[0] & 0xffL) << 24 | (bs[1] & 0xffL) << 16 | (bs[2] & 0xffL) << 8 | (bs[3] & 0xffL));
case 8:
return (long) ((bs[0] & 0xffL) << 56 | (bs[1] & 0xffL) << 48 | (bs[2] & 0xffL) << 40 | (bs[3] & 0xffL) << 32 |
(bs[4] & 0xffL) << 24 | (bs[5] & 0xffL) << 16 | (bs[6] & 0xffL) << 8 | (bs[7] & 0xffL));
default:
throw new Exception("not support");
}
//return 0;
}
public static long bytes2long(byte[] bs, int offset) {
return (long) ((bs[7 + offset] & 0xffL) << 56 | (bs[6 + offset] & 0xffL) << 48 | (bs[5 + offset] & 0xffL) << 40 | (bs[4 + offset] & 0xffL) << 32 |
(bs[3 + offset] & 0xffL) << 24 | (bs[2 + offset] & 0xffL) << 16 | (bs[1 + offset] & 0xffL) << 8 | (bs[0 + offset] & 0xffL));
}
public static byte[] hexStrToBytes(String hexStr, int len) {
if (TextUtils.isEmpty(hexStr) || hexStr.length() == 0) {
return null;
}
if (hexStr.length() % 2 == 1) {
hexStr = "0" + hexStr;
}
byte[] result = new byte[len];
char[] chars = hexStr.toCharArray();
int hexlen = hexStr.length();
if (hexlen > len)
hexlen = len;
for (int i = 0; i < hexlen - 1; i++) {
result[i] = (byte) (charToByte(chars[i]) << 4 | charToByte(chars[i + 1]));
}
return result;
}
private static byte charToByte(char c) {
String chars = "0123456789ABCDEF";
byte b = (byte) chars.indexOf(c);
return b;
}
/**
* Hex字符串转byte
*
* @param inHex 待转换的Hex字符串
* @return 转换后的byte
*/
public static byte hexToByte(String inHex) {
return (byte) Integer.parseInt(inHex, 16);
}
}
package iot.sixiang.license.util;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
/**
* Title: HmacShaUtils
* Description:
*
* @author YFW
* @version V1.0
* @date 2022-03-14
*/
public class HmacShaUtils {
private static final String HMAC_ALGORITHM = "hmacsha1";
private static final String secretKey = "90d2fca50ea8ed5472c5776c9fc53699";
/**
* 使用HMAC_ALGORITHM加密。
*
* @param content,明文。
* @param secret,密钥。
* @return 密文。
*/
public static String encrypt(String content, String secret) {
if (PubUtils.isNull(secret)) secret = secretKey;
try {
byte[] text = content.getBytes(StandardCharsets.UTF_8);
byte[] key = secret.getBytes(StandardCharsets.UTF_8);
SecretKeySpec secretKey = new SecretKeySpec(key, HMAC_ALGORITHM);
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
return byte2hex(mac.doFinal(text));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 二进制转十六进制字符串。
*
* @param b,二进制数组。
* @return 十六进制字符串。
*/
public static String byte2hex(byte[] b) {
StringBuffer sb = new StringBuffer();
for (int n = 0; b != null && n < b.length; n++) {
String stmp = Integer.toHexString(b[n] & 0XFF);
if (stmp.length() == 1) {
sb.append('0');
}
sb.append(stmp);
}
return sb.toString().toUpperCase();
}
}
package iot.sixiang.license.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.Collection;
import java.util.UUID;
/**
* Title: PubUtils
* Description: 公共实体类
*
* @author YFW
* @version V1.0
* @date 2020-07-28
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PubUtils {
/**
* The constant STRING_NULL.
*/
private final static String STRING_NULL = "-";
/**
* 匹配手机号码, 支持+86和86开头
*/
private static final String REGX_MOBILENUM = "^((\\+86)|(86))?(13|15|17|18)\\d{9}$";
/**
* 匹配手机号码, 支持+86和86开头
*/
private static final String REGX_MOBILENUM_NEW = "^((\\+86)|(86))?(1)\\d{10}$";
/**
* 匹配邮箱帐号
*/
private static final String REGX_EMAIL = "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
/**
* 匹配设备标签,支持字母、数字、汉字和英文逗号,但不能以英文逗号结尾
*/
private static final String REGX_TAGS = "[a-zA-Z0-9,\\u4E00-\\u9FA5]*[^,]";
/**
* 匹配手机号码(先支持13, 15, 17, 18开头的手机号码).
*
* @param inputStr the input str
*
* @return the boolean
*/
public static Boolean isMobileNumber(String inputStr) {
return !PubUtils.isNull(inputStr) && inputStr.matches(REGX_MOBILENUM);
}
public static Boolean isMobileNumberNew(String inputStr) {
return !PubUtils.isNull(inputStr) && inputStr.matches(REGX_MOBILENUM_NEW);
}
/**
* 判断一个或多个对象是否为空
*
* @param values 可变参数, 要判断的一个或多个对象
*
* @return 只有要判断的一个对象都为空则返回true, 否则返回false boolean
*/
public static boolean isNull(Object... values) {
if (!PubUtils.isNotNullAndNotEmpty(values)) {
return true;
}
for (Object value : values) {
boolean flag;
if (value instanceof Object[]) {
flag = !isNotNullAndNotEmpty((Object[]) value);
} else if (value instanceof Collection<?>) {
flag = !isNotNullAndNotEmpty((Collection<?>) value);
} else if (value instanceof String) {
flag = isOEmptyOrNull(value);
} else {
flag = (null == value);
}
if (flag) {
return true;
}
}
return false;
}
/**
* Is o empty or null boolean.
*
* @param o the o
*
* @return boolean boolean
*/
private static boolean isOEmptyOrNull(Object o) {
return o == null || isSEmptyOrNull(o.toString());
}
/**
* Is s empty or null boolean.
*
* @param s the s
*
* @return boolean boolean
*/
private static boolean isSEmptyOrNull(String s) {
return trimAndNullAsEmpty(s).length() <= 0;
}
/**
* Trim and null as empty string.
*
* @param s the s
*
* @return java.lang.String string
*/
private static String trimAndNullAsEmpty(String s) {
if (s != null && !s.trim().equals(STRING_NULL)) {
return s.trim();
} else {
return "";
}
// return s == null ? "" : s.trim();
}
/**
* 判断对象数组是否为空并且数量大于0
*
* @param value the value
*
* @return boolean
*/
private static Boolean isNotNullAndNotEmpty(Object[] value) {
boolean bl = false;
if (null != value && 0 < value.length) {
bl = true;
}
return bl;
}
/**
* 判断对象集合(List,Set)是否为空并且数量大于0
*
* @param value the value
*
* @return boolean
*/
private static Boolean isNotNullAndNotEmpty(Collection<?> value) {
boolean bl = false;
if (null != value && !value.isEmpty()) {
bl = true;
}
return bl;
}
/**
* Is email boolean.
*
* @param str the str
*
* @return the boolean
*/
public static boolean isEmail(String str) {
boolean bl = true;
if (isSEmptyOrNull(str) || !str.matches(REGX_EMAIL)) {
bl = false;
}
return bl;
}
/**
* Is tags boolean.
*
* @param str the str
*
* @return the boolean
*/
public static boolean isTags(String str) {
boolean bl = true;
if (isSEmptyOrNull(str) || !str.matches(REGX_TAGS)) {
bl = false;
}
return bl;
}
/**
* Uuid string.
*
* @return the string
*/
public synchronized static String uuid() {
return UUID.randomUUID().toString().replace("-", "");
}
}
package iot.sixiang.license.util.sm4;
import java.math.BigInteger;
public class ByteUtil {
/**
* 整形转换成网络传输的字节流(字节数组)型数据
*
* @param num 一个整型数据
* @return 4个字节的自己数组
*/
public static byte[] intToBytes(int num) {
byte[] bytes = new byte[4];
bytes[0] = (byte) (0xff & (num >> 0));
bytes[1] = (byte) (0xff & (num >> 8));
bytes[2] = (byte) (0xff & (num >> 16));
bytes[3] = (byte) (0xff & (num >> 24));
return bytes;
}
/**
* 四个字节的字节数据转换成一个整形数据
*
* @param bytes 4个字节的字节数组
* @return 一个整型数据
*/
public static int byteToInt(byte[] bytes) {
int num = 0;
int temp;
temp = (0x000000ff & (bytes[0])) << 0;
num = num | temp;
temp = (0x000000ff & (bytes[1])) << 8;
num = num | temp;
temp = (0x000000ff & (bytes[2])) << 16;
num = num | temp;
temp = (0x000000ff & (bytes[3])) << 24;
num = num | temp;
return num;
}
/**
* 长整形转换成网络传输的字节流(字节数组)型数据
*
* @param num 一个长整型数据
* @return 4个字节的自己数组
*/
public static byte[] longToBytes(long num) {
byte[] bytes = new byte[8];
for (int i = 0; i < 8; i++) {
bytes[i] = (byte) (0xff & (num >> (i * 8)));
}
return bytes;
}
/**
* 大数字转换字节流(字节数组)型数据
*
* @param n
* @return
*/
public static byte[] byteConvert32Bytes(BigInteger n) {
byte tmpd[] = (byte[]) null;
if (n == null) {
return null;
}
if (n.toByteArray().length == 33) {
tmpd = new byte[32];
System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);
} else if (n.toByteArray().length == 32) {
tmpd = n.toByteArray();
} else {
tmpd = new byte[32];
for (int i = 0; i < 32 - n.toByteArray().length; i++) {
tmpd[i] = 0;
}
System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);
}
return tmpd;
}
/**
* 换字节流(字节数组)型数据转大数字
*
* @param b
* @return
*/
public static BigInteger byteConvertInteger(byte[] b) {
if (b[0] < 0) {
byte[] temp = new byte[b.length + 1];
temp[0] = 0;
System.arraycopy(b, 0, temp, 1, b.length);
return new BigInteger(temp);
}
return new BigInteger(b);
}
/**
* 根据字节数组获得值(十六进制数字)
*
* @param bytes
* @return
*/
public static String getHexString(byte[] bytes) {
return getHexString(bytes, true);
}
/**
* 根据字节数组获得值(十六进制数字)
*
* @param bytes
* @param upperCase
* @return
*/
public static String getHexString(byte[] bytes, boolean upperCase) {
String ret = "";
for (int i = 0; i < bytes.length; i++) {
ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);
}
return upperCase ? ret.toUpperCase() : ret;
}
/**
* 打印十六进制字符串
*
* @param bytes
*/
public static void printHexString(byte[] bytes) {
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
System.out.print("0x" + hex.toUpperCase() + ",");
}
System.out.println("");
}
/**
* Convert hex string to byte[]
*
* @param hexString the hex string
* @return byte[]
*/
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
/**
* Convert char to byte
*
* @param c char
* @return byte
*/
public static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
/**
* 用于建立十六进制字符的输出的小写字符数组
*/
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* 用于建立十六进制字符的输出的大写字符数组
*/
private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @return 十六进制char[]
*/
public static char[] encodeHex(byte[] data) {
return encodeHex(data, true);
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
* @return 十六进制char[]
*/
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @param toDigits 用于控制输出的char[]
* @return 十六进制char[]
*/
protected static char[] encodeHex(byte[] data, char[] toDigits) {
int l = data.length;
char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
return out;
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @return 十六进制String
*/
public static String encodeHexString(byte[] data) {
return encodeHexString(data, true);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
* @return 十六进制String
*/
public static String encodeHexString(byte[] data, boolean toLowerCase) {
return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @param toDigits 用于控制输出的char[]
* @return 十六进制String
*/
protected static String encodeHexString(byte[] data, char[] toDigits) {
return new String(encodeHex(data, toDigits));
}
/**
* 将十六进制字符数组转换为字节数组
*
* @param data 十六进制char[]
* @return byte[]
* @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
*/
public static byte[] decodeHex(char[] data) {
int len = data.length;
if ((len & 0x01) != 0) {
throw new RuntimeException("Odd number of characters.");
}
byte[] out = new byte[len >> 1];
// two characters form the hex value.
for (int i = 0, j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f = f | toDigit(data[j], j);
j++;
out[i] = (byte) (f & 0xFF);
}
return out;
}
/**
* 将十六进制字符转换成一个整数
*
* @param ch 十六进制char
* @param index 十六进制字符在字符数组中的位置
* @return 一个整数
* @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
*/
protected static int toDigit(char ch, int index) {
int digit = Character.digit(ch, 16);
if (digit == -1) {
throw new RuntimeException("Illegal hexadecimal character " + ch
+ " at index " + index);
}
return digit;
}
/**
* 数字字符串转ASCII码字符串
*
* @param String 字符串
* @return ASCII字符串
*/
public static String StringToAsciiString(String content) {
String result = "";
int max = content.length();
for (int i = 0; i < max; i++) {
char c = content.charAt(i);
String b = Integer.toHexString(c);
result = result + b;
}
return result;
}
/**
* 十六进制转字符串
*
* @param hexString 十六进制字符串
* @param encodeType 编码类型4:Unicode,2:普通编码
* @return 字符串
*/
public static String hexStringToString(String hexString, int encodeType) {
String result = "";
int max = hexString.length() / encodeType;
for (int i = 0; i < max; i++) {
char c = (char) hexStringToAlgorism(hexString
.substring(i * encodeType, (i + 1) * encodeType));
result += c;
}
return result;
}
/**
* 十六进制字符串装十进制
*
* @param hex 十六进制字符串
* @return 十进制数值
*/
public static int hexStringToAlgorism(String hex) {
hex = hex.toUpperCase();
int max = hex.length();
int result = 0;
for (int i = max; i > 0; i--) {
char c = hex.charAt(i - 1);
int algorism = 0;
if (c >= '0' && c <= '9') {
algorism = c - '0';
} else {
algorism = c - 55;
}
result += Math.pow(16, max - i) * algorism;
}
return result;
}
/**
* 十六转二进制
*
* @param hex 十六进制字符串
* @return 二进制字符串
*/
public static String hexStringToBinary(String hex) {
hex = hex.toUpperCase();
String result = "";
int max = hex.length();
for (int i = 0; i < max; i++) {
char c = hex.charAt(i);
switch (c) {
case '0':
result += "0000";
break;
case '1':
result += "0001";
break;
case '2':
result += "0010";
break;
case '3':
result += "0011";
break;
case '4':
result += "0100";
break;
case '5':
result += "0101";
break;
case '6':
result += "0110";
break;
case '7':
result += "0111";
break;
case '8':
result += "1000";
break;
case '9':
result += "1001";
break;
case 'A':
result += "1010";
break;
case 'B':
result += "1011";
break;
case 'C':
result += "1100";
break;
case 'D':
result += "1101";
break;
case 'E':
result += "1110";
break;
case 'F':
result += "1111";
break;
}
}
return result;
}
/**
* ASCII码字符串转数字字符串
*
* @param String ASCII字符串
* @return 字符串
*/
public static String AsciiStringToString(String content) {
String result = "";
int length = content.length() / 2;
for (int i = 0; i < length; i++) {
String c = content.substring(i * 2, i * 2 + 2);
int a = hexStringToAlgorism(c);
char b = (char) a;
String d = String.valueOf(b);
result += d;
}
return result;
}
/**
* 将十进制转换为指定长度的十六进制字符串
*
* @param algorism int 十进制数字
* @param maxLength int 转换后的十六进制字符串长度
* @return String 转换后的十六进制字符串
*/
public static String algorismToHexString(int algorism, int maxLength) {
String result = "";
result = Integer.toHexString(algorism);
if (result.length() % 2 == 1) {
result = "0" + result;
}
return patchHexString(result.toUpperCase(), maxLength);
}
/**
* 字节数组转为普通字符串(ASCII对应的字符)
*
* @param bytearray byte[]
* @return String
*/
public static String byteToString(byte[] bytearray) {
String result = "";
char temp;
int length = bytearray.length;
for (int i = 0; i < length; i++) {
temp = (char) bytearray[i];
result += temp;
}
return result;
}
/**
* 二进制字符串转十进制
*
* @param binary 二进制字符串
* @return 十进制数值
*/
public static int binaryToAlgorism(String binary) {
int max = binary.length();
int result = 0;
for (int i = max; i > 0; i--) {
char c = binary.charAt(i - 1);
int algorism = c - '0';
result += Math.pow(2, max - i) * algorism;
}
return result;
}
/**
* 十进制转换为十六进制字符串
*
* @param algorism int 十进制的数字
* @return String 对应的十六进制字符串
*/
public static String algorismToHEXString(int algorism) {
String result = "";
result = Integer.toHexString(algorism);
if (result.length() % 2 == 1) {
result = "0" + result;
}
result = result.toUpperCase();
return result;
}
/**
* HEX字符串前补0,主要用于长度位数不足。
*
* @param str String 需要补充长度的十六进制字符串
* @param maxLength int 补充后十六进制字符串的长度
* @return 补充结果
*/
static public String patchHexString(String str, int maxLength) {
String temp = "";
for (int i = 0; i < maxLength - str.length(); i++) {
temp = "0" + temp;
}
str = (temp + str).substring(0, maxLength);
return str;
}
/**
* 将一个字符串转换为int
*
* @param s String 要转换的字符串
* @param defaultInt int 如果出现异常,默认返回的数字
* @param radix int 要转换的字符串是什么进制的,如16 8 10.
* @return int 转换后的数字
*/
public static int parseToInt(String s, int defaultInt, int radix) {
int i = 0;
try {
i = Integer.parseInt(s, radix);
} catch (NumberFormatException ex) {
i = defaultInt;
}
return i;
}
/**
* 将一个十进制形式的数字字符串转换为int
*
* @param s String 要转换的字符串
* @param defaultInt int 如果出现异常,默认返回的数字
* @return int 转换后的数字
*/
public static int parseToInt(String s, int defaultInt) {
int i = 0;
try {
i = Integer.parseInt(s);
} catch (NumberFormatException ex) {
i = defaultInt;
}
return i;
}
/**
* 十六进制串转化为byte数组
*
* @return the array of byte
*/
public static byte[] hexToByte(String hex)
throws IllegalArgumentException {
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException();
}
char[] arr = hex.toCharArray();
byte[] b = new byte[hex.length() / 2];
for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
String swap = "" + arr[i++] + arr[i];
int byteint = Integer.parseInt(swap, 16) & 0xFF;
b[j] = new Integer(byteint).byteValue();
}
return b;
}
/**
* 字节数组转换为十六进制字符串
*
* @param b byte[] 需要转换的字节数组
* @return String 十六进制字符串
*/
public static String byteToHex(byte b[]) {
if (b == null) {
throw new IllegalArgumentException(
"Argument b ( byte array ) is null! ");
}
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = Integer.toHexString(b[n] & 0xff);
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs.toUpperCase();
}
public static byte[] subByte(byte[] input, int startIndex, int length) {
byte[] bt = new byte[length];
for (int i = 0; i < length; i++) {
bt[i] = input[i + startIndex];
}
return bt;
}
}
package iot.sixiang.license.util.sm4;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class SM4 {
public static final int SM4_ENCRYPT = 1;
public static final int SM4_DECRYPT = 0;
private long GET_ULONG_BE(byte[] b, int i) {
long n = (long) (b[i] & 0xff) << 24 | (long) ((b[i + 1] & 0xff) << 16) | (long) ((b[i + 2] & 0xff) << 8) | (long) (b[i + 3] & 0xff) & 0xffffffffL;
return n;
}
private void PUT_ULONG_BE(long n, byte[] b, int i) {
b[i] = (byte) (int) (0xFF & n >> 24);
b[i + 1] = (byte) (int) (0xFF & n >> 16);
b[i + 2] = (byte) (int) (0xFF & n >> 8);
b[i + 3] = (byte) (int) (0xFF & n);
}
private long SHL(long x, int n) {
return (x & 0xFFFFFFFF) << n;
}
private long ROTL(long x, int n) {
return SHL(x, n) | x >> (32 - n);
}
private void SWAP(long[] sk, int i) {
long t = sk[i];
sk[i] = sk[(31 - i)];
sk[(31 - i)] = t;
}
public static final byte[] SboxTable = {(byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe,
(byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6,
0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
(byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,
(byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,
(byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91,
(byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
(byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
(byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8,
(byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa,
0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7,
(byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83,
0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8,
0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda,
(byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
(byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
(byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87,
(byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27,
0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4,
(byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a,
(byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3,
(byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15,
(byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,
(byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32,
0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d,
(byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca,
0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
(byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,
(byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb,
(byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41,
0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,
(byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d,
0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4,
(byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,
(byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09,
(byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0,
0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,
(byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48};
public static final int[] FK = {0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc};
public static final int[] CK = {0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279};
private byte sm4Sbox(byte inch) {
int i = inch & 0xFF;
byte retVal = SboxTable[i];
return retVal;
}
private long sm4Lt(long ka) {
long bb = 0L;
long c = 0L;
byte[] a = new byte[4];
byte[] b = new byte[4];
PUT_ULONG_BE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = GET_ULONG_BE(b, 0);
c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
return c;
}
private long sm4F(long x0, long x1, long x2, long x3, long rk) {
return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
}
private long sm4CalciRK(long ka) {
long bb = 0L;
long rk = 0L;
byte[] a = new byte[4];
byte[] b = new byte[4];
PUT_ULONG_BE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = GET_ULONG_BE(b, 0);
rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
return rk;
}
private void sm4_setkey(long[] SK, byte[] key) {
long[] MK = new long[4];
long[] k = new long[36];
int i = 0;
MK[0] = GET_ULONG_BE(key, 0);
MK[1] = GET_ULONG_BE(key, 4);
MK[2] = GET_ULONG_BE(key, 8);
MK[3] = GET_ULONG_BE(key, 12);
k[0] = MK[0] ^ (long) FK[0];
k[1] = MK[1] ^ (long) FK[1];
k[2] = MK[2] ^ (long) FK[2];
k[3] = MK[3] ^ (long) FK[3];
for (; i < 32; i++) {
k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long) CK[i]));
SK[i] = k[(i + 4)];
}
}
public void sm4_one_round(long[] sk, byte[] input, byte[] output) {
int i = 0;
long[] ulbuf = new long[36];
ulbuf[0] = GET_ULONG_BE(input, 0);
ulbuf[1] = GET_ULONG_BE(input, 4);
ulbuf[2] = GET_ULONG_BE(input, 8);
ulbuf[3] = GET_ULONG_BE(input, 12);
while (i < 32) {
ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
i++;
}
PUT_ULONG_BE(ulbuf[35], output, 0);
PUT_ULONG_BE(ulbuf[34], output, 4);
PUT_ULONG_BE(ulbuf[33], output, 8);
PUT_ULONG_BE(ulbuf[32], output, 12);
}
private byte[] padding(byte[] input, int mode) {
if (input == null) {
return null;
}
byte[] ret = (byte[]) null;
if (mode == SM4_ENCRYPT) {
int p = 16 - input.length % 16;
ret = new byte[input.length + p];
System.arraycopy(input, 0, ret, 0, input.length);
for (int i = 0; i < p; i++) {
ret[input.length + i] = (byte) p;
}
} else {
int p = input[input.length - 1];
ret = new byte[input.length - p];
System.arraycopy(input, 0, ret, 0, input.length - p);
}
return ret;
}
public void sm4_setkey_enc(SM4Context ctx, byte[] key) throws Exception {
if (ctx == null) {
throw new Exception("ctx is null!");
}
if (key == null || key.length != 16) {
throw new Exception("key error!");
}
ctx.mode = SM4_ENCRYPT;
sm4_setkey(ctx.sk, key);
}
public void sm4_setkey_dec(SM4Context ctx, byte[] key) throws Exception {
if (ctx == null) {
throw new Exception("ctx is null!");
}
if (key == null || key.length != 16) {
throw new Exception("key error!");
}
int i = 0;
ctx.mode = SM4_DECRYPT;
sm4_setkey(ctx.sk, key);
for (i = 0; i < 16; i++) {
SWAP(ctx.sk, i);
}
}
public byte[] sm4_crypt_ecb(SM4Context ctx, byte[] input) throws Exception {
if (input == null) {
throw new Exception("input is null!");
}
if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT)) {
input = padding(input, SM4_ENCRYPT);
}
int length = input.length;
ByteArrayInputStream bins = new ByteArrayInputStream(input);
ByteArrayOutputStream bous = new ByteArrayOutputStream();
for (; length > 0; length -= 16) {
byte[] in = new byte[16];
byte[] out = new byte[16];
bins.read(in);
sm4_one_round(ctx.sk, in, out);
bous.write(out);
}
byte[] output = bous.toByteArray();
if (ctx.isPadding && ctx.mode == SM4_DECRYPT) {
output = padding(output, SM4_DECRYPT);
}
bins.close();
bous.close();
return output;
}
public byte[] sm4_crypt_cbc(SM4Context ctx, byte[] iv, byte[] input) throws Exception {
if (iv == null || iv.length != 16) {
throw new Exception("iv error!");
}
if (input == null) {
throw new Exception("input is null!");
}
if (ctx.isPadding && ctx.mode == SM4_ENCRYPT) {
input = padding(input, SM4_ENCRYPT);
}
int i = 0;
int length = input.length;
ByteArrayInputStream bins = new ByteArrayInputStream(input);
ByteArrayOutputStream bous = new ByteArrayOutputStream();
if (ctx.mode == SM4_ENCRYPT) {
for (; length > 0; length -= 16) {
byte[] in = new byte[16];
byte[] out = new byte[16];
byte[] out1 = new byte[16];
bins.read(in);
for (i = 0; i < 16; i++) {
out[i] = ((byte) (in[i] ^ iv[i]));
}
sm4_one_round(ctx.sk, out, out1);
System.arraycopy(out1, 0, iv, 0, 16);
bous.write(out1);
}
} else {
byte[] temp = new byte[16];
for (; length > 0; length -= 16) {
byte[] in = new byte[16];
byte[] out = new byte[16];
byte[] out1 = new byte[16];
bins.read(in);
System.arraycopy(in, 0, temp, 0, 16);
sm4_one_round(ctx.sk, in, out);
for (i = 0; i < 16; i++) {
out1[i] = ((byte) (out[i] ^ iv[i]));
}
System.arraycopy(temp, 0, iv, 0, 16);
bous.write(out1);
}
}
byte[] output = bous.toByteArray();
if (ctx.isPadding && ctx.mode == SM4_DECRYPT) {
output = padding(output, SM4_DECRYPT);
}
bins.close();
bous.close();
return output;
}
}
package iot.sixiang.license.util.sm4;
public class SM4Context {
public int mode;
public long[] sk;
public boolean isPadding;
public SM4Context() {
this.mode = 1;
this.isPadding = true;
this.sk = new long[32];
}
}
package iot.sixiang.license.util.sm4;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SM4Utils {
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public boolean isHexString() {
return hexString;
}
public void setHexString(boolean hexString) {
this.hexString = hexString;
}
private String secretKey = "";
public String getIv() {
return iv;
}
public void setIv(String iv) {
this.iv = iv;
}
private String iv = "";
private boolean hexString = false;
public SM4Utils() {
}
public String encryptData_ECB(String plainText) {
try {
SM4Context ctx = new SM4Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_ENCRYPT;
byte[] keyBytes;
if (hexString) {
keyBytes = ByteUtil.hexStringToBytes(secretKey);
} else {
keyBytes = secretKey.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_enc(ctx, keyBytes);
byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainText.getBytes("UTF-8"));
String cipherText = Base64.getEncoder().encodeToString(encrypted);
if (cipherText != null && cipherText.trim().length() > 0) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(cipherText);
cipherText = m.replaceAll("");
}
return cipherText;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String decryptData_ECB(String cipherText) {
try {
SM4Context ctx = new SM4Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_DECRYPT;
byte[] keyBytes;
if (hexString) {
keyBytes = ByteUtil.hexStringToBytes(secretKey);
} else {
keyBytes = secretKey.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_dec(ctx, keyBytes);
byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Base64.getDecoder().decode(cipherText));
return new String(decrypted, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String encryptData_CBC(String plainText) {
try {
SM4Context ctx = new SM4Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_ENCRYPT;
byte[] keyBytes;
byte[] ivBytes;
if (hexString) {
keyBytes = ByteUtil.hexStringToBytes(secretKey);
ivBytes = ByteUtil.hexStringToBytes(iv);
} else {
keyBytes = secretKey.getBytes();
ivBytes = iv.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_enc(ctx, keyBytes);
byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes("UTF-8"));
String cipherText = Base64.getEncoder().encodeToString(encrypted);
if (cipherText != null && cipherText.trim().length() > 0) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(cipherText);
cipherText = m.replaceAll("");
}
return cipherText;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String decryptData_CBC(String cipherText) {
try {
SM4Context ctx = new SM4Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_DECRYPT;
byte[] keyBytes;
byte[] ivBytes;
if (hexString) {
keyBytes = ByteUtil.hexStringToBytes(secretKey);
ivBytes = ByteUtil.hexStringToBytes(iv);
} else {
keyBytes = secretKey.getBytes();
ivBytes = iv.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_dec(ctx, keyBytes);
byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Base64.getDecoder().decode(cipherText));
return new String(decrypted, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment