diff --git a/openapi-sdk/pom.xml b/openapi-sdk/pom.xml
new file mode 100644
index 0000000..2fc0055
--- /dev/null
+++ b/openapi-sdk/pom.xml
@@ -0,0 +1,66 @@
+
+ 4.0.0
+
+ com.cisd
+ openapi-sdk
+ 1.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.5.11
+
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.12.0
+
+
+
+ org.bouncycastle
+ bcprov-jdk18on
+ 1.83
+ compile
+
+
+ org.springframework.boot
+ spring-boot-test
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ io.swagger.core.v3
+ swagger-annotations-jakarta
+ 2.2.28
+ compile
+
+
+
+
+
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/OpenapiSdkApplication.java b/openapi-sdk/src/main/java/com/cisd/openapi/OpenapiSdkApplication.java
new file mode 100644
index 0000000..f23015e
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/OpenapiSdkApplication.java
@@ -0,0 +1,15 @@
+package com.cisd.openapi;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+
+@SpringBootApplication
+@ConfigurationPropertiesScan
+public class OpenapiSdkApplication
+{
+ public static void main( String[] args ) {
+ SpringApplication.run(OpenapiSdkApplication.class, args);
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/SignClient.java b/openapi-sdk/src/main/java/com/cisd/openapi/SignClient.java
new file mode 100644
index 0000000..423320f
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/SignClient.java
@@ -0,0 +1,468 @@
+package com.cisd.openapi;
+
+import com.cisd.openapi.config.SignServerProperties;
+import com.cisd.openapi.dto.*;
+import com.cisd.openapi.exception.BusinessException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.*;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Base64;
+import java.util.UUID;
+
+@Component
+public class SignClient {
+
+ private static final MediaType JSON_MEDIA_TYPE =
+ MediaType.parse("application/json; charset=utf-8");
+
+ private final OkHttpClient okHttpClient;
+ private final ObjectMapper objectMapper;
+ private final SignServerProperties properties;
+
+ private final ThreadLocal lastReturnCode = new ThreadLocal<>();
+
+ public SignClient(OkHttpClient okHttpClient,
+ ObjectMapper objectMapper,
+ SignServerProperties properties) {
+ this.okHttpClient = okHttpClient;
+ this.objectMapper = objectMapper;
+ this.properties = properties;
+ }
+
+
+ public String rawSign(byte[] origBytes, String dn) {
+
+ String sessionId = UUID.randomUUID().toString().replace("-", "");
+
+ if (origBytes == null) {
+ lastReturnCode.set(-100100);
+ throw new IllegalArgumentException("origBytes不能为空");
+ }
+
+ if (dn == null || dn.isBlank()) {
+ lastReturnCode.set(-100100);
+ throw new IllegalArgumentException("dn不能为空");
+ }
+
+ if (origBytes.length > 4096){
+ lastReturnCode.set(-100100);
+ throw new IllegalArgumentException("数据过大");
+ }
+
+ String origBase64 = Base64.getEncoder().encodeToString(origBytes);
+ RawSignRequest rawSignRequest = new RawSignRequest(
+ origBase64,
+ dn
+ );
+
+ rawSignRequest.setSessionId(sessionId);
+
+ String requestJson;
+ try {
+ requestJson = objectMapper.writeValueAsString(rawSignRequest);
+ } catch (JsonProcessingException e) {
+ throw new IllegalArgumentException("serialize failed", e);
+ }
+
+ RequestBody requestBody = RequestBody.create(
+ requestJson,
+ JSON_MEDIA_TYPE
+ );
+
+ Request request = new Request.Builder()
+ .url(buildUrl(properties.getRawSignPath()))
+ .post(requestBody)
+ .addHeader("Content-Type", "application/json")
+ .addHeader("X-API-Key", properties.getApiKey())
+ .build();
+
+
+ try (Response response = okHttpClient.newCall(request).execute()) {
+ String responseBody = response.body() == null ? "" : response.body().string();
+ JsonNode root = objectMapper.readTree(responseBody);
+ int code = root.get("code").asInt();
+ System.out.println(root.toPrettyString());
+ if (code == 200){
+ RawSignResponse data = objectMapper.treeToValue(root.get("data"), RawSignResponse.class);
+ return data.getSignature();
+ } else if (code == 400){
+ ErrorDataResponse errorData = objectMapper.treeToValue(root.get("data"), ErrorDataResponse.class);
+ lastReturnCode.set(errorData.getCode());
+ throw new BusinessException("参数错误或签名失败(具体见返回码)", errorData);
+ } else if (code == 401){
+ throw new RuntimeException("未认证或会话无效");
+ } else{
+ throw new RuntimeException("会话不存在");
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("调用rawSign异常", e);
+ }
+ }
+
+
+ public boolean rawVerify(byte[] origBytes, String certStr, String dn) {
+
+ String sessionId = UUID.randomUUID().toString().replace("-", "");
+
+ if (origBytes == null) {
+ lastReturnCode.set(-100100);
+ throw new IllegalArgumentException("origBytes不能为空");
+ }
+
+ if (dn == null || dn.isBlank()) {
+ lastReturnCode.set(-100100);
+ throw new IllegalArgumentException("dn不能为空");
+ }
+
+ if (certStr == null || certStr.isBlank()) {
+ lastReturnCode.set(-100100);
+ throw new IllegalArgumentException("certStr签名串不能为空");
+ }
+
+ if (origBytes.length > 4096) {
+ lastReturnCode.set(-100100);
+ throw new IllegalArgumentException("数据过大");
+ }
+
+ String origBase64 = Base64.getEncoder().encodeToString(origBytes);
+// String origBase64 = "SGVsbG8gV29ybGQ=";
+ RawVerifyRequest rawVerifyRequest = new RawVerifyRequest(
+ origBase64,
+ dn,
+ certStr
+ );
+ rawVerifyRequest.setSessionId(sessionId);
+
+ String requestJson;
+ try {
+ requestJson = objectMapper.writeValueAsString(rawVerifyRequest);
+ } catch (JsonProcessingException e) {
+ throw new IllegalArgumentException("serialize failed", e);
+ }
+
+ RequestBody requestBody = RequestBody.create(
+ requestJson,
+ JSON_MEDIA_TYPE
+ );
+
+ Request request = new Request.Builder()
+ .url(buildUrl(properties.getRawVerifyPath()))
+ .post(requestBody)
+ .addHeader("Content-Type", "application/json")
+ .addHeader("X-API-Key", properties.getApiKey())
+ .build();
+
+
+ try (Response response = okHttpClient.newCall(request).execute()) {
+ String responseBody = response.body() == null ? "" : response.body().string();
+ JsonNode root = objectMapper.readTree(responseBody);
+ int code = root.get("code").asInt();
+ if (code == 200) {
+ RawVerifyResponse data = objectMapper.treeToValue(root.get("data"), RawVerifyResponse.class);
+ return data.getVerified();
+ } else if (code == 400) {
+ ErrorDataResponse errorData = objectMapper.treeToValue(root.get("data"), ErrorDataResponse.class);
+ lastReturnCode.set(errorData.getCode());
+ throw new BusinessException("参数错误或签名失败(具体见返回码)", errorData);
+ } else if (code == 401) {
+ throw new RuntimeException("未认证或会话无效");
+ } else {
+ throw new RuntimeException("会话不存在");
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("调用rawVerify异常", e);
+ }
+ }
+
+
+ public String dettachedSign(byte[] origBytes, String dn) {
+
+ String sessionId = UUID.randomUUID().toString().replace("-", "");
+
+ if (origBytes == null) {
+ throw new IllegalArgumentException("origBytes不能为空");
+ }
+
+ if (dn == null || dn.isBlank()) {
+ throw new IllegalArgumentException("dn不能为空");
+ }
+
+ if (origBytes.length > 4096){
+ throw new IllegalArgumentException("数据过大大");
+ }
+
+ String origBase64 = Base64.getEncoder().encodeToString(origBytes);
+ DettachedSignRequest dettachedSignRequest = new DettachedSignRequest(
+ sessionId,
+ origBase64,
+ dn
+ );
+
+ String requestJson;
+ try {
+ requestJson = objectMapper.writeValueAsString(dettachedSignRequest);
+ } catch (JsonProcessingException e) {
+ throw new IllegalArgumentException("serialize failed", e);
+ }
+
+ RequestBody requestBody = RequestBody.create(
+ requestJson,
+ JSON_MEDIA_TYPE
+ );
+
+ Request request = new Request.Builder()
+ .url(buildUrl(properties.getDettachedSignPath()))
+ .post(requestBody)
+ .addHeader("Content-Type", "application/json")
+ .addHeader("X-API-Key", properties.getApiKey())
+ .build();
+
+
+ try (Response response = okHttpClient.newCall(request).execute()) {
+ String responseBody = response.body() == null ? "" : response.body().string();
+ JsonNode root = objectMapper.readTree(responseBody);
+ int code = root.get("code").asInt();
+
+ if (code == 200){
+ DettachedSignResponse data = objectMapper.treeToValue(root.get("data"), DettachedSignResponse.class);
+ return data.getSignature();
+ } else if (code == 400){
+ ErrorDataResponse errorData = objectMapper.treeToValue(root.get("data"), ErrorDataResponse.class);
+ throw new BusinessException("参数错误或签名失败(具体见返回码)", errorData);
+ } else if (code == 401){
+ throw new RuntimeException("未认证或会话无效");
+ } else{
+ throw new RuntimeException("会话不存在");
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("调用dettachedSign异常", e);
+ }
+ }
+
+
+ public GenericCertificate dettachedVerify(byte[] origBytes, String certStr) {
+
+ String sessionId = UUID.randomUUID().toString().replace("-", "");
+
+ if (origBytes == null) {
+ throw new IllegalArgumentException("origBytes不能为空");
+ }
+
+ if (certStr == null || certStr.isBlank()) {
+ throw new IllegalArgumentException("certStr签名串不能为空");
+ }
+
+ if (origBytes.length > 4096){
+ throw new IllegalArgumentException("数据过大");
+ }
+
+ String origBase64 = Base64.getEncoder().encodeToString(origBytes);
+ DettachedVerifyRequest dettachedVerifyRequest = new DettachedVerifyRequest(
+ origBase64,
+ certStr
+ );
+ dettachedVerifyRequest.setSessionId(sessionId);
+
+
+ String requestJson;
+ try {
+ requestJson = objectMapper.writeValueAsString(dettachedVerifyRequest);
+ } catch (JsonProcessingException e) {
+ throw new IllegalArgumentException("serialize failed", e);
+ }
+
+ RequestBody requestBody = RequestBody.create(
+ requestJson,
+ JSON_MEDIA_TYPE
+ );
+
+ Request request = new Request.Builder()
+ .url(buildUrl(properties.getDettachedVerifyPath()))
+ .post(requestBody)
+ .addHeader("Content-Type", "application/json")
+ .addHeader("X-API-Key", properties.getApiKey())
+ .build();
+
+
+ try (Response response = okHttpClient.newCall(request).execute()) {
+ String responseBody = response.body() == null ? "" : response.body().string();
+ JsonNode root = objectMapper.readTree(responseBody);
+ int code = root.get("code").asInt();
+ System.out.println(root.toPrettyString());
+ if (code == 200){
+ DettachedVerifyResponse data = objectMapper.treeToValue(root.get("data"), DettachedVerifyResponse.class);
+ return data.getGenericCertificate();
+ } else if (code == 400){
+ ErrorDataResponse errorData = objectMapper.treeToValue(root.get("data"), ErrorDataResponse.class);
+// System.out.println(errorData.getCode());
+// System.out.println(errorData.getMessage());
+ throw new BusinessException("参数错误或签名失败(具体见返回码)", errorData);
+ } else if (code == 401){
+ throw new RuntimeException("未认证或会话无效");
+ } else{
+ throw new RuntimeException("会话不存在");
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("调用dettachedVerify异常", e);
+ }
+ }
+
+
+
+ public GenericCertificate dettachedVerifySimple(byte[] origBytes, String certStr) {
+
+ String sessionId = UUID.randomUUID().toString().replace("-", "");
+
+ if (origBytes == null) {
+ throw new IllegalArgumentException("origBytes不能为空");
+ }
+
+ if (certStr == null || certStr.isBlank()) {
+ throw new IllegalArgumentException("certStr签名串不能为空");
+ }
+
+ if (origBytes.length > 4096){
+ throw new IllegalArgumentException("数据过大");
+ }
+
+ String origBase64 = Base64.getEncoder().encodeToString(origBytes);
+ DettachedVerifySimpleRequest dettachedVerifySimpleRequest = new DettachedVerifySimpleRequest(
+ origBase64,
+ certStr
+ );
+ dettachedVerifySimpleRequest.setSessionId(sessionId);
+
+ String requestJson;
+ try {
+ requestJson = objectMapper.writeValueAsString(dettachedVerifySimpleRequest);
+ } catch (JsonProcessingException e) {
+ throw new IllegalArgumentException("serialize failed", e);
+ }
+
+
+ RequestBody requestBody = RequestBody.create(
+ requestJson,
+ JSON_MEDIA_TYPE
+ );
+
+ Request request = new Request.Builder()
+ .url(buildUrl(properties.getDettachedVerifySimplePath()))
+ .post(requestBody)
+ .addHeader("Content-Type", "application/json")
+ .addHeader("X-API-Key", properties.getApiKey())
+ .build();
+
+
+ try (Response response = okHttpClient.newCall(request).execute()) {
+ String responseBody = response.body() == null ? "" : response.body().string();
+ JsonNode root = objectMapper.readTree(responseBody);
+ int code = root.get("code").asInt();
+ System.out.println(root.toPrettyString());
+ if (code == 200){
+ DettachedVerifySimpleResponse data = objectMapper.treeToValue(root.get("data"), DettachedVerifySimpleResponse.class);
+ return data.getGenericCertificate();
+ } else if (code == 400){
+ ErrorDataResponse errorData = objectMapper.treeToValue(root.get("data"), ErrorDataResponse.class);
+ throw new BusinessException("参数错误或签名失败(具体见返回码)", errorData);
+ } else if (code == 401){
+ throw new RuntimeException("未认证或会话无效");
+ } else{
+ throw new RuntimeException("会话不存在");
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("调用dettachedVerifySimple异常", e);
+ }
+ }
+
+
+ public boolean uploadCert(String bankCode, X509Certificate certificate){
+
+ String sessionId = UUID.randomUUID().toString().replace("-", "");
+
+ if (bankCode == null || bankCode.isBlank()) {
+ throw new IllegalArgumentException("origBytes不能为空");
+ }
+
+ if (certificate == null){
+ throw new IllegalArgumentException("certificate不能为空");
+ }
+
+
+ UploadCertRequest uploadCertRequest = new UploadCertRequest(
+ bankCode,
+ certificate
+ );
+ uploadCertRequest.setSessionId(sessionId);
+
+ String requestJson;
+ try {
+ requestJson = objectMapper.writeValueAsString(uploadCertRequest);
+ }catch (JsonProcessingException e){
+ throw new IllegalArgumentException("serialize failed", e);
+ }
+
+ RequestBody requestBody = RequestBody.create(
+ requestJson,
+ JSON_MEDIA_TYPE
+ );
+
+ Request request = new Request.Builder()
+ .url(buildUrl(properties.getUploadCertPath()))
+ .post(requestBody)
+ .addHeader("Content-Type", "application/json")
+ .addHeader("X-API-Key", properties.getApiKey())
+ .build();
+
+
+ try (Response response = okHttpClient.newCall(request).execute()) {
+ String responseBody = response.body() == null ? "" : response.body().string();
+ JsonNode root = objectMapper.readTree(responseBody);
+ int code = root.get("code").asInt();
+
+ if (code == 200){
+ UploadCertResponse data = objectMapper.treeToValue(root.get("data"), UploadCertResponse.class);
+ return data.getSuccess();
+ } else if (code == 400){
+ ErrorDataResponse errorData = objectMapper.treeToValue(root.get("data"), ErrorDataResponse.class);
+ throw new BusinessException("参数错误或签名失败(具体见返回码)", errorData);
+ } else if (code == 401){
+ throw new RuntimeException("未认证或会话无效");
+ } else{
+ throw new RuntimeException("会话不存在");
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("调用uploadCert异常", e);
+ }
+ }
+
+
+ public Integer lastReturnCode(){
+ return lastReturnCode.get();
+ }
+
+
+ private String buildUrl(String path) {
+ String baseUrl = properties.getBaseUrl();
+
+ if (baseUrl.endsWith("/") && path.startsWith("/")) {
+ return baseUrl.substring(0, baseUrl.length() - 1) + path;
+ }
+
+ if (!baseUrl.endsWith("/") && !path.startsWith("/")) {
+ return baseUrl + "/" + path;
+ }
+
+ return baseUrl + path;
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/config/OkHttpConfig.java b/openapi-sdk/src/main/java/com/cisd/openapi/config/OkHttpConfig.java
new file mode 100644
index 0000000..b6665ef
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/config/OkHttpConfig.java
@@ -0,0 +1,20 @@
+package com.cisd.openapi.config;
+
+import okhttp3.OkHttpClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.time.Duration;
+
+@Configuration
+public class OkHttpConfig {
+
+ @Bean
+ public OkHttpClient okHttpClient() {
+ return new OkHttpClient.Builder()
+ .connectTimeout(Duration.ofSeconds(5))
+ .writeTimeout(Duration.ofSeconds(10))
+ .readTimeout(Duration.ofSeconds(30))
+ .build();
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/config/SignServerProperties.java b/openapi-sdk/src/main/java/com/cisd/openapi/config/SignServerProperties.java
new file mode 100644
index 0000000..51d8d7e
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/config/SignServerProperties.java
@@ -0,0 +1,29 @@
+package com.cisd.openapi.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "sign-server")
+@Data
+public class SignServerProperties {
+
+ private String baseUrl;
+
+ private String apiKey;
+
+ private String rawSignPath;
+
+ private String rawVerifyPath;
+
+ private String dettachedSignPath;
+
+ private String dettachedVerifyPath;
+
+ private String dettachedVerifySimplePath;
+
+ private String uploadCertPath;
+
+ private String lastReturnCodePath;
+}
\ No newline at end of file
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/CertificateInfo.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/CertificateInfo.java
new file mode 100644
index 0000000..0685b06
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/CertificateInfo.java
@@ -0,0 +1,10 @@
+package com.cisd.openapi.dto;
+
+public class CertificateInfo {
+ private String subjectDN;
+ private String issuerDN;
+ private String serialNumber;
+ private String notBefore;
+ private String notAfter;
+ private String base64Encoded;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedSignRequest.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedSignRequest.java
new file mode 100644
index 0000000..84308e6
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedSignRequest.java
@@ -0,0 +1,19 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class DettachedSignRequest {
+
+ private String sessionId;
+
+ private String origBytes;
+
+ private String dn;
+
+ public DettachedSignRequest(String sessionId, String origBytes, String dn) {
+ this.sessionId = sessionId;
+ this.origBytes = origBytes;
+ this.dn = dn;
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedSignResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedSignResponse.java
new file mode 100644
index 0000000..42ef804
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedSignResponse.java
@@ -0,0 +1,9 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class DettachedSignResponse {
+
+ private String signature;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifyRequest.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifyRequest.java
new file mode 100644
index 0000000..f8ea40a
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifyRequest.java
@@ -0,0 +1,20 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class DettachedVerifyRequest {
+
+ private String sessionId;
+
+ private String origBytes;
+
+ private String signature;
+
+
+ public DettachedVerifyRequest(String origBytes, String signature) {
+ this.origBytes = origBytes;
+ this.signature = signature;
+ }
+
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifyResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifyResponse.java
new file mode 100644
index 0000000..981391e
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifyResponse.java
@@ -0,0 +1,9 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class DettachedVerifyResponse {
+
+ private GenericCertificate genericCertificate;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifySimpleRequest.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifySimpleRequest.java
new file mode 100644
index 0000000..c6e72c6
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifySimpleRequest.java
@@ -0,0 +1,19 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class DettachedVerifySimpleRequest {
+
+ private String sessionId;
+
+ private String origBytes;
+
+ private String signature;
+
+ public DettachedVerifySimpleRequest(String origBytes, String signature) {
+ this.origBytes = origBytes;
+ this.signature = signature;
+ }
+
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifySimpleResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifySimpleResponse.java
new file mode 100644
index 0000000..6415584
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DettachedVerifySimpleResponse.java
@@ -0,0 +1,9 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class DettachedVerifySimpleResponse {
+
+ private GenericCertificate genericCertificate;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/DeviceActivateInfoResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DeviceActivateInfoResponse.java
new file mode 100644
index 0000000..69f844b
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DeviceActivateInfoResponse.java
@@ -0,0 +1,19 @@
+package com.cisd.openapi.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class DeviceActivateInfoResponse {
+
+ @Schema(description = "设备型号", example = "SYD7108")
+ private String deviceModel;
+ @Schema(description = "设备名称", example = "跨境支付终端一体机")
+ private String deviceName;
+ @Schema(description = "设备版本", example = "1.0.0")
+ private String version;
+ @Schema(description = "设备序列号", example = "1234567890ABCDEF")
+ private String serialNumber;
+ @Schema(description = "设备状态", example = "INITIALIZED")
+ private String deviceStatus;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/DeviceActivateRequest.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DeviceActivateRequest.java
new file mode 100644
index 0000000..6558eef
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/DeviceActivateRequest.java
@@ -0,0 +1,11 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class DeviceActivateRequest {
+
+ private String userId;
+ private String credential;
+ private String activationCode;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/ErrorDataResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/ErrorDataResponse.java
new file mode 100644
index 0000000..4d8289d
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/ErrorDataResponse.java
@@ -0,0 +1,9 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class ErrorDataResponse {
+ Integer code;
+ String message;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/GenericCertificate.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/GenericCertificate.java
new file mode 100644
index 0000000..0e36845
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/GenericCertificate.java
@@ -0,0 +1,123 @@
+package com.cisd.openapi.dto;
+
+import com.cisd.openapi.util.Base64;
+import com.cisd.openapi.util.NetSignAgentUtil;
+import com.cisd.openapi.util.PBCUtil;
+
+import java.security.cert.X509Certificate;
+import java.text.SimpleDateFormat;
+
+
+public class GenericCertificate {
+ private String bankcode;
+ private String subject;
+ private String ser_number;
+ private String issuer_subject;
+ private String start_time;
+ private String end_time;
+ private X509Certificate cert;
+
+ public GenericCertificate() {
+ }
+
+ public GenericCertificate(X509Certificate cert) {
+ this.setCert(cert);
+ }
+
+ public String getBankcode() {
+ return this.bankcode;
+ }
+
+ public void setBankcode(String bankcode) {
+ this.bankcode = bankcode;
+ }
+
+ public String getSubject() {
+ return this.subject;
+ }
+
+ public void setSubject(String subject) {
+ this.subject = subject;
+ }
+
+ public String getSer_number() {
+ return this.ser_number;
+ }
+
+ public void setSer_number(String ser_number) {
+ this.ser_number = ser_number;
+ }
+
+ public String getIssuer_subject() {
+ return this.issuer_subject;
+ }
+
+ public void setIssuer_subject(String issuer_subject) {
+ this.issuer_subject = issuer_subject;
+ }
+
+ public String getStart_time() {
+ return this.start_time;
+ }
+
+ public void setStart_time(String start_time) {
+ this.start_time = start_time;
+ }
+
+ public String getEnd_time() {
+ return this.end_time;
+ }
+
+ public void setEnd_time(String end_time) {
+ this.end_time = end_time;
+ }
+
+ public X509Certificate getCert() {
+ return this.cert;
+ }
+
+ public String getBase64Cert() {
+ if (this.cert == null) {
+ return null;
+ } else {
+ try {
+ return Base64.encode(this.cert.getEncoded());
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ }
+
+ public void setCert(X509Certificate cert) {
+ this.cert = cert;
+ this.subject = NetSignAgentUtil.getDN(cert.getSubjectDN().toString());
+ this.ser_number = NetSignAgentUtil.dealSN(cert.getSerialNumber().toString(16).toUpperCase());
+ this.issuer_subject = NetSignAgentUtil.getDN(cert.getIssuerDN().toString());
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+ this.start_time = sdf.format(cert.getNotBefore());
+ this.end_time = sdf.format(cert.getNotAfter());
+ this.bankcode = PBCUtil.getBankID(this.subject);
+ }
+
+ public String toString() {
+ StringBuffer s = new StringBuffer();
+ s.append("=============BEGIN GenericCertificate===================\n");
+ s.append("bankCode:").append(this.bankcode).append("\n");
+ s.append("issuerSubject:").append(this.issuer_subject).append("\n");
+ s.append("serialNumber:").append(this.ser_number).append("\n");
+ s.append("subject:").append(this.subject).append("\n");
+ s.append("startTime:").append(this.start_time).append("\n");
+ s.append("endTime:").append(this.end_time).append("\n");
+ if (this.cert != null) {
+ try {
+ s.append("cert:").append(Base64.encode(this.cert.getEncoded())).append("\n");
+ } catch (Exception var3) {
+ }
+ }
+
+ s.append("=============END GenericCertificate=====================\n");
+ return s.toString();
+ }
+}
+
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/LastReturnCodeRequest.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/LastReturnCodeRequest.java
new file mode 100644
index 0000000..aaa613b
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/LastReturnCodeRequest.java
@@ -0,0 +1,12 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class LastReturnCodeRequest {
+ private String sessionId;
+
+ public LastReturnCodeRequest(String sessionId){
+ this.sessionId = sessionId;
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/LastReturnCodeResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/LastReturnCodeResponse.java
new file mode 100644
index 0000000..18aed67
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/LastReturnCodeResponse.java
@@ -0,0 +1,8 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class LastReturnCodeResponse {
+ private Integer returnCode;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawSignRequest.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawSignRequest.java
new file mode 100644
index 0000000..2ead011
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawSignRequest.java
@@ -0,0 +1,19 @@
+package com.cisd.openapi.dto;
+
+
+import lombok.Data;
+
+@Data
+public class RawSignRequest {
+
+ private String sessionId;
+
+ private String origBytes;
+
+ private String dn;
+
+ public RawSignRequest(String origBytes, String dn) {
+ this.origBytes = origBytes;
+ this.dn = dn;
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawSignResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawSignResponse.java
new file mode 100644
index 0000000..6510c5a
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawSignResponse.java
@@ -0,0 +1,8 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class RawSignResponse {
+ private String signature;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawVerifyRequest.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawVerifyRequest.java
new file mode 100644
index 0000000..b003a67
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawVerifyRequest.java
@@ -0,0 +1,24 @@
+package com.cisd.openapi.dto;
+
+
+import lombok.Data;
+
+@Data
+public class RawVerifyRequest {
+
+ private String sessionId;
+
+ private String origBytes;
+
+ private String dn;
+
+ private String signature;
+
+ public RawVerifyRequest(String origBytes, String dn, String signature) {
+ this.origBytes = origBytes;
+ this.dn = dn;
+ this.signature = signature;
+ }
+
+
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawVerifyResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawVerifyResponse.java
new file mode 100644
index 0000000..2c3b53c
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/RawVerifyResponse.java
@@ -0,0 +1,10 @@
+package com.cisd.openapi.dto;
+
+
+import lombok.Data;
+
+@Data
+public class RawVerifyResponse {
+ private Boolean verified;
+ private String message;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/UploadCertRequest.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/UploadCertRequest.java
new file mode 100644
index 0000000..c317cfd
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/UploadCertRequest.java
@@ -0,0 +1,18 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+import java.security.cert.X509Certificate;
+
+@Data
+public class UploadCertRequest {
+
+ private String sessionId;
+ private String bankCode;
+ private X509Certificate certificate;
+
+ public UploadCertRequest(String bankCode, X509Certificate certificate) {
+ this.bankCode = bankCode;
+ this.certificate = certificate;
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/dto/UploadCertResponse.java b/openapi-sdk/src/main/java/com/cisd/openapi/dto/UploadCertResponse.java
new file mode 100644
index 0000000..0a159ea
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/dto/UploadCertResponse.java
@@ -0,0 +1,9 @@
+package com.cisd.openapi.dto;
+
+import lombok.Data;
+
+@Data
+public class UploadCertResponse {
+
+ private Boolean success;
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/exception/BusinessException.java b/openapi-sdk/src/main/java/com/cisd/openapi/exception/BusinessException.java
new file mode 100644
index 0000000..4cecad0
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/exception/BusinessException.java
@@ -0,0 +1,16 @@
+package com.cisd.openapi.exception;
+
+import com.cisd.openapi.dto.ErrorDataResponse;
+
+public class BusinessException extends RuntimeException {
+ private final ErrorDataResponse errorData;
+
+ public BusinessException(String message, ErrorDataResponse errorData) {
+ super(message);
+ this.errorData = errorData;
+ }
+
+ public ErrorDataResponse getErrorData() {
+ return errorData;
+ }
+}
\ No newline at end of file
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/util/Base64.java b/openapi-sdk/src/main/java/com/cisd/openapi/util/Base64.java
new file mode 100644
index 0000000..cbc7bde
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/util/Base64.java
@@ -0,0 +1,324 @@
+package com.cisd.openapi.util;
+
+import java.util.Arrays;
+
+public class Base64 {
+ private static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
+ private static final int[] IA = new int[256];
+
+ static {
+ Arrays.fill(IA, -1);
+ int i = 0;
+
+ for (int iS = CA.length; i < iS; IA[CA[i]] = i++) {
+ }
+
+ IA[61] = 0;
+ }
+
+ public static final String encode(byte[] sArr) {
+ return new String(encodeToString(sArr, false));
+ }
+
+ private static final char[] encodeToChar(byte[] sArr, boolean lineSep) {
+ int sLen = sArr != null ? sArr.length : 0;
+ if (sLen == 0) {
+ return new char[0];
+ } else {
+ int eLen = sLen / 3 * 3;
+ int cCnt = (sLen - 1) / 3 + 1 << 2;
+ int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0);
+ char[] dArr = new char[dLen];
+ int s = 0;
+ int d = 0;
+ int cc = 0;
+
+ while (s < eLen) {
+ int i = (sArr[s++] & 255) << 16 | (sArr[s++] & 255) << 8 | sArr[s++] & 255;
+ dArr[d++] = CA[i >>> 18 & 63];
+ dArr[d++] = CA[i >>> 12 & 63];
+ dArr[d++] = CA[i >>> 6 & 63];
+ dArr[d++] = CA[i & 63];
+ if (lineSep) {
+ ++cc;
+ if (cc == 19 && d < dLen - 2) {
+ dArr[d++] = '\r';
+ dArr[d++] = '\n';
+ cc = 0;
+ }
+ }
+ }
+
+ s = sLen - eLen;
+ if (s > 0) {
+ d = (sArr[eLen] & 255) << 10 | (s == 2 ? (sArr[sLen - 1] & 255) << 2 : 0);
+ dArr[dLen - 4] = CA[d >> 12];
+ dArr[dLen - 3] = CA[d >>> 6 & 63];
+ dArr[dLen - 2] = s == 2 ? CA[d & 63] : 61;
+ dArr[dLen - 1] = '=';
+ }
+
+ return dArr;
+ }
+ }
+
+ public static final byte[] decode(char[] sArr) {
+ char[] tmp = new char[sArr.length];
+ int t = 0;
+ int i = 0;
+
+ for (int length = sArr.length; i < length; ++i) {
+ if (sArr[i] >= 'A' && sArr[i] <= 'Z' || sArr[i] >= 'a' && sArr[i] <= 'z' || sArr[i] >= '0' && sArr[i] <= '9' || sArr[i] == '+' || sArr[i] == '/' || sArr[i] == '=') {
+ tmp[t] = sArr[i];
+ ++t;
+ }
+ }
+
+ char[] tmp2 = new char[t];
+ System.arraycopy(tmp, 0, tmp2, 0, t);
+ tmp = (char[]) null;
+ return decodeFast(tmp2);
+ }
+
+ private static final byte[] decodeFast(char[] sArr) {
+ int sLen = sArr.length;
+ if (sLen == 0) {
+ return new byte[0];
+ } else {
+ int sIx = 0;
+
+ int eIx;
+ for (eIx = sLen - 1; sIx < eIx && IA[sArr[sIx]] < 0; ++sIx) {
+ }
+
+ while (eIx > 0 && IA[sArr[eIx]] < 0) {
+ --eIx;
+ }
+
+ int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0;
+ int cCnt = eIx - sIx + 1;
+ int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
+ int len = ((cCnt - sepCnt) * 6 >> 3) - pad;
+ byte[] dArr = new byte[len];
+ int d = 0;
+ int cc = 0;
+ int eLen = len / 3 * 3;
+
+ while (d < eLen) {
+ int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]];
+ dArr[d++] = (byte) (i >> 16);
+ dArr[d++] = (byte) (i >> 8);
+ dArr[d++] = (byte) i;
+ if (sepCnt > 0) {
+ ++cc;
+ if (cc == 19) {
+ sIx += 2;
+ cc = 0;
+ }
+ }
+ }
+
+ if (d < len) {
+ cc = 0;
+
+ for (int j = 0; sIx <= eIx - pad; ++j) {
+ cc |= IA[sArr[sIx++]] << 18 - j * 6;
+ }
+
+ for (int r = 16; d < len; r -= 8) {
+ dArr[d++] = (byte) (cc >> r);
+ }
+ }
+
+ return dArr;
+ }
+ }
+
+ private static final byte[] encodeToByte(byte[] sArr, boolean lineSep) {
+ int sLen = sArr != null ? sArr.length : 0;
+ if (sLen == 0) {
+ return new byte[0];
+ } else {
+ int eLen = sLen / 3 * 3;
+ int cCnt = (sLen - 1) / 3 + 1 << 2;
+ int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0);
+ byte[] dArr = new byte[dLen];
+ int s = 0;
+ int d = 0;
+ int cc = 0;
+
+ while (s < eLen) {
+ int i = (sArr[s++] & 255) << 16 | (sArr[s++] & 255) << 8 | sArr[s++] & 255;
+ dArr[d++] = (byte) CA[i >>> 18 & 63];
+ dArr[d++] = (byte) CA[i >>> 12 & 63];
+ dArr[d++] = (byte) CA[i >>> 6 & 63];
+ dArr[d++] = (byte) CA[i & 63];
+ if (lineSep) {
+ ++cc;
+ if (cc == 19 && d < dLen - 2) {
+ dArr[d++] = 13;
+ dArr[d++] = 10;
+ cc = 0;
+ }
+ }
+ }
+
+ s = sLen - eLen;
+ if (s > 0) {
+ d = (sArr[eLen] & 255) << 10 | (s == 2 ? (sArr[sLen - 1] & 255) << 2 : 0);
+ dArr[dLen - 4] = (byte) CA[d >> 12];
+ dArr[dLen - 3] = (byte) CA[d >>> 6 & 63];
+ dArr[dLen - 2] = s == 2 ? (byte) CA[d & 63] : 61;
+ dArr[dLen - 1] = 61;
+ }
+
+ return dArr;
+ }
+ }
+
+ public static final byte[] decode(byte[] sArr) {
+ byte[] tmp = new byte[sArr.length];
+ int t = 0;
+ int i = 0;
+
+ for (int length = sArr.length; i < length; ++i) {
+ if (sArr[i] >= 65 && sArr[i] <= 90 || sArr[i] >= 97 && sArr[i] <= 122 || sArr[i] >= 48 && sArr[i] <= 57 || sArr[i] == 43 || sArr[i] == 47 || sArr[i] == 61) {
+ tmp[t] = sArr[i];
+ ++t;
+ }
+ }
+
+ byte[] tmp2 = new byte[t];
+ System.arraycopy(tmp, 0, tmp2, 0, t);
+ tmp = (byte[]) null;
+ return decodeFast(tmp2);
+ }
+
+ private static final byte[] decodeFast(byte[] sArr) {
+ int sLen = sArr.length;
+ if (sLen == 0) {
+ return new byte[0];
+ } else {
+ int sIx = 0;
+
+ int eIx;
+ for (eIx = sLen - 1; sIx < eIx && IA[sArr[sIx] & 255] < 0; ++sIx) {
+ }
+
+ while (eIx > 0 && IA[sArr[eIx] & 255] < 0) {
+ --eIx;
+ }
+
+ int pad = sArr[eIx] == 61 ? (sArr[eIx - 1] == 61 ? 2 : 1) : 0;
+ int cCnt = eIx - sIx + 1;
+ int sepCnt = sLen > 76 ? (sArr[76] == 13 ? cCnt / 78 : 0) << 1 : 0;
+ int len = ((cCnt - sepCnt) * 6 >> 3) - pad;
+ byte[] dArr = new byte[len];
+ int d = 0;
+ int cc = 0;
+ int eLen = len / 3 * 3;
+
+ while (d < eLen) {
+ int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]];
+ dArr[d++] = (byte) (i >> 16);
+ dArr[d++] = (byte) (i >> 8);
+ dArr[d++] = (byte) i;
+ if (sepCnt > 0) {
+ ++cc;
+ if (cc == 19) {
+ sIx += 2;
+ cc = 0;
+ }
+ }
+ }
+
+ if (d < len) {
+ cc = 0;
+
+ for (int j = 0; sIx <= eIx - pad; ++j) {
+ cc |= IA[sArr[sIx++]] << 18 - j * 6;
+ }
+
+ for (int r = 16; d < len; r -= 8) {
+ dArr[d++] = (byte) (cc >> r);
+ }
+ }
+
+ return dArr;
+ }
+ }
+
+ private static final String encodeToString(byte[] sArr, boolean lineSep) {
+ return new String(encodeToChar(sArr, lineSep));
+ }
+
+ public static final byte[] decode(String sArr) {
+ return decode(sArr.getBytes());
+ }
+
+ private static final byte[] decodeFast(String s) {
+ int sLen = s.length();
+ if (sLen == 0) {
+ return new byte[0];
+ } else {
+ int sIx = 0;
+
+ int eIx;
+ for (eIx = sLen - 1; sIx < eIx && IA[s.charAt(sIx) & 255] < 0; ++sIx) {
+ }
+
+ while (eIx > 0 && IA[s.charAt(eIx) & 255] < 0) {
+ --eIx;
+ }
+
+ int pad = s.charAt(eIx) == '=' ? (s.charAt(eIx - 1) == '=' ? 2 : 1) : 0;
+ int cCnt = eIx - sIx + 1;
+ int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0;
+ int len = ((cCnt - sepCnt) * 6 >> 3) - pad;
+ byte[] dArr = new byte[len];
+ int d = 0;
+ int cc = 0;
+ int eLen = len / 3 * 3;
+
+ while (d < eLen) {
+ int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)];
+ dArr[d++] = (byte) (i >> 16);
+ dArr[d++] = (byte) (i >> 8);
+ dArr[d++] = (byte) i;
+ if (sepCnt > 0) {
+ ++cc;
+ if (cc == 19) {
+ sIx += 2;
+ cc = 0;
+ }
+ }
+ }
+
+ if (d < len) {
+ cc = 0;
+
+ for (int j = 0; sIx <= eIx - pad; ++j) {
+ cc |= IA[s.charAt(sIx++)] << 18 - j * 6;
+ }
+
+ for (int r = 16; d < len; r -= 8) {
+ dArr[d++] = (byte) (cc >> r);
+ }
+ }
+
+ return dArr;
+ }
+ }
+
+ public static void main(String[] args) {
+ String a = "abcabc";
+ String b64 = encode(a.getBytes());
+ System.out.println(b64);
+ b64 = "YWJj\r\nYWJj\r\nYWJj\r\n";
+ byte[] x = decode(b64.getBytes());
+ System.out.println(encode(x));
+ byte[] plain = new byte[]{18, 52};
+ char[] var10000 = new char[]{'\u0012', '4'};
+ System.out.println(encode(plain));
+ }
+}
\ No newline at end of file
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/util/DNItemReverseUtil.java b/openapi-sdk/src/main/java/com/cisd/openapi/util/DNItemReverseUtil.java
new file mode 100644
index 0000000..34488ba
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/util/DNItemReverseUtil.java
@@ -0,0 +1,117 @@
+package com.cisd.openapi.util;
+
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+public class DNItemReverseUtil {
+ private static final String[] dNObjectsForward = new String[]{"1.2.840.113549.1.9.8", "1.2.840.113549.1.9.2", "emailaddress", "e", "email", "uid", "cn", "sn", "serialnumber", "gn", "givenname", "initials", "surname", "t", "ou", "o", "l", "st", "dc", "c"};
+ private static final String[] dNObjectsReverse = new String[]{"c", "dc", "st", "l", "o", "ou", "t", "surname", "initials", "givenname", "gn", "serialnumber", "sn", "cn", "uid", "email", "e", "emailaddress", "1.2.840.113549.1.9.2", "1.2.840.113549.1.9.8"};
+ private static final String[] dNObjects;
+
+ static {
+ dNObjects = dNObjectsForward;
+ }
+
+ public static String reverse(String dn) {
+ StringTokenizer st = new StringTokenizer(dn, ",");
+ Stack s = new Stack();
+
+ while(st.hasMoreTokens()) {
+ s.push(st.nextToken());
+ }
+
+ int len = s.size();
+ StringBuffer buffer = new StringBuffer();
+
+ for(int i = 0; i < len; ++i) {
+ if (i > 0) {
+ buffer.append(",");
+ }
+
+ buffer.append((String)s.pop());
+ }
+
+ return buffer.toString();
+ }
+
+// public static String reverseDN(String dn) {
+// String ret = null;
+// if (dn != null) {
+// BasicX509NameTokenizer xt = new BasicX509NameTokenizer(dn);
+// StringBuffer buf = new StringBuffer();
+//
+// String o;
+// for(boolean first = true; xt.hasMoreTokens(); buf.insert(0, o)) {
+// o = xt.nextToken();
+// if (!first) {
+// buf.insert(0, ",");
+// } else {
+// first = false;
+// }
+// }
+//
+// if (buf.length() > 0) {
+// ret = buf.toString();
+// }
+// }
+//
+// return ret;
+// }
+
+ public static String reverseDN2(String dn) {
+ if (dn == null) {
+ return null;
+ } else {
+ StringBuffer sb = new StringBuffer();
+ String[] tmp = dn.split("(?= 0; --i) {
+ sb.append(tmp[i]);
+ if (i > 0) {
+ sb.append(",");
+ }
+ }
+
+ return sb.toString();
+ }
+ }
+
+ public static boolean isDNReversed(String dn) {
+ boolean ret = false;
+ if (dn != null) {
+ String first = null;
+ String last = null;
+ X509NameTokenizer xt = new X509NameTokenizer(dn);
+ if (xt.hasMoreTokens()) {
+ first = xt.nextToken();
+ }
+
+ while(xt.hasMoreTokens()) {
+ last = xt.nextToken();
+ }
+
+ if (first != null && last != null) {
+ first = first.substring(0, first.indexOf(61));
+ last = last.substring(0, last.indexOf(61));
+ int firsti = 0;
+ int lasti = 0;
+
+ for(int i = 0; i < dNObjects.length; ++i) {
+ if (first.toLowerCase().equals(dNObjectsForward[i])) {
+ firsti = i;
+ }
+
+ if (last.toLowerCase().equals(dNObjectsForward[i])) {
+ lasti = i;
+ }
+ }
+
+ if (lasti < firsti) {
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/util/NetSignAgentRes.java b/openapi-sdk/src/main/java/com/cisd/openapi/util/NetSignAgentRes.java
new file mode 100644
index 0000000..0783f9f
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/util/NetSignAgentRes.java
@@ -0,0 +1,629 @@
+package com.cisd.openapi.util;
+
+//
+//import cn.com.infosec.netsign.agent.communication.APIToServer;
+//import cn.com.infosec.netsign.agent.exception.NetSignAgentException;
+//import cn.com.infosec.netsign.agent.newcommunitor.CommunitorManager;
+//import cn.com.infosec.netsign.agent.service.NSService;
+//import cn.com.infosec.netsign.crypto.util.SoftCryptoImpl;
+//import cn.com.infosec.netsign.frame.config.ExtendedConfig;
+//import cn.com.infosec.netsign.logger.ConsoleLogger;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class NetSignAgentRes {
+ private static ResourceBundle resBundle = null;
+ static boolean hasDone = false;
+ private static int communicateMode = 1;
+ private static boolean zipMode = false;
+ private static int minZipSize = 200;
+ private static byte[] secKey = null;
+ private static byte[] keyHash = null;
+ private static byte[] encSecKey = null;
+ private static String clientId = null;
+ private static int seq = 0;
+ private static String encoding;
+ private static int orderDN = 0;
+ private static int snmode = 1;
+ public static final int CONNECTION_MODE_CONCENTRATE = 1;
+ public static final int CONNECTION_MODE_HASH = 2;
+ public static final int CONNECTION_MODE_ORDER = 3;
+ public static final int CONNECTION_MODE_POLLING = 4;
+ private static int connectionMode = 1;
+ private static boolean autoTest = false;
+ private static long testInterval = 30000L;
+ private static boolean logConnection = false;
+ private static boolean poolFlag = false;
+ private static int maxPoolSize = 20;
+ private static int retryTimes = 1;
+ private static int retryInterval = 500;
+ private static int encLock = 8;
+ private static int maxWorkingThread = -1;
+
+ static {
+ initNewConnectionParameters();
+ }
+
+ public static void initNewConnectionParameters() {
+ String str = System.getProperty("cn.com.infosec.netsign.agent.servicetest.interval");
+ if (str != null) {
+ try {
+ testInterval = Long.parseLong(str);
+ } catch (Exception var3) {
+ }
+ }
+
+ str = System.getProperty("cn.com.infosec.netsign.agent.servicetest.isautotest");
+ if (str != null) {
+ autoTest = str.equals("yes");
+ }
+
+ str = System.getProperty("cn.com.infosec.netsign.agent.connection.mode");
+ if (str != null) {
+ try {
+ connectionMode = Integer.parseInt(str);
+ } catch (Exception var2) {
+ }
+ }
+
+ }
+
+// static synchronized void initialize(ResourceBundle res) throws NetSignAgentException {
+// if (!hasDone) {
+// System.out.println("NetSignServerAPI initialize start...");
+// if (resBundle == null) {
+// resBundle = getResourceBundle(res);
+// }
+//
+// initConnections();
+// if (initPooledFlag().equals("true") && initHeartBeat()) {
+// if (APIToServer.timeout == 0) {
+// boolean var10000 = true;
+// } else {
+// int var4 = APIToServer.timeout / 2;
+// }
+// }
+//
+// long gc = initGC();
+// if (gc != 0L) {
+// AutoGC tgc = new AutoGC(gc);
+// tgc.start();
+// }
+//
+// clientId = initClientId();
+// communicateMode = initCommunicateMode();
+// zipMode = initZipMode();
+// if (zipMode) {
+// minZipSize = initMinZipSize();
+// }
+//
+// if (communicateMode == 0) {
+// initSecKey();
+// }
+//
+// encoding = initEncoding() != null && !"".equals(initEncoding()) ? initEncoding() : encoding;
+// if (encoding != null && !"".equals(encoding)) {
+// ExtendedConfig.setEncoding(encoding);
+// } else {
+// ExtendedConfig.setEncoding("GBK");
+// }
+//
+// orderDN = initOrderDN();
+// snmode = initSNMode();
+// hasDone = true;
+// encLock = initEncryptLock();
+// maxWorkingThread = initMaxParallelThread();
+// System.out.println("NetSignServerAPI initialize finished...");
+// }
+//
+// }
+
+ public static void setMaxWorkingThread(int count) {
+ maxWorkingThread = count;
+ }
+
+ public static int getMaxParallelThread() {
+ return maxWorkingThread;
+ }
+
+ public static int getEncLock() {
+ return encLock;
+ }
+
+ static int initMaxParallelThread() {
+ try {
+ String tmp = resBundle.getString("maxparallelthread");
+ return Integer.parseInt(tmp);
+ } catch (Exception var1) {
+ return maxWorkingThread;
+ }
+ }
+
+ static int initEncryptLock() {
+ try {
+ String tmp = resBundle.getString("encryptlock");
+ return Integer.parseInt(tmp);
+ } catch (Exception var1) {
+ return encLock;
+ }
+ }
+
+// static synchronized void initialize(NetSignService service) throws NetSignAgentException {
+// if (!hasDone) {
+// System.out.println("NetSignServerAPI initialize start...");
+// initConnections(service.getHost(), service.getPort(), service.getPoolSize(), service.getTimeout());
+// hasDone = true;
+// System.out.println("NetSignServerAPI initialize finished...");
+// }
+//
+// }
+//
+// private static String initServerIP() throws NetSignAgentException {
+// try {
+// return resBundle.getString("ServerIP").trim();
+// } catch (MissingResourceException var1) {
+// throw new NetSignAgentException("ServerIP can not be null");
+// }
+// }
+//
+// private static String initTimeout() throws NetSignAgentException {
+// try {
+// return resBundle.getString("Timeout").trim();
+// } catch (Exception var1) {
+// return "30000";
+// }
+// }
+//
+// private static String initConnectTimeout() throws NetSignAgentException {
+// try {
+// return resBundle.getString("ConnectTimeout").trim();
+// } catch (Exception var1) {
+// return "30000";
+// }
+// }
+//
+// private static String initServerPort() throws NetSignAgentException {
+// try {
+// return resBundle.getString("ServerPort").trim();
+// } catch (MissingResourceException var1) {
+// throw new NetSignAgentException("ServerPort can not be null");
+// }
+// }
+//
+// private static int initCommunicateMode() throws NetSignAgentException {
+// try {
+// return Integer.parseInt(resBundle.getString("CommunicateMode").trim());
+// } catch (MissingResourceException var1) {
+// throw new NetSignAgentException("CommunicateMode can not be null");
+// } catch (NumberFormatException var2) {
+// throw new NetSignAgentException("Invalid CommunicateMode value");
+// }
+// }
+//
+// private static String initMaxConnections() throws NetSignAgentException {
+// try {
+// String max = resBundle.getString("MaxConnections").trim();
+// maxPoolSize = Integer.parseInt(max);
+// return max;
+// } catch (MissingResourceException var1) {
+// maxPoolSize = 20;
+// return "20";
+// }
+// }
+//
+// private static boolean initZipMode() throws NetSignAgentException {
+// try {
+// return Boolean.valueOf(resBundle.getString("ZipMode").trim());
+// } catch (MissingResourceException var1) {
+// throw new NetSignAgentException("ZipMode can not be null");
+// }
+// }
+//
+// private static int initMinZipSize() throws NetSignAgentException {
+// try {
+// return 1024 * Integer.parseInt(resBundle.getString("MinZipSize").trim());
+// } catch (MissingResourceException var1) {
+// throw new NetSignAgentException("MinZipSize can not be null");
+// } catch (NumberFormatException var2) {
+// throw new NetSignAgentException("Invalid MinZipSize value");
+// }
+// }
+//
+// private static void initSecKey() throws NetSignAgentException {
+// String certFile = null;
+//
+// try {
+// certFile = resBundle.getString("ServerEncCert").trim();
+// } catch (MissingResourceException var17) {
+// throw new NetSignAgentException("ServerEncCert can not be null");
+// }
+//
+// FileInputStream in = null;
+//
+// try {
+// CertificateFactory factory = CertificateFactory.getInstance("X.509", "INFOSEC");
+// in = new FileInputStream(certFile);
+// System.out.println("comm cert:" + certFile + " length:" + in.available());
+// X509Certificate cert = (X509Certificate)factory.generateCertificate(in);
+// secKey = SoftCryptoImpl.genSecretKey(SoftCryptoImpl.RC4, 128);
+// keyHash = SoftCryptoImpl.hash("SHA1", secKey);
+// encSecKey = SoftCryptoImpl.encryptWithRSAPubkey(cert.getPublicKey(), secKey);
+// } catch (FileNotFoundException var14) {
+// throw new NetSignAgentException("Can not found cert file: " + certFile);
+// } catch (Exception ex) {
+// ConsoleLogger.logException(ex);
+// throw new NetSignAgentException("Generate SecKey Error: " + ex.getMessage());
+// } finally {
+// try {
+// if (in != null) {
+// in.close();
+// }
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+//
+// }
+//
+// }
+
+ private static String initClientId() {
+ try {
+ return resBundle.getString("ClientID").trim();
+ } catch (MissingResourceException var1) {
+ return null;
+ }
+ }
+
+ private static String initPooledFlag() {
+ try {
+ String flag = resBundle.getString("UsedConnectionPool").trim();
+ poolFlag = Boolean.valueOf(flag);
+ return flag;
+ } catch (Exception var1) {
+ poolFlag = false;
+ return "false";
+ }
+ }
+
+// private static void initConnections() throws NetSignAgentException {
+// initPooledFlag();
+// initMaxConnections();
+// initConnectTimeout();
+// initServiceTestIsTest();
+// initConnectionMode();
+// initConnectionLog();
+// initServiceTestInterval();
+// initRetryTimes();
+// initRetryInerval();
+// NetSignAgent.cm = new CommunitorManager(false);
+// String ip = initServerIP();
+// String port = initServerPort();
+// String timeout = initTimeout();
+// String[] ips = ip.split(",");
+// String[] ports = port.split(",");
+// String[] timeouts = timeout.split(",");
+//
+// for(int i = 0; i < ips.length; ++i) {
+// NSService s = new NSService();
+// s.setIp(ips[i].trim());
+// s.setPort(Integer.parseInt(ports[i].trim()));
+// s.setTimeout(Integer.parseInt(timeouts[i].trim()));
+// NetSignAgent.cm.addService(s);
+// }
+//
+// }
+
+ private static void initConnectionLog() {
+ try {
+ String str = resBundle.getString("logconnection");
+ if (str != null && (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("yes"))) {
+ logConnection = true;
+ }
+ } catch (Exception var1) {
+ }
+
+ }
+
+ private static void initRetryTimes() {
+ try {
+ String str = resBundle.getString("retrytimes");
+ if (str != null) {
+ retryTimes = Integer.parseInt(str);
+ }
+ } catch (Exception var1) {
+ }
+
+ }
+
+ private static void initRetryInerval() {
+ try {
+ String str = resBundle.getString("retryinterval");
+ if (str != null) {
+ retryInterval = Integer.parseInt(str);
+ }
+ } catch (Exception var1) {
+ }
+
+ }
+
+ private static void initServiceTestIsTest() {
+ try {
+ String str = resBundle.getString("servicetestistest");
+ if (str != null) {
+ autoTest = "yes".equals(str.toLowerCase()) || "true".equals(str.toLowerCase());
+ }
+ } catch (Exception var1) {
+ }
+
+ }
+
+ private static void initServiceTestInterval() {
+ try {
+ String str = resBundle.getString("servicetestinterval");
+ if (str != null) {
+ try {
+ testInterval = (long)Integer.parseInt(str);
+ } catch (Exception var2) {
+ }
+ }
+ } catch (Exception var3) {
+ }
+
+ }
+
+ private static void initConnectionMode() {
+ try {
+ String str = resBundle.getString("connectionmode");
+ connectionMode = Integer.parseInt(str);
+ } catch (Exception var1) {
+ }
+
+ if (connectionMode <= 0) {
+ connectionMode = 3;
+ }
+
+ }
+
+ private static boolean initHeartBeat() {
+ try {
+ String start = resBundle.getString("heartbeat").trim();
+ return start.equals("true");
+ } catch (Exception var1) {
+ return false;
+ }
+ }
+
+ private static long initGC() {
+ try {
+ String gc = resBundle.getString("gc").trim();
+ return Long.parseLong(gc);
+ } catch (Exception var1) {
+ return 60L;
+ }
+ }
+
+ private static String initEncoding() {
+ try {
+ return resBundle.getString("encoding").trim();
+ } catch (Exception var1) {
+ return null;
+ }
+ }
+
+ private static int initOrderDN() {
+ try {
+ return Integer.parseInt(resBundle.getString("orderdn"));
+ } catch (Exception var1) {
+ return 0;
+ }
+ }
+
+ private static int initSNMode() {
+ try {
+ return Integer.parseInt(resBundle.getString("snmode"));
+ } catch (Exception var1) {
+ return 1;
+ }
+ }
+
+// public static void initConnections(String ip, int port, int maxConns, int timeout) throws NetSignAgentException {
+// if (!hasDone) {
+// Properties p = new Properties();
+// p.setProperty("ip", ip);
+// p.setProperty("port", String.valueOf(port));
+// p.setProperty("pooled", "true");
+// if (maxConns < 1) {
+// maxConns = 50;
+// }
+//
+// p.setProperty("maxconn", String.valueOf(maxConns));
+// if (timeout < 1) {
+// timeout = 0;
+// }
+//
+// p.setProperty("timeout", String.valueOf(timeout));
+// APIToServer.initConnections(p);
+// hasDone = true;
+// }
+//
+// }
+//
+// public static void setClientId(String id) {
+// clientId = id;
+// }
+//
+// public static void setEncryptMode(String encCertFile) throws NetSignAgentException {
+// communicateMode = 0;
+// String certFile = encCertFile;
+//
+// try {
+// CertificateFactory factory = CertificateFactory.getInstance("X.509", "INFOSEC");
+// new File(certFile);
+// FileInputStream in = new FileInputStream(certFile);
+// X509Certificate cert = (X509Certificate)factory.generateCertificate(in);
+// in.close();
+// secKey = SoftCryptoImpl.genSecretKey(SoftCryptoImpl.RC4, 128);
+// keyHash = SoftCryptoImpl.hash("SHA1", secKey);
+// encSecKey = SoftCryptoImpl.encryptWithRSAPubkey(cert.getPublicKey(), secKey);
+// } catch (FileNotFoundException fileEx) {
+// fileEx.printStackTrace();
+// throw new NetSignAgentException("Can not found cert file: " + encCertFile);
+// } catch (Exception ex) {
+// ex.printStackTrace();
+// throw new NetSignAgentException("Generate SecKey Error: " + ex.getMessage());
+// }
+// }
+
+ public static void setZipMode(int zipSize) {
+ zipMode = true;
+ if (zipSize > 1) {
+ minZipSize = zipSize * 1024;
+ }
+
+ }
+
+ static String getClientId() {
+ return clientId;
+ }
+
+ static int getCommunicateMode() {
+ return communicateMode;
+ }
+
+ static boolean isZipMode() {
+ return zipMode;
+ }
+
+ static int getMinZipSize() {
+ return minZipSize;
+ }
+
+ static byte[] getSecKey() {
+ return secKey;
+ }
+
+ static byte[] getKeyHash() {
+ return keyHash;
+ }
+
+ static byte[] getEncSecKey() {
+ return encSecKey;
+ }
+
+ static int getOrderDN() {
+ return orderDN;
+ }
+
+ static int getSNMode() {
+ return snmode;
+ }
+
+ public static void setLogConnection(boolean on) {
+ logConnection = on;
+ }
+
+ public static boolean isLogConnection() {
+ return logConnection;
+ }
+
+ public static int getRetryTimes() {
+ return retryTimes;
+ }
+
+ public static int getRetryInterval() {
+ return retryInterval;
+ }
+
+ public static void setEncoding(String encoding) {
+ NetSignAgentRes.encoding = encoding;
+ }
+
+ public static boolean isUseConnectionPool() {
+ return poolFlag;
+ }
+
+ public static void setUseConnectionPool(boolean ispool) {
+ poolFlag = ispool;
+ }
+
+ public static int getMaxPoolSize() {
+ return maxPoolSize;
+ }
+
+ public static void setMaxPoolSize(int poolsize) {
+ maxPoolSize = poolsize;
+ }
+
+ public static void setAutoTest(boolean isautotest) {
+ autoTest = isautotest;
+ }
+
+ public static boolean isAutoTest() {
+ return autoTest;
+ }
+
+ public static void setConnectionMode(int mode) {
+ connectionMode = mode;
+ }
+
+ public static int getConnectionMode() {
+ return connectionMode;
+ }
+
+ public static void setTestInterval(long interval) {
+ testInterval = interval;
+ }
+
+ public static long getTestInterval() {
+ return testInterval;
+ }
+
+ static void setOrderDN(int orderdn) {
+ orderDN = orderdn;
+ }
+
+ static String getSeq() {
+ ++seq;
+ seq &= Integer.MAX_VALUE;
+ return String.valueOf(seq % 100000 + 100000).substring(1);
+ }
+
+ public static String getEncoding() {
+ return encoding;
+ }
+
+// private static ResourceBundle getResourceBundle(ResourceBundle res) throws NetSignAgentException {
+// ResourceBundle bundle = null;
+// System.out.println("vvvvvvvvvvvvvvvv NetSignAgent ENV vvvvvvvvvvvvvvvvv");
+//
+// try {
+// ClassLoader cl = ClassLoader.getSystemClassLoader();
+// URL[] urls = ((URLClassLoader)cl).getURLs();
+// if (urls != null) {
+// int i = 0;
+//
+// for(int length = urls.length; i < length; ++i) {
+// System.out.println(urls[i].getFile());
+// }
+// }
+// } catch (Throwable t) {
+// t.printStackTrace(System.out);
+// }
+//
+// System.out.println("^^^^^^^^^^^^^^^^^ NetSignAgent ENV ^^^^^^^^^^^^^^^^");
+//
+// try {
+// if (res != null) {
+// bundle = res;
+// } else {
+// bundle = ResourceBundle.getBundle("netsignagent");
+// }
+//
+// return bundle;
+// } catch (Exception miss1ex) {
+// miss1ex.printStackTrace(System.out);
+// throw new NetSignAgentException("Can not Found Config File netsignagent.properties");
+// }
+// }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/util/NetSignAgentUtil.java b/openapi-sdk/src/main/java/com/cisd/openapi/util/NetSignAgentUtil.java
new file mode 100644
index 0000000..258cda8
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/util/NetSignAgentUtil.java
@@ -0,0 +1,819 @@
+package com.cisd.openapi.util;
+
+//import cn.com.infosec.jce.provider.*;
+//import cn.com.infosec.jce.provider.fastparser.DerUtil;
+//import cn.com.infosec.jce.provider.fastparser.FastPkcs7;
+//import cn.com.infosec.jce.provider.fastparser.Item;
+//import cn.com.infosec.netsign.agent.exception.NetSignAgentException;
+//import cn.com.infosec.netsign.base.AbstractMessage;
+//import cn.com.infosec.netsign.base.NSMessage;
+//import cn.com.infosec.netsign.base.NSMessageOpt;
+//import cn.com.infosec.netsign.base.processors.util.GZipUtil;
+//import cn.com.infosec.netsign.crypto.util.Base64;
+//import cn.com.infosec.netsign.crypto.util.SoftCryptoImpl;
+//import cn.com.infosec.netsign.logger.ConsoleLogger;
+//import cn.com.infosec.netsign.pool.Pool;
+//import cn.com.infosec.netsign.pool.Poolable;
+//import cn.com.infosec.oscca.encryption.SM4CBC;
+//import cn.com.infosec.oscca.encryption.SM4ECB;
+//import cn.com.infosec.oscca.sm2.SM2PublicKey;
+
+import org.w3c.dom.Document;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class NetSignAgentUtil {
+ public static HashMap digestOIDName;
+// public static Pool encLockPool;
+
+// static {
+// if (Security.getProvider("INFOSEC") == null) {
+// Security.addProvider(new InfosecProvider());
+// }
+//
+// digestOIDName = new HashMap();
+// digestOIDName.put("1.3.14.3.2.26", "SHA1");
+// digestOIDName.put("1.2.840.113549.2.5", "MD5");
+// digestOIDName.put("1.2.840.113549.2.2", "MD2");
+// digestOIDName.put("2.16.840.1.101.3.4.2.4", "SHA224");
+// digestOIDName.put("2.16.840.1.101.3.4.2.1", "SHA256");
+// digestOIDName.put("2.16.840.1.101.3.4.2.2", "SHA384");
+// digestOIDName.put("2.16.840.1.101.3.4.2.3", "SHA512");
+// digestOIDName.put("1.2.840.113549.11.5", "SHA1");
+// digestOIDName.put("1.2.840.113549.1.1.11", "SHA256");
+// digestOIDName.put("1.2.156.197.1.401", "SM3");
+// digestOIDName.put("1.2.156.10197.1.401", "SM3");
+// digestOIDName.put("1.2.156.10197.1.501", "SM3");
+// digestOIDName.put("1.2.156.197.1.401.2", "SM3-2");
+// digestOIDName.put("1.2.156.10197.1.401.2", "SM3-2");
+// digestOIDName.put("1.2.156.197.1.401.1", "SM3-1");
+// digestOIDName.put("1.2.156.10197.1.401.1", "SM3-1");
+//
+// try {
+// encLockPool = new Pool("cn.com.infosec.netsign.pool.SamplePoolable", NetSignAgentRes.getEncLock(), (Object)null);
+// } catch (Exception e) {
+// e.printStackTrace(System.out);
+// }
+//
+// }
+
+// public static X509Certificate getCertificateFromP7(String p7b) {
+// return getCertificateFromP7(Base64.decode(p7b));
+// }
+
+// public static X509Certificate getCertificateFromP7(byte[] p7b) {
+// try {
+// FastPkcs7 fxPKCS7 = new FastPkcs7();
+// fxPKCS7.pkcs7SignedData(p7b);
+// Item signCertItem = fxPKCS7.getSignCert();
+// byte[] bsCert = DerUtil.getItemDataAndTag(p7b, signCertItem);
+// return new X509CertificateObjectFX(bsCert);
+// } catch (Exception e) {
+// e.printStackTrace(System.out);
+// return null;
+// }
+// }
+
+ public static byte[] xmlCanonical(byte[] xml) throws Exception {
+ ByteArrayInputStream in = null;
+ ByteArrayOutputStream out = null;
+
+ byte[] var11;
+ try {
+ in = new ByteArrayInputStream(xml);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.parse(in);
+ DOMSource domSource = new DOMSource(doc.getDocumentElement());
+ out = new ByteArrayOutputStream();
+ StreamResult result = new StreamResult(out);
+ Transformer tf = TransformerFactory.newInstance().newTransformer();
+ tf.transform(domSource, result);
+ var11 = out.toByteArray();
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (Exception var19) {
+ }
+
+ try {
+ if (out != null) {
+ out.close();
+ }
+ } catch (Exception var18) {
+ }
+
+ }
+
+ return var11;
+ }
+
+// public static String encode(byte[] bytes) {
+// return Base64.encode(bytes);
+// }
+//
+// public static byte[] decode(String text) throws NetSignAgentException {
+// try {
+// return Base64.decode(text);
+// } catch (Exception e) {
+// throw new NetSignAgentException(-1011, e.getMessage());
+// }
+// }
+//
+// public static NSMessage createMessage(String processor) {
+// NSMessage req = new NSMessage();
+// req.setType("request");
+// req.setProcessor(processor);
+// req.setClientId(NetSignAgentRes.getClientId());
+// return req;
+// }
+//
+// public static byte[] checkOrZip(byte[] bytes, NSMessage req) throws NetSignAgentException {
+// try {
+// new GZIPInputStream(new ByteArrayInputStream(bytes));
+// } catch (IOException e) {
+// if (!e.getMessage().toLowerCase().startsWith("not in gzip format")) {
+// throw new NetSignAgentException(-1014, e.getMessage());
+// }
+//
+// return checkAndZip(bytes, req);
+// }
+//
+// req.setZipMode(true);
+// return bytes;
+// }
+//
+// public static byte[] checkAndZip(byte[] bytes, NSMessage req) throws NetSignAgentException {
+// if (NetSignAgentRes.isZipMode() && bytes.length >= NetSignAgentRes.getMinZipSize()) {
+// req.setZipMode(true);
+//
+// try {
+// return GZipUtil.zip(bytes);
+// } catch (IOException var3) {
+// if (NetSignAgent.getDebugWriter() != null) {
+// NetSignAgent.getDebugWriter().println(new Date() + " Zip message failed, " + "the error code is " + -1012 + ", the error is " + var3.getMessage());
+// }
+//
+// throw new NetSignAgentException(-1012, var3.getMessage());
+// }
+// } else {
+// req.setZipMode(false);
+// return bytes;
+// }
+// }
+//
+// public static byte[] checkAndEncrypt(byte[] bytes, NSMessage req) throws NetSignAgentException {
+// if (NetSignAgentRes.getCommunicateMode() == 0) {
+// req.setCommunicateMode(0);
+// req.setEncKey(NetSignAgentRes.getEncSecKey());
+// req.setKeyHash(NetSignAgentRes.getKeyHash());
+//
+// try {
+// return SoftCryptoImpl.encrypt(SoftCryptoImpl.RC4, NetSignAgentRes.getSecKey(), bytes, (byte[])null);
+// } catch (Exception var3) {
+// if (NetSignAgent.getDebugWriter() != null) {
+// NetSignAgent.getDebugWriter().println(new Date() + " Encrypt message failed, " + "the error code is " + -1015 + ", the error is " + var3.getMessage());
+// }
+//
+// throw new NetSignAgentException(-1015, var3.getMessage());
+// }
+// } else {
+// req.setCommunicateMode(1);
+// return bytes;
+// }
+// }
+//
+// public static byte[] checkAndDecrypt(byte[] bytes, int commMode) throws NetSignAgentException {
+// if (commMode == 0) {
+// try {
+// return SoftCryptoImpl.decrypt(SoftCryptoImpl.RC4, NetSignAgentRes.getSecKey(), bytes, "12345678".getBytes());
+// } catch (Exception var3) {
+// if (NetSignAgent.getDebugWriter() != null) {
+// NetSignAgent.getDebugWriter().println(new Date() + " Decrypt message failed, " + "the error code is " + -1016 + ", the error is " + var3.getMessage());
+// }
+//
+// throw new NetSignAgentException(-1016, var3.getMessage());
+// }
+// } else {
+// return bytes;
+// }
+// }
+//
+// public static byte[] checkAndUnzip(byte[] bytes, boolean isZipped) throws NetSignAgentException {
+// if (!isZipped) {
+// return bytes;
+// } else {
+// try {
+// return GZipUtil.unzip(bytes);
+// } catch (IOException var3) {
+// if (NetSignAgent.getDebugWriter() != null) {
+// NetSignAgent.getDebugWriter().println(new Date() + " Unzip message failed, " + "the error code is " + -1013 + ", the error is " + var3.getMessage());
+// }
+//
+// throw new NetSignAgentException(-1013, var3.getMessage());
+// }
+// }
+// }
+//
+// public static void checkAndSetTSA(String tsaText, NSMessage req) throws NetSignAgentException {
+// if (tsaText == null) {
+// req.setUsedTSA(false);
+// } else {
+// req.setUsedTSA(true);
+// req.setTSAText(decode(tsaText));
+// }
+//
+// }
+//
+// public static NetSignResult attachedVerifyResult(NSMessageOpt res) throws NetSignAgentException {
+// Map map = new HashMap();
+// byte[] plainText = checkAndDecrypt(res.getPlainText(), res.getCommunicateMode());
+// plainText = checkAndUnzip(plainText, res.isZipMode());
+// map.put("Result_Num", String.valueOf(res.getResult()));
+// map.put("Byte_Array_Plain_Text", plainText);
+// if (res.isTransCert()) {
+// map.put("X509Certificate_Sign_Cert", res.getCert());
+// }
+//
+// if (res.getDigestAlg() != null) {
+// map.put("DIGEST_ALG", res.getDigestAlg());
+// }
+//
+// map.put("Sign_Subject", res.getSignSubject());
+// map.put("Sign_Ser_Number", res.getSignSerNumber());
+// map.put("Sign_Issuer_Subject", res.getSignIssuerSubject());
+// map.put("Sign_Start_Time", res.getSignStartTime());
+// map.put("Sign_End_Time", res.getSignEndtime());
+// if (res.getSignCertType() != null) {
+// map.put("Sign_Cert_Type", res.getSignCertType());
+// }
+//
+// if (res.getUsedTSA()) {
+// map.put("TSA_Gen_Time", res.getTSAGenerateTime());
+// }
+//
+// return new NetSignResult(map);
+// }
+//
+// public static ArrayList pdfVerifyResult(NSMessageOpt res) {
+// return res.getPDFVerifyResults();
+// }
+//
+// public static ArrayList xmlVerifyResult(NSMessageOpt res) {
+// return res.getXmlVerifyResults();
+// }
+//
+// public static NetSignResult detachedVerifyResult(NSMessageOpt res) {
+// Map map = new HashMap();
+// if (res.isTransCert()) {
+// map.put("X509Certificate_Sign_Cert", res.getCert());
+// }
+//
+// if (res.getDigestAlg() != null) {
+// map.put("DIGEST_ALG", res.getDigestAlg());
+// }
+//
+// map.put("Sign_Subject", res.getSignSubject());
+// map.put("Sign_Ser_Number", res.getSignSerNumber());
+// map.put("Sign_Issuer_Subject", res.getSignIssuerSubject());
+// map.put("Sign_Start_Time", res.getSignStartTime());
+// map.put("Sign_End_Time", res.getSignEndtime());
+// if (res.getSignCertType() != null) {
+// map.put("Sign_Cert_Type", res.getSignCertType());
+// }
+//
+// if (res.getUsedTSA()) {
+// map.put("TSA_Gen_Time", res.getTSAGenerateTime());
+// }
+//
+// return new NetSignResult(map);
+// }
+//
+// public static NetSignResult TSASigVerifyResult(NSMessageOpt res) {
+// Map map = new HashMap();
+// map.put("TSA_Gen_Time", res.getTSAGenerateTime());
+// return new NetSignResult(map);
+// }
+//
+// public static NetSignResult rawVerifyResult(NSMessageOpt res) {
+// Map map = new HashMap();
+// if (res.getUsedTSA()) {
+// map.put("TSA_Gen_Time", res.getTSAGenerateTime());
+// }
+//
+// if (res.getDigestAlg() != null) {
+// map.put("DIGEST_ALG", res.getDigestAlg());
+// }
+//
+// if (res.getProcessor().equals("PBCRAWVerifyProcessor")) {
+// map.put("Sign_Subject", res.getSignSubject());
+// map.put("Sign_Ser_Number", res.getSignSerNumber());
+// map.put("Sign_Issuer_Subject", res.getSignIssuerSubject());
+// map.put("Sign_Start_Time", res.getSignStartTime());
+// map.put("Sign_End_Time", res.getSignEndtime());
+// }
+//
+// return new NetSignResult(map);
+// }
+//
+// public static NetSignResult signatureResult(NSMessage res) throws NetSignAgentException {
+// Map map = new HashMap();
+// byte[] signText = checkAndDecrypt(res.getCryptoText(), res.getCommunicateMode());
+// signText = checkAndUnzip(signText, res.isZipMode());
+// map.put("Base64_Signed_Text", signText);
+// if (res.getUsedTSA()) {
+// map.put("Base64_TSA_Text", res.getTSAText());
+// }
+//
+// return new NetSignResult(map);
+// }
+//
+// public static NetSignResult xmlSignatureResult(NSMessage res) throws NetSignAgentException {
+// Map map = new HashMap();
+// byte[] signText = checkAndDecrypt(res.getCryptoText(), res.getCommunicateMode());
+// signText = checkAndUnzip(signText, res.isZipMode());
+// map.put("Base64_Signed_Text", signText);
+// map.put("Signature_Id", res.getXmlSigID());
+// if (res.getUsedTSA()) {
+// map.put("Base64_TSA_Text", res.getTSAText());
+// }
+//
+// return new NetSignResult(map);
+// }
+//
+// public static NetSignResult pdfEncryptResult(NSMessage res) throws NetSignAgentException {
+// Map map = new HashMap();
+// map.put("Pdf_Encrypt_Text", res.getCryptoText());
+// return new NetSignResult(map);
+// }
+//
+// public static NetSignResult pdfSignatureResult(NSMessage res) throws NetSignAgentException {
+// Map map = new HashMap();
+// map.put("Base64_Signed_Text", res.getCryptoText());
+// return new NetSignResult(map);
+// }
+//
+// public static NetSignResult envelopeResult(NSMessage res) throws NetSignAgentException {
+// Map map = new HashMap();
+// byte[] cryptoText = checkAndUnzip(res.getCryptoText(), res.isZipMode());
+// map.put("Base64_Enveloped_Text", cryptoText);
+// return new NetSignResult(map);
+// }
+//
+// public static NetSignResult decryptEnvelopeResult(NSMessageOpt res) throws NetSignAgentException {
+// Map map = new HashMap();
+// byte[] plainText = checkAndDecrypt(res.getPlainText(), res.getCommunicateMode());
+// plainText = checkAndUnzip(plainText, res.isZipMode());
+// map.put("Byte_Array_Plain_Text", plainText);
+// map.put("Enc_Subject", res.getEncSubject());
+// map.put("Enc_Ser_Number", res.getEncSerNumber());
+// map.put("Enc_Issuer_Subject", res.getEncIssuerSubject());
+// map.put("Enc_Start_Time", res.getEncStartTime());
+// map.put("Enc_End_Time", res.getEncEndtime());
+// if (res.getDigestAlg() != null) {
+// map.put("DIGEST_ALG", res.getDigestAlg());
+// }
+//
+// if (res.getSymmetricalAlg() != null) {
+// map.put("Enc_Alg", res.getSymmetricalAlg());
+// }
+//
+// if (res.getSignSubject() != null) {
+// map.put("Sign_Subject", res.getSignSubject());
+// map.put("Sign_Ser_Number", res.getSignSerNumber());
+// map.put("Sign_Issuer_Subject", res.getSignIssuerSubject());
+// map.put("Sign_Start_Time", res.getSignStartTime());
+// map.put("Sign_End_Time", res.getSignEndtime());
+// }
+//
+// return new NetSignResult(map);
+// }
+//
+// public static PublicKey transpublickey(PublicKey pubkey) throws NetSignAgentException {
+// try {
+// if (!(pubkey instanceof JCERSAPublicKey) && !(pubkey instanceof JCESM2PublicKey) && !(pubkey instanceof SM2PublicKey)) {
+// RSAPublicKey rsapbkey = (RSAPublicKey)pubkey;
+// return KeyFactory.getInstance("RSA", "INFOSEC").generatePublic(new RSAPublicKeySpec(rsapbkey.getModulus(), rsapbkey.getPublicExponent()));
+// } else {
+// return pubkey;
+// }
+// } catch (Exception ex) {
+// throw new NetSignAgentException(ex.getMessage());
+// }
+// }
+//
+// public static X509Certificate transcertificate(X509Certificate cert) throws NetSignAgentException {
+// try {
+// if (cert instanceof X509CertificateObject) {
+// return cert;
+// } else {
+// ByteArrayInputStream binput = new ByteArrayInputStream(cert.getEncoded());
+// return (X509Certificate)CertificateFactory.getInstance("X.509", "INFOSEC").generateCertificate(binput);
+// }
+// } catch (Exception ex) {
+// throw new NetSignAgentException(ex.getMessage());
+// }
+// }
+//
+// public static void debug(String msg, AbstractMessage am) {
+// if (NetSignAgent.getDebugWriter() != null) {
+// NetSignAgent.getDebugWriter().println(msg + (am != null ? am.getString() : ""));
+// }
+//
+// }
+
+ public static String getDN(String dn) {
+ if (dn != null && !dn.equals("")) {
+ switch (NetSignAgentRes.getOrderDN()) {
+ case 0:
+ return dn;
+ case 1:
+ if (DNItemReverseUtil.isDNReversed(dn)) {
+ return DNItemReverseUtil.reverse(dn);
+ }
+
+ return dn;
+ case 2:
+ if (!dn.startsWith("CN=") && !dn.startsWith("cn=")) {
+ return dn;
+ }
+
+ return turnDNString(dn);
+ default:
+ return dn;
+ }
+ } else {
+ return dn;
+ }
+ }
+
+ public static boolean compareDN(String srcDN, String destDN) {
+ srcDN = removeTrans(srcDN);
+ String temp = turnDNString(srcDN);
+ destDN = removeTrans(destDN);
+ return srcDN.equals(destDN) || temp.equals(destDN);
+ }
+
+ public static String turnDNString(String dn) {
+ String[] temp = dn.split(",\\w+=");
+ String turnDN = "";
+ List temp2 = new ArrayList();
+ String s = ",\\w+=";
+ Pattern pat = Pattern.compile(s);
+ Matcher mat = pat.matcher(dn);
+
+ while(mat.find()) {
+ temp2.add(mat.group(0).substring(1));
+ }
+
+ int j = temp2.size() - 1;
+
+ for(int i = temp.length - 1; i > 0; --i) {
+ if (j >= 0) {
+ turnDN = turnDN + temp2.get(j) + temp[i].trim() + ",";
+ --j;
+ }
+ }
+
+ turnDN = turnDN + temp[0];
+ return turnDN;
+ }
+
+ public static String removeTrans(String rawStr) {
+ rawStr = rawStr.trim();
+ rawStr = rawStr.replace("\\\\", "#");
+ rawStr = rawStr.replace("\\", "");
+ rawStr = rawStr.replace("#", "\\");
+ return rawStr;
+ }
+
+// public static NetSignResult barcodeResult(NSMessageOpt res) throws NetSignAgentException {
+// Map map = new HashMap();
+// map.put("BarCode_Symbology", res.getBcSymbology());
+// return new NetSignResult(map);
+// }
+
+// public static byte[] digest(byte[] msg, String alg) {
+// try {
+// MessageDigest md = MessageDigest.getInstance(alg, "INFOSEC");
+// return md.digest(msg);
+// } catch (Exception e) {
+// ConsoleLogger.logException(e);
+// return null;
+// }
+// }
+
+ public static byte[] getSignatureInPKCS7(byte[] p7, X509Certificate cert) {
+ PublicKey k = cert.getPublicKey();
+ if (k instanceof RSAPublicKey) {
+ RSAPublicKey rsaK = (RSAPublicKey)k;
+ int keyLength = rsaK.getModulus().bitLength() / 8;
+ byte[] signed = new byte[keyLength];
+ System.arraycopy(p7, p7.length - keyLength, signed, 0, keyLength);
+ return signed;
+ } else {
+ int i = p7.length - 64;
+ byte[] signed = (byte[])null;
+
+ for(boolean matched = false; i > 0; --i) {
+ if (p7[i] == 4) {
+ int l = 0;
+ if (p7[i + 1] == 81) {
+ l = 255 & p7[i + 2];
+ if (i + 2 + l == p7.length) {
+ matched = true;
+ }
+ } else {
+ l = 255 & p7[i + 1];
+ if (i + 1 + l == p7.length) {
+ matched = true;
+ }
+ }
+
+ if (matched) {
+ signed = new byte[l];
+ System.arraycopy(p7, p7.length - l, signed, 0, l);
+ return signed;
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+
+
+
+ public static String dealSN(String sn) {
+ switch (NetSignAgentRes.getSNMode()) {
+ case 1:
+ sn = sn.length() % 2 == 0 ? sn : "0" + sn;
+ return sn;
+ case 2:
+ BigInteger snbi = new BigInteger(sn, 16);
+ return snbi.toString(10);
+ default:
+ return sn;
+ }
+ }
+
+ public static byte[] catText4TransValue(byte[][] text) {
+ int segLength = text.length;
+ byte[] buf = getDataLength(segLength);
+
+ for(int i = 0; i < text.length; ++i) {
+ byte[] tmp = new byte[buf.length + 4 + text[i].length];
+ System.arraycopy(buf, 0, tmp, 0, buf.length);
+ System.arraycopy(getDataLength(text[i].length), 0, tmp, buf.length, 4);
+ System.arraycopy(text[i], 0, tmp, buf.length + 4, text[i].length);
+ buf = tmp;
+ }
+
+ return buf;
+ }
+
+ public static byte[][] splitTextFromTransValue(byte[] value) {
+ byte[] intBs = new byte[4];
+ System.arraycopy(value, 0, intBs, 0, 4);
+ int segCount = bytes2Int(intBs, false);
+ int pos = 4;
+ byte[][] values = new byte[segCount][];
+
+ for(int i = 0; i < segCount; ++i) {
+ System.arraycopy(value, pos, intBs, 0, 4);
+ int segLen = bytes2Int(intBs, false);
+ byte[] tmp = new byte[segLen];
+ System.arraycopy(value, pos + 4, tmp, 0, segLen);
+ values[i] = tmp;
+ pos = pos + 4 + segLen;
+ }
+
+ return values;
+ }
+
+ public static byte[] getDataLength(int intLen) {
+ byte[] result = new byte[4];
+ result[0] = (byte)(255 & intLen >> 24);
+ result[1] = (byte)(255 & intLen >> 16);
+ result[2] = (byte)(255 & intLen >> 8);
+ result[3] = (byte)(255 & intLen >> 0);
+ return result;
+ }
+
+ public static int bytes2Int(byte[] bytes, boolean desc) {
+ if (bytes == null) {
+ return 0;
+ } else {
+ if (bytes.length < 4) {
+ byte[] tmp = new byte[4];
+ if (!desc) {
+ System.arraycopy(bytes, 0, tmp, 4 - bytes.length, bytes.length);
+ } else {
+ System.arraycopy(bytes, 0, tmp, 0, bytes.length);
+ }
+
+ bytes = tmp;
+ }
+
+ return !desc ? bytes[0] << 24 | bytes[1] << 16 & 16711680 | bytes[2] << 8 & '\uff00' | bytes[3] & 255 : bytes[3] << 24 | bytes[2] << 16 & 16711680 | bytes[1] << 8 & '\uff00' | bytes[0] & 255;
+ }
+ }
+
+// public static byte[] symmCipherSM4(byte[] plain, byte[] key, byte[] iv, int cipherMod) throws Exception {
+// byte[] cipher = (byte[])null;
+// if (iv == null) {
+// SM4ECB sm4 = new SM4ECB(cipherMod);
+// sm4.init(key);
+// sm4.update(plain);
+// cipher = sm4.doFinal();
+// } else {
+// SM4CBC sm4 = new SM4CBC(cipherMod);
+// sm4.init(key, iv);
+// sm4.update(plain);
+// cipher = sm4.doFinal();
+// }
+//
+// return cipher;
+// }
+
+ public static byte[] symmCipher(byte[] plain, byte[] key, byte[] iv, String alg, String mod, int cipherMod) throws Exception {
+ SecretKey sk = new SecretKeySpec(key, alg);
+ IvParameterSpec ivp = null;
+ if (iv != null) {
+ ivp = new IvParameterSpec(iv);
+ }
+
+ if (mod != null) {
+ alg = alg + mod;
+ }
+
+ Cipher c = Cipher.getInstance(alg);
+ if (ivp != null) {
+ c.init(cipherMod, sk, ivp);
+ } else {
+ c.init(cipherMod, sk);
+ }
+
+ return c.doFinal(plain);
+ }
+
+// public static void symmCipherSM4(InputStream in, OutputStream out, byte[] key, byte[] iv, int cipherMod) throws Exception {
+// if (iv == null) {
+// SM4ECB sm4 = new SM4ECB(cipherMod);
+// sm4.init(key);
+// Poolable lock = encLockPool.getObject();
+//
+// try {
+// int readed;
+// for(int left = in.available(); left > 0; left -= readed) {
+// byte[] buf = (byte[])null;
+// buf = new byte[10485760];
+// readed = in.read(buf);
+// byte[] cipher = sm4.update(buf, 0, readed);
+// if (cipher != null) {
+// out.write(cipher);
+// out.flush();
+// }
+// }
+//
+// byte[] cipher = sm4.doFinal();
+// if (cipher != null) {
+// out.write(cipher);
+// out.flush();
+// }
+// } finally {
+// encLockPool.freeObject(lock);
+// }
+// } else {
+// SM4CBC sm4 = new SM4CBC(cipherMod);
+// sm4.init(key, iv);
+// Poolable lock = encLockPool.getObject();
+//
+// try {
+// int readed;
+// for(int left = in.available(); left > 0; left -= readed) {
+// byte[] buf = (byte[])null;
+// buf = new byte[10485760];
+// readed = in.read(buf);
+// byte[] cipher = sm4.update(buf, 0, readed);
+// if (cipher != null) {
+// out.write(cipher);
+// out.flush();
+// }
+// }
+//
+// byte[] cipher = sm4.doFinal();
+// if (cipher != null) {
+// out.write(cipher);
+// out.flush();
+// }
+// } finally {
+// encLockPool.freeObject(lock);
+// }
+// }
+//
+// }
+//
+// public static void symmCipher(InputStream in, OutputStream out, byte[] key, byte[] iv, String alg, String mod, int cipherMod) throws Exception {
+// SecretKey sk = new SecretKeySpec(key, alg);
+// IvParameterSpec ivp = null;
+// if (iv != null) {
+// ivp = new IvParameterSpec(iv);
+// }
+//
+// if (mod != null) {
+// alg = alg + mod;
+// }
+//
+// Cipher c = Cipher.getInstance(alg, "INFOSEC");
+// if (ivp != null) {
+// c.init(cipherMod, sk, ivp);
+// } else {
+// c.init(cipherMod, sk);
+// }
+//
+// Poolable lock = encLockPool.getObject();
+//
+// try {
+// int readed;
+// for(int left = in.available(); left > 0; left -= readed) {
+// byte[] buf = (byte[])null;
+// buf = new byte[10485760];
+// readed = in.read(buf);
+// byte[] cipher = c.update(buf, 0, readed);
+// if (cipher != null) {
+// out.write(cipher);
+// out.flush();
+// }
+// }
+//
+// byte[] cipher = c.doFinal();
+// if (cipher != null) {
+// out.write(cipher);
+// out.flush();
+// }
+// } finally {
+// encLockPool.freeObject(lock);
+// }
+//
+// }
+//
+// public static PublicKey getRSAPublicKey(byte[] pubkey) throws NetSignAgentException {
+// try {
+// X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubkey);
+// PublicKey publicKey = null;
+//
+// try {
+// KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+// publicKey = keyFactory.generatePublic(keySpec);
+// } catch (Exception var5) {
+// }
+//
+// try {
+// KeyFactory keyFactory = KeyFactory.getInstance("EC");
+// publicKey = keyFactory.generatePublic(keySpec);
+// } catch (Exception var4) {
+// }
+//
+// if (publicKey == null) {
+// throw new NetSignAgentException("Parse PublicKey error");
+// } else {
+// return publicKey;
+// }
+// } catch (Exception var6) {
+// throw new NetSignAgentException("Parse PublicKey error");
+// }
+// }
+
+// public static void main(String[] args) {
+// String signed = "MIIDyQYKKoEcz1UGAQQCAqCCA7kwggO1AgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICujCCArYwggJaoAMCAQICBRACiTiTMAwGCCqBHM9VAYN1BQAwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0ExMB4XDTE2MDcxMTAzMTUwMVoXDTIwMDcwMTE1NTk1OVowejELMAkGA1UEBhMCY24xFTATBgNVBAoMDENGQ0EgVEVTVCBDQTEOMAwGA1UECwwFQ05BUFMxFDASBgNVBAsMC0VudGVycHJpc2VzMS4wLAYDVQQDDCUwNDFAWjMxMzY1NjAwMDAxOUBTTTJfUFpIQ0NCQDAwMDAwMDAzMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE0WPSq0X/BlYXzyD0YurRI1QuFSdTGizsFZyzXD+CaQkqV2m6IOZ+7ysS6ZCiiiVG86t/eF0PtgfQxBE+3OkEZqOB6DCB5TAfBgNVHSMEGDAWgBRr/hjaj0I6prhtsy6Igzo0osEw4TBIBgNVHSAEQTA/MD0GCGCBHIbvKgEBMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTQuaHRtMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly91Y3JsLmNmY2EuY29tLmNuL1NNMi9jcmw5NzguY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU9PijS0jFNf8Cjs6cXVPzn0lnmB0wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYIKoEcz1UBg3UFAANIADBFAiEAyRdXAXsIYZTlhcud5qrkwQLHRIUgNXKtMtaoZUY4PQMCIC5+K7LliVsIPevXTlrzAbCCFatj2a/zcAe6foUn6vn8MYHTMIHQAgEBMGUwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0ExAgUQAok4kzAMBggqgRzPVQGDEQUAMA0GCSqBHM9VAYItAQUABEcwRQIhAM9S65Xki2vqDA5W9YNMBpCXpfTh9AM7yvx1xi/tgS4YAiAxYnDZ4HchdOS8OYSDQwONAefRsGuHijuVCl/WH4KdUA==";
+// X509Certificate cert = getCertificateFromP7(signed);
+// System.out.println("证书DN:" + cert.getSubjectDN().getName() + "\n证书有效期起始日:" + cert.getNotBefore() + "\n证书有效期结束日期:" + cert.getNotAfter() + "\n证书SN:" + cert.getSerialNumber().toString(16) + "\n公钥算法:" + cert.getPublicKey().getAlgorithm() + "\n证书公钥:" + Base64.encode(cert.getPublicKey().getEncoded()) + "\n");
+// }
+
+// public static String[] genKeyPairResult(NSMessage res) throws NetSignAgentException {
+// return (new String(checkAndDecrypt(res.getCryptoText(), res.getCommunicateMode()))).split(":");
+// }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/util/PBCUtil.java b/openapi-sdk/src/main/java/com/cisd/openapi/util/PBCUtil.java
new file mode 100644
index 0000000..fa31534
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/util/PBCUtil.java
@@ -0,0 +1,27 @@
+package com.cisd.openapi.util;
+
+public class PBCUtil {
+ public static String getBankID(String dn) {
+ try {
+ String cn = "";
+ String[] pieces = dn.split(",");
+ int i = 0;
+
+ for(int length = pieces.length; i < length; ++i) {
+ if (pieces[i].toUpperCase().indexOf("CN=") > -1) {
+ cn = pieces[i].substring(pieces[i].indexOf("=") + 1);
+ }
+ }
+
+ if (cn.indexOf("@") > -1) {
+ pieces = cn.split("@");
+ String tmp = pieces[1];
+ return tmp.substring(1);
+ } else {
+ return cn;
+ }
+ } catch (Exception var5) {
+ return null;
+ }
+ }
+}
diff --git a/openapi-sdk/src/main/java/com/cisd/openapi/util/X509NameTokenizer.java b/openapi-sdk/src/main/java/com/cisd/openapi/util/X509NameTokenizer.java
new file mode 100644
index 0000000..8d55bed
--- /dev/null
+++ b/openapi-sdk/src/main/java/com/cisd/openapi/util/X509NameTokenizer.java
@@ -0,0 +1,68 @@
+package com.cisd.openapi.util;
+
+
+public class X509NameTokenizer {
+ private String value;
+ private int index;
+ private char seperator;
+ private StringBuffer buf;
+
+ public X509NameTokenizer(String oid) {
+ this(oid, ',');
+ }
+
+ public X509NameTokenizer(String oid, char seperator) {
+ this.buf = new StringBuffer();
+ this.value = oid;
+ this.index = -1;
+ this.seperator = seperator;
+ }
+
+ public boolean hasMoreTokens() {
+ return this.index != this.value.length();
+ }
+
+ public String nextToken() {
+ if (this.index == this.value.length()) {
+ return null;
+ } else {
+ int end = this.index + 1;
+ boolean quoted = false;
+ boolean escaped = false;
+ this.buf.setLength(0);
+
+ for(; end != this.value.length(); ++end) {
+ char c = this.value.charAt(end);
+ if (c == '"') {
+ if (!escaped) {
+ quoted = !quoted;
+ } else {
+ this.buf.append(c);
+ }
+
+ escaped = false;
+ } else if (!escaped && !quoted) {
+ if (c == '\\') {
+ escaped = true;
+ } else {
+ if (c == this.seperator) {
+ break;
+ }
+
+ this.buf.append(c);
+ }
+ } else {
+ if (c == '#' && this.buf.charAt(this.buf.length() - 1) == '=') {
+ this.buf.append('\\');
+ }
+
+ this.buf.append(c);
+ escaped = false;
+ }
+ }
+
+ this.index = end;
+ return this.buf.toString().trim();
+ }
+ }
+}
diff --git a/openapi-sdk/src/main/resources/application.yml b/openapi-sdk/src/main/resources/application.yml
new file mode 100644
index 0000000..a232468
--- /dev/null
+++ b/openapi-sdk/src/main/resources/application.yml
@@ -0,0 +1,13 @@
+server:
+ port: 8680
+
+sign-server:
+ base-url: http://172.1.41.249:8080/api/v1/openapi
+ api-key:
+ raw-sign-path: /rawSign
+ raw-verify-path: /rawVerify
+ dettached-sign-path: /dettachedSign
+ dettached-verify-path: /dettachedVerify
+ dettached-verify-simple-path: /dettachedVerifySimple
+ upload-cert-path: /uploadCert
+ last-return-code-path: /lastReturnCode
diff --git a/openapi-sdk/src/test/java/com/cisd/openapi/SignClientTest.java b/openapi-sdk/src/test/java/com/cisd/openapi/SignClientTest.java
new file mode 100644
index 0000000..e13e403
--- /dev/null
+++ b/openapi-sdk/src/test/java/com/cisd/openapi/SignClientTest.java
@@ -0,0 +1,90 @@
+package com.cisd.openapi;
+
+import com.cisd.openapi.dto.GenericCertificate;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+import java.io.FileInputStream;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+@SpringBootTest
+@ActiveProfiles("test")
+class SignClientTest {
+
+ @Autowired
+ private SignClient signClient;
+
+ private final byte[] origBytes = "11111111".getBytes();
+ private final String dn = "C=CN,ST=Beijing,L=Beijing,O=Initial Org,OU=Initial OU,CN=Initial Entity";
+
+
+ @Test
+ void testRawSign() {
+ String signature = signClient.rawSign(origBytes, dn);
+ System.out.println("rawSign: " + signature);
+ }
+
+ @Test
+ void testRawVerify() {
+ String signature = signClient.rawSign(origBytes, dn);
+ boolean verified = signClient.rawVerify(origBytes, signature, dn);
+ System.out.println("rawVerify: " + verified);
+ }
+
+ @Test
+ void testDettachedSign() {
+ String dettachedSig = signClient.dettachedSign(origBytes, dn);
+ System.out.println("dettachedSign: " + dettachedSig);
+ }
+
+
+
+
+ @Test
+ void testDettachedVerify() {
+ String dettachedSignature = signClient.dettachedSign(origBytes, dn);
+ GenericCertificate cert = signClient.dettachedVerify(origBytes, dettachedSignature);
+ System.out.println("dettachedVerify 证书主题: " + cert.getSubject());
+ }
+
+
+ @Test
+ void testDettachedVerifySimple() {
+ String dettachedSig = signClient.dettachedSign(origBytes, dn);
+ GenericCertificate cert = signClient.dettachedVerifySimple(origBytes, dettachedSig);
+ System.out.println("dettachedVerifySimple 证书主题: " + cert.getSubject());
+ }
+
+
+ @Test
+ void testUploadCert() throws Exception {
+ String certFilePath = "path";
+ X509Certificate certificate;
+ try {
+ certificate = loadCertificate(certFilePath);
+ } catch (Exception e) {
+ System.out.println("加载失败" + certFilePath);
+ return;
+ }
+ boolean success = signClient.uploadCert("bankCode", certificate);
+ System.out.println("uploadCert : " + success);
+ }
+
+
+ @Test
+ void testLastReturnCode() {
+ Integer code = signClient.lastReturnCode();
+ System.out.println("lastReturnCode: " + code);
+ }
+
+
+ private X509Certificate loadCertificate(String filePath) throws Exception {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ try (FileInputStream fis = new FileInputStream(filePath)) {
+ return (X509Certificate) cf.generateCertificate(fis);
+ }
+ }
+}
\ No newline at end of file
diff --git a/openapi-sdk/src/test/resources/application-test.yml b/openapi-sdk/src/test/resources/application-test.yml
new file mode 100644
index 0000000..a51b191
--- /dev/null
+++ b/openapi-sdk/src/test/resources/application-test.yml
@@ -0,0 +1,10 @@
+sign-server:
+ base-url: http://172.1.41.249:8080/api/v1/openapi
+ api-key:
+ raw-sign-path: /rawSign
+ raw-verify-path: /rawVerify
+ dettached-sign-path: /dettachedSign
+ dettached-verify-path: /dettachedVerify
+ dettached-verify-simple-path: /dettachedVerifySimple
+ upload-cert-path: /uploadCert
+ last-return-code-path: /lastReturnCode
\ No newline at end of file