first commit

This commit is contained in:
Cheney 2024-11-05 16:48:28 +08:00
commit a877436fcc
16 changed files with 1403 additions and 0 deletions

9
.gitattributes vendored Normal file
View File

@ -0,0 +1,9 @@
# auto generated by UGit
translog filter=lfs diff=lfs merge=binary -text
*.zip filter=lfs diff=lfs merge=binary -text
*.pdf filter=lfs diff=lfs merge=binary -text
*.so filter=lfs diff=lfs merge=binary -text
*.jar filter=lfs diff=lfs merge=binary -text
*.o filter=lfs diff=lfs merge=binary -text
*.dll filter=lfs diff=lfs merge=binary -text
*.doc filter=lfs diff=lfs merge=binary -text

40
.gitignore vendored Normal file
View File

@ -0,0 +1,40 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
SydLog
.idea

10
README.md Normal file
View File

@ -0,0 +1,10 @@
# sdf1102
java 对接 三合一版本加密机 SDF 接口封装
## 注意
git 自动转换回车会导致动态库错误。执行命令关闭自动转换。
```
git config --global core.autocrlf false
```

122
dependency-reduced-pom.xml Normal file
View File

@ -0,0 +1,122 @@
<?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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sunyard</groupId>
<artifactId>sdf1102</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<finalName>${project.artifactId}-${project.version}</finalName>
<transformers>
<transformer>
<mainClass>com.sunyard.security.Main</mainClass>
</transformer>
<transformer>
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer>
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer>
<resource>META-INF/spring.tooling</resource>
</transformer>
<transformer>
<projectName>Apache CXF</projectName>
</transformer>
<transformer>
<resource>META-INF/cxf/cxf.extension</resource>
</transformer>
<transformer>
<resource>META-INF/extensions.xml</resource>
</transformer>
<transformer>
<resource>META-INF/cxf/extensions.xml</resource>
</transformer>
<transformer>
<resource>META-INF/cxf/bus-extensions.txt</resource>
</transformer>
<transformer>
<resource>META-INF/cxf/bus-extensions.xml</resource>
</transformer>
<transformer>
<resource>META-INF/wsdl.plugin.xml</resource>
</transformer>
<transformer>
<resource>META-INF/cxf/java2wsbeans.xml</resource>
</transformer>
<transformer>
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer>
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer />
<transformer />
<transformer />
</transformers>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.github.edwgiz</groupId>
<artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
<groupId>org.hamcrest</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>nexus-own</id>
<name>repo-release</name>
<url>${ReleaseRepository}</url>
</repository>
<snapshotRepository>
<id>nexus-own</id>
<name>repo-snapshot</name>
<url>${SnapshotRepository}</url>
</snapshotRepository>
</distributionManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>

162
pom.xml Normal file
View File

@ -0,0 +1,162 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sunyard</groupId>
<artifactId>sdf1102</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<distributionManagement>
<snapshotRepository>
<id>nexus-own</id>
<name>repo-snapshot</name>
<url>${SnapshotRepository}</url>
</snapshotRepository>
<repository>
<id>nexus-own</id>
<name>repo-release</name>
<url>${ReleaseRepository}</url>
</repository>
</distributionManagement>
<dependencies>
<!--动态库调用依赖-->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
<dependency>
<groupId>com.sunyard</groupId>
<artifactId>loadbalancing</artifactId>
<version>1.2.201905230000</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<finalName>${project.artifactId}-${project.version}</finalName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.sunyard.security.Main</mainClass>
<!-- <mainClass>com.sunyard.test.PCIApiTest</mainClass>-->
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.tooling</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
<projectName>Apache CXF</projectName>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/cxf.extension</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/extensions.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/cxf/extensions.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/bus-extensions.txt</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/cxf/bus-extensions.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/wsdl.plugin.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/cxf/java2wsbeans.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformer"/>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer
implementation="com.github.edwgiz.mavenShadePlugin.log4j2CacheTransformer.PluginsCacheFileTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.github.edwgiz</groupId>
<artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,69 @@
package com.sunyard.security;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import com.sunyard.security.sdf.SDFJna;
import com.sunyard.security.util.ByteUtil;
public class Main {
private static PointerByReference phDeviceHandle = new PointerByReference();
private static PointerByReference phSessionHandle = new PointerByReference();;
private static final byte[] data = new byte[16];
private static final byte[] symKey = new byte[]{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
private static final String ip = "172.16.17.245";
public static void random(){
int oneSize = 16;
byte[] oneRadom = new byte[16]; // 注意这里初始化大小应为 oneSize
int ret = SDFJna.INSTANCE.SDF_GenerateRandom( phSessionHandle.getValue(), oneSize, oneRadom );
if (ret != 0) {
throw new RuntimeException(String.format("0x%02X", ret));
} else {
System.out.println("调用成功");
}
System.out.println( ByteUtil.bytes2HexString( oneRadom ) );
}
public static void main(String[] args) {
// 打开设备
int ret = SDFJna.INSTANCE.SDF_OpenDevice(
phDeviceHandle,
ByteUtil.safeStringBytes(ip),
8889,
3000,
3000,
0);
if (ret != 0) {
System.err.println("打开设备失败 错误码:" + String.format("0x%02X", ret));
throw new RuntimeException(String.format("0x%02X", ret));
}
Pointer hDeviceHandle = phDeviceHandle.getValue();
// 打开会话
ret = SDFJna.INSTANCE.SDF_OpenSession(hDeviceHandle, phSessionHandle);
if (ret != 0) {
System.err.println("打开设备失败 错误码:" + String.format("0x%02X", ret));
throw new RuntimeException(String.format("0x%02X", ret));
}
try {
random();
} finally {
if ( null != phSessionHandle.getValue() ) {
SDFJna.INSTANCE.SDF_CloseSession( phSessionHandle.getValue() );
}
if ( null != phDeviceHandle.getValue() ) {
SDFJna.INSTANCE.SDF_CloseDevice(phDeviceHandle.getValue());
}
}
}
}

View File

@ -0,0 +1,15 @@
package com.sunyard.security;
public enum RdEnum {
RD_PATH("./lib/rd"),
RD_DATA_FILE_PATH("./data/data.bin"),
RD_DATA_PATH("./data/"),
RD_REPORT_PATH("./report/report.csv");
private String value;
public String getValue() {
return value;
}
RdEnum(String value){
this.value=value;
}
}

View File

@ -0,0 +1,49 @@
package com.sunyard.security.sdf;
/**
* @author 梁俊杰
* @date 2024/05/22
*/
public enum AlgorithmEnum {
/**
* sm4 ecb 算法标识
*/
SGD_SM4_ECB(0x00000401),
/**
* sm4 ecb 算法标识
*/
SGD_SM4_CBC(0x00000402),
/**
* sm2 算法标识
*/
SGD_SM2(0x00020100),
/**
* sm3 算法标识
*/
SGD_SM3(0x00000001),
/**
* 密码设备存储私钥的索引值
*/
SM2_INDEX(0x02),
SGD_SM4_MAC(0x00000410),
;
AlgorithmEnum(int value){
this.value = value;
}
public int getValue() {
return value;
}
/**
* 算法标识
*/
private final int value;
}

View File

@ -0,0 +1,27 @@
package com.sunyard.security.sdf;
/**
* 动态库枚举类
* @author admin
*/
public enum LibEnum {
/**
* 动态库路径
*/
LIB_PATH("./lib"),
LIB_NAME("sdf");
/**
*
*/
private final String value;
LibEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,401 @@
package com.sunyard.security.sdf;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
/**
* @author sunyard
*/
public interface SDFJna extends Library {
/**
* 加载动态库
*/
SDFJna INSTANCE = Native.load(LibEnum.LIB_NAME.getValue(), SDFJna.class);
/**
* 打开设备
* @param phDeviceHandle 设备句柄
* @return int 响应码
*/
int SDF_OpenDevice(PointerByReference phDeviceHandle, byte[] ip, int port, int connTimeout, int dealTimeout, int ipMode);
/**
* 关闭设备
* @param hDeviceHandle 设备句柄
* @return int 响应码
*/
int SDF_CloseDevice(Pointer hDeviceHandle);
/**
* 打开会话
* @param hDeviceHandle 设备句柄
* @param phSessionHandle 会话句柄
* @return int 响应码
*/
int SDF_OpenSession(Pointer hDeviceHandle, PointerByReference phSessionHandle);
/**
* 关闭会话
* @param hSessionHandle 会话句柄
* @return int 响应码
*/
int SDF_CloseSession(Pointer hSessionHandle);
/**
* 生成随机数
* @param hSessionHandle 会话句柄
* @param uiLength 生成随机数长度
* @param pucRandom 存放随机数容器
* @return int 响应码
*/
int SDF_GenerateRandom(Pointer hSessionHandle, int uiLength, byte[] pucRandom);
int SDF_ImportKey(Pointer hSessionHandle, byte[] pucKey, int uiKeyLen, PointerByReference phKeyhandle);
/**
* 导出签名公钥
* @param phSessionHandle
* @param uiKeyIndex
* @param pucPublicKey
* @return
*/
int SDF_ExportSignPublicKey_ECC(Pointer phSessionHandle,
int uiKeyIndex,
byte[] pucPublicKey);
/**
* 导出加密公钥
* @param phSessionHandle
* @param uiKeyIndex
* @param pucPublicKey
* @return
*/
int SDF_ExportEncPublicKey_ECC(Pointer phSessionHandle,
int uiKeyIndex,
byte[] pucPublicKey);
/**
* 生成会话密钥并用内部 ECC公钥加密输出,输出密钥句柄
* @param phSessionHandle
* @param uiIPKIndex
* @param uiKeyBits
* @param puckey
* @param phKeyhandle
* @return
*/
int SDF_GenerateKeyWithIPK_ECC(Pointer phSessionHandle,
int uiIPKIndex,
int uiKeyBits ,
byte[] puckey,
PointerByReference phKeyhandle);
/**
* 生成会话密钥并用外部ECC公钥加密输出,输出密钥句柄
* @param hSessionHandle 会话句柄
* @param uiKeyBits 密钥长度
* @param uiAlgID 算法标识
* @param pucPublicKey ECC公钥结构
* @param pucKey 密钥密文
* @param phKeyHandle 密钥句柄
* @return int 响应码
*/
int SDF_GenerateKeyWithEPK_ECC(
Pointer hSessionHandle,
int uiKeyBits,
int uiAlgID,
byte[] pucPublicKey,
byte[] pucKey,
PointerByReference phKeyHandle
);
/**
* 导入会话密钥并用内部ECC私钥解密
* @param phSessionHandle
* @param uiISKIndex
* @param puckey
* @param phKeyhandle
* @return
*/
int SDF_ImportKeyWithISK_ECC(Pointer phSessionHandle,
int uiISKIndex,
byte[] puckey,
PointerByReference phKeyhandle);
/**
* 销毁会话密钥
* @param phSessionHandle
* @param phKeyhandle
* @return
*/
int SDF_DestroyKey(Pointer phSessionHandle, PointerByReference phKeyhandle);
/**
* 生成ECC密钥对
* @param phSessionHandle 会话句柄
* @param uiAlgID 算法标识
* @param uiKeyBits 密钥长度
* @param pucPublicKey 输出的ECC公钥结构
* @param pucPrivateKey 输出的ECC私钥结构
* @return int 响应码
*/
int SDF_GenerateKeyPair_ECC(
Pointer phSessionHandle,
int uiAlgID,
int uiKeyBits,
byte[] pucPublicKey,
byte[] pucPrivateKey
);
/**
* 对称加密
* @param phSessionHandle 会话句柄
* @param hKeyHandle 密钥句柄
* @param uiAlgID 算法标识
* @param pucIV IV数据
* @param pucData 待加密数据
* @param pucDataLength 待加密数据长度
* @param pucEncData 存放密文容器
* @param pucEncDataLength 密文长度
* @return int 响应码
*/
int SDF_Encrypt(
Pointer phSessionHandle,
Pointer hKeyHandle,
int uiAlgID,
byte[] pucIV,
byte[] pucData,
int pucDataLength,
byte[] pucEncData,
IntByReference pucEncDataLength
);
/**
* 对称解密
* @param phSessionHandle 会话句柄
* @param hKeyHandle 密钥句柄
* @param uiAlgID 算法标识
* @param pucIV IV数据
* @param purEncData 指向密文数据的指针
* @param encDataLength 密文数据长度
* @param pucData 输出明文数据
* @param pucDataLength 输出明文数据长度
* @return int 响应码
*/
int SDF_Decrypt(
Pointer phSessionHandle,
Pointer hKeyHandle,
int uiAlgID,
byte[] pucIV,
byte[] purEncData,
int encDataLength,
byte[] pucData,
IntByReference pucDataLength
);
/**
* 杂凑运算初始化
* @param phSessionHandle 会话句柄
* @param uiAlgID 算法标识
* @param pucPublicKey ECC公钥结构
* @param pucID 签名者的ID值
* @param pucIDlength 签名者ID的长度
* @return int 响应码
*/
int SDF_HashInit(Pointer phSessionHandle, int uiAlgID, byte[] pucPublicKey, String pucID, int pucIDlength);
/**
* 多包杂凑运算
* @param phSessionHandle 会话句柄
* @param pucData 输入的数据明文
* @param uiDataLength 输入的数据明文长度
* @return int 响应码
*/
int SDF_HashUpdate(
Pointer phSessionHandle, // 使用IntByReference因为SessionHandle可能是引用类型的
byte[] pucData, // 输入的明文数据作为字节数组
int uiDataLength // 明文数据长度
);
/**
* 杂凑运算结束
* @param phSessionHandle 会话句柄
* @param pucHash 杂凑结果
* @param pucHashLength 杂凑结果长度
* @return int 响应码
*/
int SDF_HashFinal(Pointer phSessionHandle, byte[] pucHash, IntByReference pucHashLength);
int SDF_CalculateMAC(Pointer phSessionHandle,
Pointer hKeyHadnle,
int uiAlgID,
byte[] pucIV,
byte[] purData,
int pucDatalength,
byte[] pucMAC,
IntByReference pucMACLength);
/**
* 外部ECC签名
* @param phSessionHandle 会话句柄
* @param uiAlgID 算法标识
* @param pucPublicKey ECC公钥结构
* @param pucData 输入的数据明文
* @param pucDataLength 输入的数据明文长度
* @param pucECCSignature 输出的签名值数据
* @return int 响应码
*/
int SDF_ExternalSign_ECC(
Pointer phSessionHandle,
int uiAlgID,
byte[] pucPublicKey,
byte[] pucData,
int pucDataLength,
byte[] pucECCSignature
);
/**
* 外部ECC验签
* @param phSessionHandle 会话句柄
* @param uiAlgID 算法标识
* @param pucPublicKey ECC公钥结构
* @param pucData 输入的数据明文
* @param pucDataLength 输入的数据明文长度
* @param pucECCSignature 输入的签名值数据
* @return int 响应码
*/
int SDF_ExternalVerify_ECC(Pointer phSessionHandle, int uiAlgID, byte[] pucPublicKey, byte[] pucData, int pucDataLength, byte[] pucECCSignature);
/**
* 内部密钥ECC签名
* @param phSessionHandle
* @param uiAlgID
* @param uiISKIndex
* @param pucData
* @param pucDatalength
* @param pucECCSignature
* @return
*/
int SDF_InternalSign_ECC(Pointer phSessionHandle,
int uiISKIndex,
byte[] pucData,
int pucDatalength,
byte[] pucECCSignature);
/**
* 内部密钥ECC签名
* @param phSessionHandle
* @param uiISKIndex
* @param pucData
* @param pucDatalength
* @param pucECCSignature
* @return
*/
int SDF_InternalVerify_ECC(Pointer phSessionHandle,
int uiISKIndex,
byte[] pucData,
int pucDatalength,
byte[] pucECCSignature);
/**
* 密钥加密
* @param phSessionHandle 会话句柄
* @param uiAlgID 算法标识
* @param pucPublicKey ECC公钥结构
* @param pucData 输入的数据明文
* @param pucDatalength 输入的数据明文长度
* @param pucEncData 输出的密文数据
* @return int 响应码
*/
int SDF_ExternalEncrypt_ECC(Pointer phSessionHandle, int uiAlgID, byte[] pucPublicKey, byte[] pucData, int pucDatalength, byte[] pucEncData);
/**
* 密钥解密
* @param phSessionHandle 会话句柄
* @param uiAlgID 算法标识
* @param pucPrivateKey ECC私钥结构
* @param pucEncData 输入的密文数据
* @param pucDataOut 输出的数据明文
* @param pucDatalength 输出的数据明文长度
* @return int 响应码
*/
int SDF_ExternalDecrypt_ECC(Pointer phSessionHandle, int uiAlgID, byte[] pucPrivateKey, byte[] pucEncData, byte[] pucDataOut, IntByReference pucDatalength);
/**
* 生成密钥协商数据
* @param phSessionHandle 会话句柄
* @param uiISKIndex 密码设备存储私钥的索引值
* @param uiKeyBits 要求协商的密钥长度
* @param pucSponsorID 参与密钥协商的发起方ID值
* @param uiSponsorIDLength 发起方ID长度
* @param pucSponsorPublicKey 返回的发起方ECC公钥结构
* @param pucSponsorTmpPublicKey 返回的发起方临时ECC公钥结构
* @param phAgreementHandle 返回的协商对象用于计算协商密钥
* @return int 响应码
*/
int SDF_GenerateAgreementDataWithECC(Pointer phSessionHandle, int uiISKIndex, int uiKeyBits,
String pucSponsorID, int uiSponsorIDLength,
byte[] pucSponsorPublicKey, byte[] pucSponsorTmpPublicKey,
PointerByReference phAgreementHandle);
/**
* 生成密钥协商数据并计算密钥
* @param phSessionHandle 会话句柄
* @param uiISKIndex 密码设备存储私钥的索引值
* @param uiKeyBits 要求协商的密钥长度
* @param pucResponseID 参与密钥协商的响应方ID值
* @param uiResponseIDLength 响应方ID长度
* @param pucSponsorID 参与密钥协商的发起方ID值
* @param uiSponsorIDLength 发起方ID长度
* @param pucSponsorPublicKey 发起方ECC公钥结构
* @param pucSponsorTmpPublicKey 发起方临时ECC公钥结构
* @param pucResponsePublicKey 响应方ECC公钥结构
* @param pucResponseTmpPublicKey 响应方临时ECC公钥结构
* @param phKeyhandle 返回的密钥句柄
* @return
*/
int SDF_GenerateAgreementDataAndKeyWithECC(
Pointer phSessionHandle,
int uiISKIndex,
int uiKeyBits,
String pucResponseID,
int uiResponseIDLength,
String pucSponsorID,
int uiSponsorIDLength,
byte[] pucSponsorPublicKey,
byte[] pucSponsorTmpPublicKey,
byte[] pucResponsePublicKey,
byte[] pucResponseTmpPublicKey,
PointerByReference phKeyhandle
);
/**
* 获取私钥访问权
* @param phSessionHandle 会话句柄
* @param uiKeyIndex 密码设备存储私钥的索引值
* @param pucPassword 使用私钥权限的标识码
* @param uiPwdLength 私钥访问控制码长度不少于8字节
* @return int 响应码
*/
int SDF_GetPrivateKeyAccessRight(Pointer phSessionHandle, int uiKeyIndex, String pucPassword, int uiPwdLength);
/**
* 释放私钥访问权
* @param phSessionHandle 会话句柄
* @param uiKeyIndex 密码设备存储私钥的索引值
* @return int 响应码
*/
int SDF_ReleasePrivateKeyAccessRight(Pointer phSessionHandle, int uiKeyIndex);
}

View File

@ -0,0 +1,114 @@
package com.sunyard.security.util;
import java.util.Arrays;
public class ByteUtil {
/**
* PKCS5/PKCS7 标准填充数据
* @param data
* @return
*/
public static byte[] pkcsFullPadding(byte[] data) {
int remainder = data.length % 16;
remainder = 16 - remainder;
byte[] buff = new byte[ data.length + remainder ];
System.arraycopy( data, 0, buff, 0, data.length );
Arrays.fill( buff, data.length, buff.length, (byte)( 0xFF & remainder ));
return buff;
}
/**
* PKCS5/PKCS7 标准去除填充数据
* @param data
* @param len 有效数据长度
* @return
*/
public static byte[] pkcsRemovePadding(byte[] data, int len) {
if ( data.length < len ) {
throw new IllegalArgumentException();
}
int remainder = data[ len - 1 ];
if ( remainder < 0 || remainder > 16 || remainder > len ) {
throw new IllegalArgumentException();
}
len -= remainder;
byte[] buff = new byte[ len ];
System.arraycopy( data, 0, buff, 0, len );
return buff;
}
public static byte[] pkcsRemovePadding(byte[] data){
return pkcsRemovePadding( data, data.length );
}
public static String bytes2HexString(byte[] b) {
StringBuilder bs = new StringBuilder();
for (int i = 0; i < b.length; ++i) {
String hex = Integer.toHexString(b[i] & 255);
if (hex.length() == 1) {
hex = '0' + hex;
}
bs.append(hex.toUpperCase());
}
return bs.toString();
}
public static String bytes2HexString(byte[] b, int len) {
StringBuilder bs = new StringBuilder();
for (int i = 0; i < len; ++i) {
String hex = Integer.toHexString(b[i] & 255);
if (hex.length() == 1) {
hex = '0' + hex;
}
bs.append(hex.toUpperCase());
}
return bs.toString();
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
public static byte[] hexString2Bytes(String hex) {
if (hex != null && !hex.equals("")) {
if (hex.length() % 2 != 0) {
return new byte[0];
} else {
hex = hex.toUpperCase();
int len = hex.length() / 2;
byte[] b = new byte[len];
char[] hc = hex.toCharArray();
for (int i = 0; i < len; ++i) {
int p = 2 * i;
b[i] = (byte) (charToByte(hc[p]) << 4 | charToByte(hc[p + 1]) & 0xff );
}
return b;
}
} else {
return new byte[0];
}
}
public static byte[] safeStringBytes(String str){
if ( null == str || str.isEmpty()) {
return new byte[] { 0x30 };
}
int len = str.getBytes().length;
byte[] ret = new byte[len + 1];
System.arraycopy(str.getBytes(), 0, ret, 0, len);
return ret;
}
}

BIN
src/main/resources/linux-aarch64/libsdf.so (Stored with Git LFS) Normal file

Binary file not shown.

BIN
src/main/resources/linux-x86-64/libsdf.so (Stored with Git LFS) Normal file

Binary file not shown.

BIN
src/main/resources/win32-x86-64/sdf.dll (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,117 @@
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sunyard.security.sdf.AlgorithmEnum;
import com.sunyard.security.sdf.SDFJna;
import com.sunyard.security.util.ByteUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class MutiThreads {
private PointerByReference phDeviceHandle = new PointerByReference();
private static final byte[] data = new byte[16];
private static final byte[] symKey = new byte[]{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
private static final String ip = "172.16.17.245";
private static final int thread_max = 16;
private static final int func_maxcall = 10000;
@Before
public void before(){
// 打开设备
int ret = SDFJna.INSTANCE.SDF_OpenDevice(
phDeviceHandle,
ByteUtil.safeStringBytes(ip),
8889,
3000,
3000,
0);
if (ret != 0) {
System.err.println("打开设备失败 错误码:" + String.format("0x%02X", ret));
throw new RuntimeException(String.format("0x%02X", ret));
}
}
@After
public void after(){
if ( null != phDeviceHandle.getValue() ) {
SDFJna.INSTANCE.SDF_CloseDevice(phDeviceHandle.getValue());
}
}
private void genSessionKey(PointerByReference phSessionHandle, PointerByReference phkeyHandle){
int ret = SDFJna.INSTANCE.SDF_ImportKey(phSessionHandle.getValue(), symKey, symKey.length ,phkeyHandle);
if (ret != 0) {
throw new RuntimeException("genSessionKey " + String.format("0x%02X", ret));
}
}
/**
* 多线程加解密
*/
@Test
public void sm4_en(){
System.out.println(" sm4 en 测试开始");
Thread[] threads = new Thread[thread_max];
for ( int i = 0; i < thread_max; i++ ) {
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
PointerByReference phSessionHandle = new PointerByReference();
try {
Pointer hDeviceHandle = phDeviceHandle.getValue();
// 打开会话
int ret = SDFJna.INSTANCE.SDF_OpenSession(hDeviceHandle, phSessionHandle);
if (ret != 0) {
System.err.println("打开设备失败 错误码:" + String.format("0x%02X", ret));
throw new RuntimeException(String.format("0x%02X", ret));
}
PointerByReference phkeyHandle = new PointerByReference();
genSessionKey(phSessionHandle, phkeyHandle);
for (int c= 0; c < func_maxcall; c++ ) {
byte[] enData = new byte[32];
IntByReference intByReference = new IntByReference();
ret = SDFJna.INSTANCE.SDF_Encrypt(phSessionHandle.getValue(), phkeyHandle.getValue(), AlgorithmEnum.SGD_SM4_ECB.getValue(), null, data, data.length, enData, intByReference);
if (ret != 0) {
throw new RuntimeException("加密失败 " + String.format("0x%02X", ret));
}
}
} finally {
if ( null != phSessionHandle.getValue() ) {
SDFJna.INSTANCE.SDF_CloseSession( phSessionHandle.getValue() );
}
}
}
});
}
long start = System.currentTimeMillis();
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
long end = System.currentTimeMillis();
long delta = end - start;
double p = (double) thread_max * func_maxcall * 1000.0 / delta;
System.out.println( " sm4 en " + p + "TPS");
}
}

259
src/test/java/SDFTest.java Normal file
View File

@ -0,0 +1,259 @@
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sunyard.security.sdf.AlgorithmEnum;
import com.sunyard.security.sdf.SDFJna;
import com.sunyard.security.util.ByteUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class SDFTest {
private PointerByReference phDeviceHandle = new PointerByReference();
private PointerByReference phSessionHandle = new PointerByReference();;
private static final byte[] data = new byte[16];
private static final byte[] symKey = new byte[]{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
private static final String ip = "172.16.17.245";
@Before
public void before(){
// 打开设备
int ret = SDFJna.INSTANCE.SDF_OpenDevice(
phDeviceHandle,
ByteUtil.safeStringBytes(ip),
8889,
3000,
3000,
0);
if (ret != 0) {
System.err.println("打开设备失败 错误码:" + String.format("0x%02X", ret));
throw new RuntimeException(String.format("0x%02X", ret));
}
Pointer hDeviceHandle = phDeviceHandle.getValue();
// 打开会话
ret = SDFJna.INSTANCE.SDF_OpenSession(hDeviceHandle, phSessionHandle);
if (ret != 0) {
System.err.println("打开设备失败 错误码:" + String.format("0x%02X", ret));
throw new RuntimeException(String.format("0x%02X", ret));
}
}
@After
public void after(){
if ( null != phSessionHandle.getValue() ) {
SDFJna.INSTANCE.SDF_CloseSession( phSessionHandle.getValue() );
}
if ( null != phDeviceHandle.getValue() ) {
SDFJna.INSTANCE.SDF_CloseDevice(phDeviceHandle.getValue());
}
}
@Test
public void random(){
int oneSize = 16;
byte[] oneRadom = new byte[16]; // 注意这里初始化大小应为 oneSize
int ret = SDFJna.INSTANCE.SDF_GenerateRandom( phSessionHandle.getValue(), oneSize, oneRadom );
if (ret != 0) {
throw new RuntimeException(String.format("0x%02X", ret));
} else {
System.out.println("调用成功");
}
Assert.assertEquals( ret, 0 );
System.out.println( ByteUtil.bytes2HexString( oneRadom ) );
}
private void genSessionKey(PointerByReference phkeyHandle){
int ret = SDFJna.INSTANCE.SDF_ImportKey(phSessionHandle.getValue(), symKey, symKey.length ,phkeyHandle);
if (ret != 0) {
throw new RuntimeException("genSessionKey " + String.format("0x%02X", ret));
}
}
/**
* SDF 接口内没有填充
* 输入数据必须 16 的整倍数
*/
@Test
public void sym_ecb(){
int ret = 0;
PointerByReference phkeyHandle = new PointerByReference();
genSessionKey(phkeyHandle);
System.out.println( "data=" + ByteUtil.bytes2HexString( data ));
byte[] enData = new byte[32];
IntByReference intByReference = new IntByReference();
ret = SDFJna.INSTANCE.SDF_Encrypt(phSessionHandle.getValue(), phkeyHandle.getValue(), AlgorithmEnum.SGD_SM4_ECB.getValue(), null, data, data.length, enData, intByReference);
if (ret != 0) {
throw new RuntimeException("加密失败 " + String.format("0x%02X", ret));
}
System.out.println( intByReference.getValue() );
System.out.println( "enData=" + ByteUtil.bytes2HexString( enData ));
byte[] rawData = new byte[32];
ret = SDFJna.INSTANCE.SDF_Decrypt(phSessionHandle.getValue(), phkeyHandle.getValue(), AlgorithmEnum.SGD_SM4_ECB.getValue(), null, enData, intByReference.getValue(), rawData, intByReference);
if (ret != 0) {
throw new RuntimeException("解密失败 " + String.format("0x%02X", ret));
}
System.out.println("长度" + intByReference.getValue());
System.out.println( "rawData=" + ByteUtil.bytes2HexString( rawData , intByReference.getValue()));
}
@Test
public void sym_cbc(){
int ret = 0;
PointerByReference phkeyHandle = new PointerByReference();
genSessionKey(phkeyHandle);
byte[] iv = new byte[16];
System.out.println( "data=" + ByteUtil.bytes2HexString( data ));
byte[] enData = new byte[32];
IntByReference intByReference = new IntByReference();
ret = SDFJna.INSTANCE.SDF_Encrypt(phSessionHandle.getValue(), phkeyHandle.getValue(), AlgorithmEnum.SGD_SM4_CBC.getValue(), iv, data, data.length, enData, intByReference);
if (ret != 0) {
throw new RuntimeException("加密失败 " + String.format("0x%02X", ret));
}
System.out.println( intByReference.getValue() );
System.out.println( "enData=" + ByteUtil.bytes2HexString( enData ));
byte[] rawData = new byte[32];
iv = new byte[16];
ret = SDFJna.INSTANCE.SDF_Decrypt(phSessionHandle.getValue(), phkeyHandle.getValue(), AlgorithmEnum.SGD_SM4_CBC.getValue(), iv, enData, intByReference.getValue(), rawData, intByReference);
if (ret != 0) {
throw new RuntimeException("解密失败 " + String.format("0x%02X", ret));
}
System.out.println( "rawData=" + ByteUtil.bytes2HexString( rawData , intByReference.getValue()));
}
@Test
public void mac(){
int ret = 0;
PointerByReference phkeyHandle = new PointerByReference();
genSessionKey(phkeyHandle);
byte[] mac = new byte[32];
IntByReference macLen = new IntByReference();
ret = SDFJna.INSTANCE.SDF_CalculateMAC(phSessionHandle.getValue(),
phkeyHandle.getValue(),
AlgorithmEnum.SGD_SM4_MAC.getValue(),
new byte[16],
data,
data.length,
mac,
macLen
);
if (ret != 0) {
throw new RuntimeException("CalculateMAC " + String.format("0x%02X", ret));
}
System.out.println( ByteUtil.bytes2HexString( mac , macLen.getValue()) );
}
@Test
public void hash(){
int ret = 0;
byte[] mac = new byte[32];
IntByReference macLen = new IntByReference();
ret = SDFJna.INSTANCE.SDF_HashInit( phSessionHandle.getValue(), AlgorithmEnum.SGD_SM3.getValue(), null, null, 0 );
if (ret != 0) {
throw new RuntimeException("HashInit " + String.format("0x%02X", ret));
}
ret = SDFJna.INSTANCE.SDF_HashUpdate(phSessionHandle.getValue(), data, data.length);
if (ret != 0) {
throw new RuntimeException("HashUpdate " + String.format("0x%02X", ret));
}
ret = SDFJna.INSTANCE.SDF_HashFinal(phSessionHandle.getValue(), mac, macLen);
if (ret != 0) {
throw new RuntimeException("HashFinal " + String.format("0x%02X", ret));
}
System.out.println( ByteUtil.bytes2HexString( mac , macLen.getValue()) );
}
/**
* 非对称 签名验签
* 外部密钥
*/
@Test
public void asym_ext_sv(){
byte[] puk = new byte[256];
byte[] pak = new byte[256];
byte[] hash = new byte[32];
int ret = SDFJna.INSTANCE.SDF_GenerateKeyPair_ECC(phSessionHandle.getValue(), AlgorithmEnum.SGD_SM2.getValue(), 256, puk, pak);
if (ret != 0) {
throw new RuntimeException("生成非对称密钥 " + String.format("0x%02X", ret));
}
byte[] sign = new byte[512];
ret = SDFJna.INSTANCE.SDF_ExternalSign_ECC(
phSessionHandle.getValue(),
AlgorithmEnum.SGD_SM2.getValue(), pak, hash, hash.length, sign
);
if (ret != 0) {
throw new RuntimeException("ExternalSign_ECC " + String.format("0x%02X", ret));
}
// 验签
ret = SDFJna.INSTANCE.SDF_ExternalVerify_ECC(phSessionHandle.getValue(), AlgorithmEnum.SGD_SM2.getValue(), puk, hash, hash.length, sign);
if (ret != 0) {
throw new RuntimeException("ExternalSign_ECC " + String.format("0x%02X", ret));
}
}
/**
* 非对称 加密解密
* 外部密钥
*/
@Test
public void asym_en(){
byte[] puk = new byte[256];
byte[] pak = new byte[256];
int ret = SDFJna.INSTANCE.SDF_GenerateKeyPair_ECC(phSessionHandle.getValue(), AlgorithmEnum.SGD_SM2.getValue(), 256, puk, pak);
if (ret != 0) {
throw new RuntimeException("生成非对称密钥 " + String.format("0x%02X", ret));
}
System.out.println( "ret= " + ret);
System.out.println( "puk= " + ByteUtil.bytes2HexString( puk ));
System.out.println( "pak= " + ByteUtil.bytes2HexString( pak ));
byte[] enc = new byte[512];
ret = SDFJna.INSTANCE.SDF_ExternalEncrypt_ECC(
phSessionHandle.getValue(),
AlgorithmEnum.SGD_SM2.getValue(),
puk,
data, data.length, enc
);
if (ret != 0) {
throw new RuntimeException("ExternalEncrypt_ECC " + String.format("0x%02X", ret));
}
byte[] buffer = new byte[512];
IntByReference bufferLen = new IntByReference( buffer.length );
ret = SDFJna.INSTANCE.SDF_ExternalDecrypt_ECC(
phSessionHandle.getValue(),
AlgorithmEnum.SGD_SM2.getValue(),
pak,
enc, buffer, bufferLen
);
if (ret != 0) {
throw new RuntimeException("ExternalEncrypt_ECC " + String.format("0x%02X", ret));
}
}
}