添加设备激活相关模块,设计 Bean 的属性。
This commit is contained in:
parent
e14ee17d2c
commit
a89fd0c116
68
device-activation-platform/Readme.md
Normal file
68
device-activation-platform/Readme.md
Normal file
@ -0,0 +1,68 @@
|
||||
激活登录请求参数 req {
|
||||
params {
|
||||
使用者ID
|
||||
初始密码
|
||||
}
|
||||
}
|
||||
|
||||
激活登录响应参数 res {
|
||||
status : 'ok' 成功; 'error' 错误
|
||||
msg: "提示消息"
|
||||
code: "状态码"
|
||||
}
|
||||
|
||||
|
||||
激活申请请求参数 req {
|
||||
params {
|
||||
设备的序列号
|
||||
激活原因
|
||||
}
|
||||
}
|
||||
|
||||
激活申请响应参数 res {
|
||||
身份凭证
|
||||
设备激活码
|
||||
}
|
||||
|
||||
|
||||
设备激活请求参数 req {
|
||||
params {
|
||||
使用者ID
|
||||
身份凭证
|
||||
设备激活码
|
||||
设备序列号
|
||||
设备指纹
|
||||
当前时间戳
|
||||
随机数
|
||||
}
|
||||
hash: params 对象所有属性字符串按顺序累计计算 SM3 摘要值
|
||||
}
|
||||
|
||||
设备激活响应参数 res {
|
||||
status : 'ok' 成功; 'error' 错误
|
||||
msg: "提示消息"
|
||||
code: "状态码"
|
||||
data: {
|
||||
hash: 入参的 hash
|
||||
设备激活公钥: 公钥格式
|
||||
设备激活结果: SM2 算法对 hash 值的签名, pkcs1 格式。
|
||||
}
|
||||
}
|
||||
|
||||
设备指纹信息 {
|
||||
主板序列号
|
||||
设备序列号
|
||||
CPU型号
|
||||
CPU序列号
|
||||
内存大小
|
||||
首块网卡MAC地址
|
||||
硬盘序列号
|
||||
起始日期
|
||||
终止日期
|
||||
}
|
||||
|
||||
设备指纹是设备指纹信息的 SM2 签名(pkcs1 格式)。
|
||||
~~设备指纹信息存储于文件 /home/tms/device/dev.info 文件,json 格式。~~
|
||||
设备指纹存放于签名文件 /home/tms/device/dev.sign, pkcs1 格式。校验值 /home/tms/device/dev.sign.sm3。
|
||||
设备指纹密钥公钥存储于文件 /home/tms/device/dev.fingerprint.pub, 公钥格式。校验值 /home/tms/device/dev.fingerprint.pub.sm3。
|
||||
设备激活密钥公钥存储于文件 /home/tms/device/dev.active.pub, 公钥格式。校验值 /home/tms/device/dev.active.pub.sm3。
|
||||
63
device-activation-platform/pom.xml
Normal file
63
device-activation-platform/pom.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.5.11</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>com.sunyar</groupId>
|
||||
<artifactId>device-activation-platform</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<name>device-activation-platform</name>
|
||||
<description>Device Activation Platform</description>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
<version>1.83</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk18on</artifactId>
|
||||
<version>1.83</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,11 @@
|
||||
package com.sunyar.cisd;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DeviceActivationApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DeviceActivationApplication.class, args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.sunyar.cisd;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/device")
|
||||
public class DeviceActivationController {
|
||||
|
||||
@Autowired
|
||||
private DeviceActivationService deviceActivationService;
|
||||
|
||||
@PostMapping("/active")
|
||||
public DeviceActivationResponse activate(@RequestBody DeviceActivationRequest request) {
|
||||
try {
|
||||
if (request.getParams() == null) {
|
||||
return DeviceActivationResponse.error("参数不能为空", "1001");
|
||||
}
|
||||
|
||||
DeviceActivationRequest.Params params = request.getParams();
|
||||
String concatenatedParams = params.toConcatenatedString();
|
||||
String calculatedHash = deviceActivationService.calculateSm3Hash(concatenatedParams);
|
||||
|
||||
String deviceActivationPublicKey = deviceActivationService.generateDeviceActivationPublicKey();
|
||||
String deviceActivationResult = deviceActivationService.signWithSm2Pkcs1(calculatedHash, deviceActivationPublicKey);
|
||||
|
||||
DeviceActivationResponse.Data data = new DeviceActivationResponse.Data();
|
||||
data.setHash(calculatedHash);
|
||||
data.setDeviceActivationPublicKey(deviceActivationPublicKey);
|
||||
data.setDeviceActivationResult(deviceActivationResult);
|
||||
|
||||
return DeviceActivationResponse.ok("设备激活成功", data);
|
||||
} catch (Exception e) {
|
||||
return DeviceActivationResponse.error("设备激活失败: " + e.getMessage(), "1002");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
package com.sunyar.cisd;
|
||||
|
||||
public class DeviceActivationRequest {
|
||||
private Params params;
|
||||
private String hash;
|
||||
|
||||
public DeviceActivationRequest() {
|
||||
}
|
||||
|
||||
public Params getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(Params params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void setHash(String hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
public static class Params {
|
||||
private String userId;
|
||||
private String credential;
|
||||
private String deviceActivationCode;
|
||||
private String deviceSerialNumber;
|
||||
private String deviceFingerprintJson;
|
||||
private String deviceSignature;
|
||||
private String devicePublicKey;
|
||||
private String timestamp;
|
||||
private String nonce;
|
||||
|
||||
public Params() {
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getCredential() {
|
||||
return credential;
|
||||
}
|
||||
|
||||
public void setCredential(String credential) {
|
||||
this.credential = credential;
|
||||
}
|
||||
|
||||
public String getDeviceActivationCode() {
|
||||
return deviceActivationCode;
|
||||
}
|
||||
|
||||
public void setDeviceActivationCode(String deviceActivationCode) {
|
||||
this.deviceActivationCode = deviceActivationCode;
|
||||
}
|
||||
|
||||
public String getDeviceSerialNumber() {
|
||||
return deviceSerialNumber;
|
||||
}
|
||||
|
||||
public void setDeviceSerialNumber(String deviceSerialNumber) {
|
||||
this.deviceSerialNumber = deviceSerialNumber;
|
||||
}
|
||||
|
||||
public String getDeviceFingerprintJson() {
|
||||
return deviceFingerprintJson;
|
||||
}
|
||||
|
||||
public void setDeviceFingerprintJson(String deviceFingerprintJson) {
|
||||
this.deviceFingerprintJson = deviceFingerprintJson;
|
||||
}
|
||||
|
||||
public String getDeviceSignature() {
|
||||
return deviceSignature;
|
||||
}
|
||||
|
||||
public void setDeviceSignature(String deviceSignature) {
|
||||
this.deviceSignature = deviceSignature;
|
||||
}
|
||||
|
||||
public String getDevicePublicKey() {
|
||||
return devicePublicKey;
|
||||
}
|
||||
|
||||
public void setDevicePublicKey(String devicePublicKey) {
|
||||
this.devicePublicKey = devicePublicKey;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(String timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
public void setNonce(String nonce) {
|
||||
this.nonce = nonce;
|
||||
}
|
||||
|
||||
public String toConcatenatedString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (userId != null) sb.append(userId);
|
||||
if (credential != null) sb.append(credential);
|
||||
if (deviceActivationCode != null) sb.append(deviceActivationCode);
|
||||
if (deviceSerialNumber != null) sb.append(deviceSerialNumber);
|
||||
if (deviceFingerprintJson != null) sb.append(deviceFingerprintJson);
|
||||
if (deviceSignature != null) sb.append(deviceSignature);
|
||||
if (devicePublicKey != null) sb.append(devicePublicKey);
|
||||
if (timestamp != null) sb.append(timestamp);
|
||||
if (nonce != null) sb.append(nonce);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
package com.sunyar.cisd;
|
||||
|
||||
public class DeviceActivationResponse {
|
||||
private String status;
|
||||
private String msg;
|
||||
private String code;
|
||||
private Data data;
|
||||
|
||||
public DeviceActivationResponse() {
|
||||
}
|
||||
|
||||
public static DeviceActivationResponse ok(String msg, Data data) {
|
||||
DeviceActivationResponse response = new DeviceActivationResponse();
|
||||
response.status = "ok";
|
||||
response.msg = msg;
|
||||
response.code = "0";
|
||||
response.data = data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public static DeviceActivationResponse error(String msg, String code) {
|
||||
DeviceActivationResponse response = new DeviceActivationResponse();
|
||||
response.status = "error";
|
||||
response.msg = msg;
|
||||
response.code = code;
|
||||
response.data = null;
|
||||
return response;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Data getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Data data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static class Data {
|
||||
private String hash;
|
||||
private String deviceActivationPublicKey;
|
||||
private String deviceActivationResult;
|
||||
|
||||
public Data() {
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void setHash(String hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
public String getDeviceActivationPublicKey() {
|
||||
return deviceActivationPublicKey;
|
||||
}
|
||||
|
||||
public void setDeviceActivationPublicKey(String deviceActivationPublicKey) {
|
||||
this.deviceActivationPublicKey = deviceActivationPublicKey;
|
||||
}
|
||||
|
||||
public String getDeviceActivationResult() {
|
||||
return deviceActivationResult;
|
||||
}
|
||||
|
||||
public void setDeviceActivationResult(String deviceActivationResult) {
|
||||
this.deviceActivationResult = deviceActivationResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.sunyar.cisd;
|
||||
|
||||
import org.bouncycastle.crypto.digests.SM3Digest;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Security;
|
||||
import java.security.Signature;
|
||||
import java.util.Base64;
|
||||
|
||||
@Service
|
||||
public class DeviceActivationService {
|
||||
|
||||
private static final String PROVIDER = "BC";
|
||||
private static final String SIGNATURE_ALGO = "SM3withSM2";
|
||||
|
||||
static {
|
||||
if (Security.getProvider(PROVIDER) == null) {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
}
|
||||
|
||||
public String calculateSm3Hash(String data) {
|
||||
SM3Digest digest = new SM3Digest();
|
||||
byte[] input = data.getBytes(StandardCharsets.UTF_8);
|
||||
digest.update(input, 0, input.length);
|
||||
byte[] hash = new byte[digest.getDigestSize()];
|
||||
digest.doFinal(hash, 0);
|
||||
return Hex.toHexString(hash);
|
||||
}
|
||||
|
||||
public String signWithSm2Pkcs1(String data, String privateKeyBase64) {
|
||||
try {
|
||||
byte[] keyBytes = Base64.getDecoder().decode(privateKeyBase64);
|
||||
java.security.spec.PKCS8EncodedKeySpec keySpec = new java.security.spec.PKCS8EncodedKeySpec(keyBytes);
|
||||
java.security.KeyFactory keyFactory = java.security.KeyFactory.getInstance("EC", PROVIDER);
|
||||
java.security.PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
|
||||
|
||||
Signature signature = Signature.getInstance(SIGNATURE_ALGO, PROVIDER);
|
||||
signature.initSign(privateKey);
|
||||
signature.update(data.getBytes(StandardCharsets.UTF_8));
|
||||
byte[] signatureBytes = signature.sign();
|
||||
return Base64.getEncoder().encodeToString(signatureBytes);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("SM2签名失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String generateDeviceActivationPublicKey() {
|
||||
try {
|
||||
java.security.KeyPairGenerator keyGen = java.security.KeyPairGenerator.getInstance("EC", PROVIDER);
|
||||
keyGen.initialize(256);
|
||||
java.security.KeyPair keyPair = keyGen.generateKeyPair();
|
||||
return Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("生成设备激活公钥失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package com.sunyar.cisd;
|
||||
|
||||
//TIP 要<b>运行</b>代码,请按 <shortcut actionId="Run"/> 或
|
||||
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
//TIP 当文本光标位于高亮显示的文本处时按 <shortcut actionId="ShowIntentionActions"/>
|
||||
// 查看 IntelliJ IDEA 建议如何修正。
|
||||
System.out.printf("Hello and welcome!");
|
||||
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
//TIP 按 <shortcut actionId="Debug"/> 开始调试代码。我们已经设置了一个 <icon src="AllIcons.Debugger.Db_set_breakpoint"/> 断点
|
||||
// 但您始终可以通过按 <shortcut actionId="ToggleLineBreakpoint"/> 添加更多断点。
|
||||
System.out.println("i = " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: device-activation-platform
|
||||
Loading…
Reference in New Issue
Block a user