1、升级dproto依赖,2、添加77,78指令的接口,sm2加解密密文结构为C1C2C3,3、生成数字信封添加机构码
This commit is contained in:
+38
-6
@@ -14,6 +14,9 @@
|
||||
<option cn="SM2_SM4_ECB">
|
||||
<hex>1</hex>
|
||||
</option>
|
||||
<option cn="SM2_SM4_ECB 机构码|02|密钥">
|
||||
<hex>2</hex>
|
||||
</option>
|
||||
</options>
|
||||
</alg>
|
||||
|
||||
@@ -50,6 +53,14 @@
|
||||
LMK 下加密密钥的方案。
|
||||
</keyType>
|
||||
|
||||
<orgCodeLen len="2" :value="orgCodeLen()" :if="hasOrgCode()" cn="机构码长度">
|
||||
公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在
|
||||
</orgCodeLen>
|
||||
|
||||
<orgCode :if="hasOrgCode()" cn="机构码长度">
|
||||
公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在
|
||||
</orgCode>
|
||||
|
||||
<tailSep len="1" :if=" null != $packet.data.tail " cn="尾分隔">
|
||||
可选项。如果显示消息尾域,则该域必须显示。值为
|
||||
“X’19”。
|
||||
@@ -140,7 +151,8 @@
|
||||
|
||||
|
||||
</res>
|
||||
<script>function certificateLen(){
|
||||
<script>
|
||||
function certificateLen(){
|
||||
var data = $packet.data;
|
||||
if( 0 == data.certificateModel$option ){
|
||||
return data.certificateSn.length
|
||||
@@ -148,15 +160,15 @@
|
||||
if( 1 == data.certificateModel$option ){
|
||||
return data.certificateDn.length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getKeyLen() {
|
||||
function getKeyLen() {
|
||||
return Util.a2i( $final.getSection('data').getSection('keyLen') )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function lmkLen() {
|
||||
function lmkLen() {
|
||||
if( Arrays.equals("L".getBytes(),
|
||||
$final.getSection('data').getSection('lmkHead').getValue()
|
||||
) ){
|
||||
@@ -164,5 +176,25 @@ function lmkLen() {
|
||||
}else{
|
||||
return 32
|
||||
}
|
||||
} </script>
|
||||
}
|
||||
|
||||
<![CDATA[
|
||||
function hasOrgCode() {
|
||||
if(2 == $packet.data.alg$option && 'P' == $packet.data.pFlag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function orgCodeLen() {
|
||||
def len = $packet.data.orgCode.length();
|
||||
def data = new byte[2];
|
||||
data[0] = (byte)(len >> 8 & 0xFF)
|
||||
data[1] = (byte)(len & 0xFF)
|
||||
|
||||
return data;
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
</packet>
|
||||
|
||||
+21
-8
@@ -120,6 +120,14 @@
|
||||
密钥校验值
|
||||
</keyCheck>
|
||||
|
||||
<orgCodeLen len="4" cn="机构码长度">
|
||||
公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在
|
||||
</orgCodeLen>
|
||||
|
||||
<orgCode :len="orgCodeLen()" cn="机构码长度">
|
||||
公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在
|
||||
</orgCode>
|
||||
|
||||
<tailSep len="1" required="false" cn="尾分隔">
|
||||
可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。
|
||||
<hex>19</hex>
|
||||
@@ -133,7 +141,8 @@
|
||||
|
||||
|
||||
</res>
|
||||
<script>function certificateLen(){
|
||||
<script>
|
||||
function certificateLen(){
|
||||
var data = $packet.data;
|
||||
if( 0 == data.certificateModel$option ){
|
||||
return data.certificateSn.length()
|
||||
@@ -141,18 +150,18 @@
|
||||
if( 1 == data.certificateModel$option ){
|
||||
return data.certificateDn.length()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function keyLen() {
|
||||
function keyLen() {
|
||||
return $packet.data.key.length()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getKeyLen() {
|
||||
function getKeyLen() {
|
||||
return Util.a2i( $final.getSection('data').getSection('keyLen') )
|
||||
}
|
||||
}
|
||||
|
||||
function lmkLen() {
|
||||
function lmkLen() {
|
||||
if( Arrays.equals("L".getBytes(),
|
||||
$final.getSection('data').getSection('lmkHead').getValue()
|
||||
) ){
|
||||
@@ -160,5 +169,9 @@ function lmkLen() {
|
||||
}else{
|
||||
return 32
|
||||
}
|
||||
} </script>
|
||||
}
|
||||
function orgCodeLen() {
|
||||
return Util.a2i( $final.getSection('data').getSection('orgCodeLen') )
|
||||
}
|
||||
</script>
|
||||
</packet>
|
||||
|
||||
Binary file not shown.
@@ -77,7 +77,7 @@
|
||||
<dependency>
|
||||
<groupId>com.sunyard</groupId>
|
||||
<artifactId>dproto</artifactId>
|
||||
<version>1.0-20211220</version>
|
||||
<version>1.0-20220107</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -95,6 +95,16 @@ interface SydASYMApi {
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* 用指定的 SM2 公钥对指定的密文数据进行加密。
|
||||
* 输出的sm2密文结构为C1C2C3格式
|
||||
* @param publicKey 公钥钥串,DER 编码,HEX 格式。
|
||||
* @param pOrgData 加密的数据。
|
||||
* @return 加密的数据 base64 编码。
|
||||
*/
|
||||
String SM2EncryptOrder(byte[] publicKey, byte[] pOrgData);
|
||||
|
||||
|
||||
/**
|
||||
* 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。
|
||||
*
|
||||
@@ -112,6 +122,15 @@ interface SydASYMApi {
|
||||
*/
|
||||
byte[] SM2Decrypt(byte[] sk, String enData);
|
||||
|
||||
/**
|
||||
* 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。
|
||||
* 输入的sm2密文结构为C1C2C3格式
|
||||
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
|
||||
* @param enData 加密的数据,base64 编码。
|
||||
* @return 明文数据。
|
||||
*/
|
||||
byte[] SM2DecryptOrder(String userId, String enData);
|
||||
|
||||
/**
|
||||
* 用指定的 RSA 私钥对指定的密文数据进行加密。
|
||||
*
|
||||
|
||||
@@ -228,6 +228,18 @@ public interface SydGenApi {
|
||||
*/
|
||||
RetWrap generateDEbyGS(String certSerial, byte nAlg);
|
||||
|
||||
/**
|
||||
* 产生对称密钥,通过公钥加密生成网联格式的数字信封。
|
||||
*
|
||||
* @param certSerial 对*方 X509 证书的序列号。
|
||||
* @param orgCode 机构码
|
||||
* @return RetWrap 包含 CipherKey, SessionKey, KCV
|
||||
* CipherKey 公钥加密的会话密钥 ,BASE64 编码
|
||||
* SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。
|
||||
* KCV 会话密钥的检验值,HEX 格式,长度为 32H。
|
||||
*/
|
||||
RetWrap generateDEbyGS(String certSerial, String orgCode);
|
||||
|
||||
/**
|
||||
* 产生对称密钥,通过公钥加密生成网联格式的数字信封。
|
||||
|
||||
@@ -252,6 +264,7 @@ public interface SydGenApi {
|
||||
* @return RetWrap 包含 SessionKey KCV
|
||||
* SessionKey 输出。 本地LMK 加密的会话密钥,格式为:密钥类型|密钥密文,比如:02|密钥密文
|
||||
* KCV 会话密钥的检验值,HEX 格式,长度为 36H。
|
||||
* orgCode 如果有机构码的话会返回机构码
|
||||
*/
|
||||
RetWrap decryptDE(
|
||||
String pCertSerial,
|
||||
|
||||
@@ -2129,15 +2129,20 @@ public class SydApi4j implements SydApi {
|
||||
|
||||
@Override
|
||||
public RetWrap generateDEbyGS(String certSerial, byte nAlg) {
|
||||
return generateDE(1, certSerial, nAlg);
|
||||
return generateDE(1, certSerial, nAlg, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RetWrap generateDEbyGS(String certSerial, String orgCode) {
|
||||
return generateDE(1, certSerial, (byte) 0x32, orgCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RetWrap generateDE(String certSerial, byte nAlg) {
|
||||
return generateDE(0, certSerial, nAlg);
|
||||
return generateDE(0, certSerial, nAlg, null);
|
||||
}
|
||||
|
||||
public RetWrap generateDE(int pFlag, String certSerial, byte nAlg) {
|
||||
private RetWrap generateDE(int pFlag, String certSerial, byte nAlg, String orgCode) {
|
||||
// 获取协议
|
||||
//ProtocolRender render = pset.getProtocolReqRender("6A");
|
||||
Proto6A proto = new Proto6A();
|
||||
@@ -2149,6 +2154,14 @@ public class SydApi4j implements SydApi {
|
||||
data.put("alg$option", nAlg - 0x30);
|
||||
if (pFlag == 1) {
|
||||
data.put("pFlag", 'P');
|
||||
|
||||
if (nAlg == 0x32) {
|
||||
if (orgCode.length() != 14) {
|
||||
throw new SydApiException("机构码长度错(只能==14)", -6);
|
||||
}
|
||||
|
||||
data.put("orgCode", orgCode);
|
||||
}
|
||||
}
|
||||
data.put("certificateModel$option", 0);
|
||||
data.put("certificateSn", certSerial.getBytes());
|
||||
@@ -2225,6 +2238,11 @@ public class SydApi4j implements SydApi {
|
||||
}
|
||||
RetWrap rw = new RetWrap();
|
||||
|
||||
int orgCodeLen = Util.a2i(((PacketSection) ret.get("orgCodeLen")).getBytes(), 10);
|
||||
if (orgCodeLen != 0) {
|
||||
rw.put("orgCode", ((PacketSection) ret.get("orgCode")).getString());
|
||||
}
|
||||
|
||||
rw.put(SydApi.RET_SESSION_KEY, ((PacketSection) ret.get("lmkHead")).getString() +
|
||||
((PacketSection) ret.get("lmk")).getString()
|
||||
);
|
||||
@@ -3974,6 +3992,43 @@ public class SydApi4j implements SydApi {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String SM2EncryptOrder(byte[] publicKey, byte[] pOrgData) {
|
||||
Proto77 proto = new Proto77();
|
||||
|
||||
// 填充数据
|
||||
HashMap<String, Object> packet = new HashMap<String, Object>();
|
||||
HashMap<String, Object> data = new HashMap<String, Object>();
|
||||
packet.put("data", data);
|
||||
PacketSN sn = PacketSN.gen();
|
||||
packet.put("header", sn.getSn().array());
|
||||
data.put("AlgorithmKey$option", 1);
|
||||
data.put("publicKey", publicKey);
|
||||
data.put("infoData", pOrgData);
|
||||
// 渲染发送
|
||||
ByteBuffer bb = proto.rend(packet);
|
||||
synchronized (this) {
|
||||
// 响应解析
|
||||
bb = syncRead(syncSend(bb));
|
||||
}
|
||||
//ProtocolParser parser = pset.getProtocolResParse();
|
||||
Packet p = proto.parse(bb);
|
||||
Map<String, Object> ret = p.toMap();
|
||||
if (
|
||||
!Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes())
|
||||
) {
|
||||
throw new SydApiException("包序号不匹配", -4);
|
||||
}
|
||||
ret = (Map<String, Object>) ret.get("data");
|
||||
PacketSection error = (PacketSection) ret.get("error");
|
||||
if (!"00".equals(error.getString())) {
|
||||
throw new SydApiException(error.getInfo(), error.autoInt());
|
||||
}
|
||||
|
||||
System.out.println("内部输出: " + Util.bytes2HexString(((PacketSection) ret.get("cipherData")).getBytes()));
|
||||
|
||||
return SYMUtil.derEnData2Base64EnC1C2C3(((PacketSection) ret.get("cipherData")).getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String SM2Encrypt(byte[] publicKey, byte[] pOrgData) {
|
||||
@@ -4092,6 +4147,54 @@ public class SydApi4j implements SydApi {
|
||||
return ((PacketSection) ret.get("data")).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。
|
||||
* 输入的sm2密文结构为C1C2C3格式
|
||||
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
|
||||
* @param enData 加密的数据,base64 编码。
|
||||
* @return 明文数据。
|
||||
*/
|
||||
@Override
|
||||
public byte[] SM2DecryptOrder(String userId, String enData) {
|
||||
//ProtocolRender render = pset.getProtocolReqRender("78");
|
||||
Proto78 proto = new Proto78();
|
||||
|
||||
byte[] pOrgData = SYMUtil.base64EnData2DerEnDataC1C2C3(enData);
|
||||
|
||||
System.out.println("解密内部输出: " + Util.bytes2HexString(pOrgData));
|
||||
|
||||
// 填充数据
|
||||
HashMap<String, Object> packet = new HashMap<String, Object>();
|
||||
HashMap<String, Object> data = new HashMap<String, Object>();
|
||||
packet.put("data", data);
|
||||
PacketSN sn = PacketSN.gen();
|
||||
packet.put("header", sn.getSn().array());
|
||||
data.put("AlgorithmKey$option", 1);
|
||||
data.put("infoData", pOrgData);
|
||||
data.put("privateKeyTag", SYMUtil.genPrivateKeyMark(userId, SYMUtil.KT_ENCRYPT, "00000001"));
|
||||
// 渲染发送
|
||||
ByteBuffer bb = proto.rend(packet);
|
||||
synchronized (this) {
|
||||
// 响应解析
|
||||
bb = syncRead(syncSend(bb));
|
||||
}
|
||||
//ProtocolParser parser = pset.getProtocolResParse();
|
||||
Packet p = proto.parse(bb);
|
||||
Map<String, Object> ret = p.toMap();
|
||||
if (
|
||||
!Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes())
|
||||
) {
|
||||
throw new SydApiException("包序号不匹配", -4);
|
||||
}
|
||||
ret = (Map<String, Object>) ret.get("data");
|
||||
PacketSection error = (PacketSection) ret.get("error");
|
||||
if (!"00".equals(error.getString())) {
|
||||
throw new SydApiException(error.getInfo(), error.autoInt());
|
||||
}
|
||||
|
||||
return ((PacketSection) ret.get("data")).getBytes();
|
||||
}
|
||||
|
||||
public byte[] SM3HashSNaId(String sn, String userId, byte[] msg) {
|
||||
return SM3Hash(null, sn, null, userId, msg);
|
||||
}
|
||||
|
||||
@@ -39,9 +39,10 @@ public class ABCNorthBranch {
|
||||
|
||||
SM2PublicKey = api.SM2GetPublicKeyC(SM2PrivateKeyTag);
|
||||
SM2PrivateKey = api.SM2GetPrivateKeyC(SM2PrivateKeyTag);
|
||||
SM4Key = new String(Util.hexString2Bytes(Util.bytes2HexString((byte[]) api.readKey(SM4PrivateKeyTag).get("key"))));
|
||||
|
||||
|
||||
SM4Key = new String((byte[]) api.readKey(SM4PrivateKeyTag).get("key"));
|
||||
|
||||
System.out.println("=========================================密钥获取完成=========================================");
|
||||
}
|
||||
|
||||
|
||||
@@ -776,6 +776,8 @@ public class TestAllMethods {
|
||||
String index = "333333333333333300A00000001";
|
||||
RetWrap retWrap = api.readKey(index);
|
||||
printRetWrap(retWrap);
|
||||
|
||||
System.out.println("aaaaaaaa: " + new String((byte[]) retWrap.get("key")));
|
||||
}
|
||||
|
||||
// 测试通过
|
||||
@@ -932,9 +934,10 @@ public class TestAllMethods {
|
||||
// String index = "1111111111111148";
|
||||
// 0342000450420312F4ABAD98AA8EFC1F8F8204BD9E2F752C59C25A4025E675EDA5FB2337A449E00241EFA4A2F76A6C58D9834D6F0AB1164652E9C588E0EBD539C8ECB9EF
|
||||
|
||||
// 1111111111111149 000 00000001
|
||||
String index = "1111111111111149";
|
||||
// 03420004080589A33A4DB304A3C48355761AC216B8BB5493966996E532B664A5B9CD8F1374F0DAACBF3F6D1F0E48E10DAA91889DB632FF4BE19D903502680D1AB56584D5
|
||||
// 1111111111111151 000 00000001
|
||||
String index = "1111111111111151";
|
||||
// 034200048043AF118B45629857DB693105849B2617FED249D59DFD29BE9A891ADEE7441A2D8C62020953DAEF038184E0244310CF2123C507F26F5380FFECC8D53E79B24E
|
||||
// 00010000BEF3ECEF9CC88ED5F1159F2B18DCFC648D9FF6A8D6F36516F0333B106805A9B30000000000000000000000000000000000000000000000000000000000000000
|
||||
|
||||
// SM2
|
||||
RetWrap retWrap = api.SM2OrRSAGenKeyPair(1, index, 0);
|
||||
@@ -1296,6 +1299,19 @@ public class TestAllMethods {
|
||||
printRetWrap(retWrap1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecryptDE4() {
|
||||
String sn = "1004282452";
|
||||
|
||||
RetWrap retWrap = api.generateDEbyGS(sn, "00001111222233");
|
||||
String CipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY);
|
||||
String sessionKey = (String) retWrap.get(SydApi.RET_SESSION_KEY);
|
||||
printRetWrap(retWrap);
|
||||
|
||||
RetWrap retWrap1 = api.decryptDE(sn, CipherKey);
|
||||
printRetWrap(retWrap1);
|
||||
}
|
||||
|
||||
// 测试通过
|
||||
// 6C
|
||||
@Test
|
||||
@@ -1684,16 +1700,36 @@ public class TestAllMethods {
|
||||
// 78
|
||||
@Test
|
||||
public void testSM2DecryptC() {
|
||||
String certId = "1111111111111122";
|
||||
String publicKey = "0342000469DE3847DD6A66DA96DB8F2DCFA32E10E680FF2EF4A592079E7C3A44320BB15084E7CA9782A39B6E28F07C04FE00D68958A2605921E71712D56C1E4435A39FA5";
|
||||
String orgData = "FFFFFFFFFFFFFFFF";
|
||||
String certId = "1111111111111151";
|
||||
String publicKey = "034200048043AF118B45629857DB693105849B2617FED249D59DFD29BE9A891ADEE7441A2D8C62020953DAEF038184E0244310CF2123C507F26F5380FFECC8D53E79B24E";
|
||||
String orgData = "FFFFFFFFFFF1111111111FFFFF";
|
||||
String s = api.SM2Encrypt(Util.hexString2Bytes(publicKey), orgData.getBytes());
|
||||
|
||||
System.out.println("加密后的数据: " + s);
|
||||
byte[] pOrgData = SYMUtil.base64EnData2DerEnData(s);
|
||||
System.out.println("加密后的数据解base64-2: " + Util.bytes2HexString(pOrgData));
|
||||
|
||||
byte[] bytes = api.SM2DecryptC(certId, s);
|
||||
|
||||
System.out.println("decData:" + new String(bytes));
|
||||
}
|
||||
|
||||
// 测试通过
|
||||
// 78
|
||||
@Test
|
||||
public void testSM2DecryptOrder() {
|
||||
String certId = "1111111111111151";
|
||||
String publicKey = "034200048043AF118B45629857DB693105849B2617FED249D59DFD29BE9A891ADEE7441A2D8C62020953DAEF038184E0244310CF2123C507F26F5380FFECC8D53E79B24E";
|
||||
String orgData = "FfffffffffffffFfffffffffffffffff";
|
||||
String s = api.SM2EncryptOrder(Util.hexString2Bytes(publicKey), orgData.getBytes());
|
||||
|
||||
System.out.println("加密后的数据: " + s);
|
||||
|
||||
byte[] bytes = api.SM2DecryptOrder(certId, s);
|
||||
|
||||
System.out.println("decData:" + new String(bytes));
|
||||
}
|
||||
|
||||
// QQ
|
||||
@Test
|
||||
public void testSM2GetPublicKeyC() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.sunyard.sydapi.test;
|
||||
|
||||
import com.sunyard.RetWrap;
|
||||
import com.sunyard.SydApi;
|
||||
import com.sunyard.cert.X509;
|
||||
import com.sunyard.proto.Util;
|
||||
import org.junit.After;
|
||||
@@ -11,6 +12,8 @@ import racal.sunyard.main.SydApi4j;
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
|
||||
import static com.sunyard.sydapi.util.PrintUtil.printRetWrap;
|
||||
|
||||
/**
|
||||
* 甘肃银行数字货币
|
||||
*/
|
||||
@@ -26,10 +29,19 @@ public class TestGSYH {
|
||||
public void before() {
|
||||
// 通过设置debug的属性开启debug,如果不设置则默认不打开
|
||||
System.setProperty("com.sunyard.sydapi4j.debug", "true");
|
||||
api = (SydApi4j) new SydApi4j().connect("192.168.0.66", 8889, null, 1000);
|
||||
api = (SydApi4j) new SydApi4j().connect("61.164.40.82", 8889, null, 1000);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
try {
|
||||
this.api.disconnect();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test02() {
|
||||
Base64.Encoder encoder = Base64.getEncoder();
|
||||
@@ -38,24 +50,25 @@ public class TestGSYH {
|
||||
// 2.
|
||||
String data = "1111111111111111";
|
||||
// 随机生成对称密钥,由指定的公钥加密生成数字信封
|
||||
RetWrap retWrap = api.generateDE(sn, (byte) 0x31);
|
||||
String sessionKey = (String) retWrap.get("SessionKey");
|
||||
RetWrap retWrap = api.generateDEbyGS(sn, SydApi.ALG_SM4);
|
||||
String sessionKey = (String) retWrap.get(SydApi.RET_SESSION_KEY);
|
||||
|
||||
// sm4加密账号等数据
|
||||
byte[] dataEnc = api.SYMEncryptData(3, sessionKey, data.getBytes());
|
||||
byte[] dataEnc = api.SYMEncryptData(SydApi.NALG_SM4, sessionKey, data.getBytes());
|
||||
// base64转码
|
||||
byte[] dataEncBs64 = encoder.encode(dataEnc);
|
||||
|
||||
// 将sm2加密后的数据进行base64转码
|
||||
String cipherKey = (String) retWrap.get("CipherKey");
|
||||
byte[] cipherKeyBs64 = encoder.encode(cipherKey.getBytes());
|
||||
System.out.println("dataEncBs64: " + Util.bytes2HexString(dataEncBs64));
|
||||
|
||||
// 将sm2加密后的数据进行base64转码
|
||||
String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY);
|
||||
byte[] cipherKeyBs64 = encoder.encode(cipherKey.getBytes());
|
||||
|
||||
// 3.
|
||||
// 报文正文
|
||||
String msg = "12313146464564";
|
||||
// 对报文正文签名(内部会计算hash)
|
||||
String msgSign = api.netSign(sn1, msg.getBytes());
|
||||
String msgSign = api.netGSSign(sn1, msg.getBytes());
|
||||
// base64转码
|
||||
byte[] msgSignBs64 = encoder.encode(msgSign.getBytes());
|
||||
|
||||
@@ -65,31 +78,22 @@ public class TestGSYH {
|
||||
// base64解码
|
||||
byte[] msgSignB = decoder.decode(msgSignBs64);
|
||||
// 对报文验签
|
||||
boolean b = api.netVerify(sn1, dataEncBs64, new String(msgSignB));
|
||||
boolean b = api.netGSVerify(sn1, msg.getBytes(), new String(msgSignB));
|
||||
System.out.println("验签结果: " + b);
|
||||
|
||||
// 8.
|
||||
byte[] cipherKeyB = decoder.decode(cipherKeyBs64);
|
||||
// 解密数字信封获取对称密钥
|
||||
RetWrap retWrap1 = api.decryptDE(sn, new String(cipherKeyB));
|
||||
sessionKey = (String) retWrap1.get("SessionKey");
|
||||
sessionKey = (String) retWrap1.get(SydApi.RET_SESSION_KEY);
|
||||
|
||||
// 9.
|
||||
// 使用对称密钥解密报文
|
||||
dataEnc = decoder.decode(dataEncBs64);
|
||||
byte[] bytes1 = api.SYMDecryptData(3, sessionKey, dataEnc);
|
||||
byte[] bytes1 = api.SYMDecryptData(SydApi.NALG_SM4, sessionKey, dataEnc);
|
||||
System.out.println("data: " + new String(bytes1));
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
try {
|
||||
this.api.disconnect();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 测试通过
|
||||
// 8017
|
||||
@Test
|
||||
@@ -102,7 +106,7 @@ public class TestGSYH {
|
||||
* @param nCertType 证书类型,0:签名证书, 1:加密证书
|
||||
* @return base64 编码的证书
|
||||
*/
|
||||
String s = api.GetX509CertFileBySN(sn2, 0);
|
||||
String s = api.GetX509CertFileBySN(sn2, SydApi.FOR_SIGN);
|
||||
System.out.println(s);
|
||||
|
||||
/**
|
||||
@@ -115,34 +119,6 @@ public class TestGSYH {
|
||||
System.out.println("证书主题DN: " + x509.getSubject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportCert2() throws IOException {
|
||||
|
||||
String cert2 = "-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIB4TCCAYSgAwIBAgIIPJMAAAAAACswDAYIKoEcz1UBg3UFADAmMQswCQYDVQQG\n" +
|
||||
"EwJDTjEXMBUGA1UEAwwOU3VueWFyZFNNMlJvb3QwHhcNMTcxMTE3MDIzMDUxWhcN\n" +
|
||||
"MjMwMTI1MDIzMDUxWjBZMQswCQYDVQQGEwJDTjELMAkGA1UECAwCWkoxCzAJBgNV\n" +
|
||||
"BAcMAkhaMQ4wDAYDVQQKDAVISkpZUzERMA8GA1UECwwIMDAwMDAwMDAxDTALBgNV\n" +
|
||||
"BAMMBDIyMjIwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAATxqegqlmc/lduzBaKR\n" +
|
||||
"EyeNuPf78RA3wfJuhAv8zymLwQ6doefs1Iul+kMOukhfwY9aEhVdqws34FZMm2vs\n" +
|
||||
"1+wXo2cwZTAOBgNVHQ8BAf8EBAMCAMAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYD\n" +
|
||||
"VR0jBBgwFoAU93/arv8hxtk6eq2g+6z+AqVO1cEwHQYDVR0OBBYEFHfjFl72707A\n" +
|
||||
"6s+YVuGvEuyvFWTMMAwGCCqBHM9VAYN1BQADSQAwRgIhALzg7+QW7RU4phv+4arE\n" +
|
||||
"v0IOeaA6dtR8VT4Bwin9oHTWAiEA9kLESGiYm8L5Htf7GBXgH+pk7BJ68clml41B\n" +
|
||||
"/ejZglI=\n" +
|
||||
"-----END CERTIFICATE-----";
|
||||
|
||||
String organizationId = "00000000";
|
||||
|
||||
/**
|
||||
* 上传指定证书到加密设备
|
||||
* @param certData 证书的字节数组
|
||||
* @param organizationId 机构号的字节数组
|
||||
* @return
|
||||
*/
|
||||
RetWrap retWrap = api.importCert(Util.getSafeBytes(cert2), organizationId.getBytes());
|
||||
System.out.println(retWrap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testimportCertAddHT() {
|
||||
@@ -202,45 +178,75 @@ public class TestGSYH {
|
||||
System.out.println("证书公钥: " + Util.bytes2HexString(x509.getPubKey()));
|
||||
}
|
||||
|
||||
|
||||
// 测试通过
|
||||
// 78
|
||||
@Test
|
||||
public void test() {
|
||||
// 证书序号
|
||||
String sn = "1004282451";
|
||||
String data = "111";
|
||||
public void testSM2DecryptC() {
|
||||
String certId = "1111111111111151";
|
||||
String publicKey = "034200048043AF118B45629857DB693105849B2617FED249D59DFD29BE9A891ADEE7441A2D8C62020953DAEF038184E0244310CF2123C507F26F5380FFECC8D53E79B24E";
|
||||
|
||||
String orgData = "FFFFFFFFFFFFFFFF";
|
||||
String s = api.SM2Encrypt(Util.hexString2Bytes(publicKey), orgData.getBytes());
|
||||
|
||||
System.out.println("加密后的数据: " + s);
|
||||
System.out.println("加密后的数据解base64: " + Util.bytes2HexString(Base64.getDecoder().decode(s)));
|
||||
|
||||
byte[] bytes = api.SM2DecryptC(certId, s);
|
||||
|
||||
System.out.println("decData:" + new String(bytes));
|
||||
}
|
||||
|
||||
// 测试通过
|
||||
// 78
|
||||
@Test
|
||||
public void testSM2DecryptOrder() {
|
||||
String certId = "1111111111111151";
|
||||
String publicKey = "034200048043AF118B45629857DB693105849B2617FED249D59DFD29BE9A891ADEE7441A2D8C62020953DAEF038184E0244310CF2123C507F26F5380FFECC8D53E79B24E";
|
||||
String orgData = "FfffffffffffffFfffffffffffffffff";
|
||||
|
||||
/**
|
||||
* 用指定的证书私钥对指定的数据进行数字签名。
|
||||
* @param pCertSerial 输入。签名 X509 证书的序列号。
|
||||
* @param pOrgData 输入。 待签名的原始数据。
|
||||
* @return 签名数据(BASE64 编码)。
|
||||
* 用指定的 SM2 公钥对指定的密文数据进行加密。
|
||||
* 输出的sm2密文结构为C1C2C3格式
|
||||
* @param publicKey 公钥钥串,DER 编码,HEX 格式。
|
||||
* @param pOrgData 加密的数据。
|
||||
* @return 加密的数据 base64 编码。
|
||||
*/
|
||||
String s = api.netSign(sn, data.getBytes());
|
||||
String s = api.SM2EncryptOrder(Util.hexString2Bytes(publicKey), orgData.getBytes());
|
||||
|
||||
System.out.println("加密后的数据: " + s);
|
||||
|
||||
/**
|
||||
* 用指定证书对指定的原始数据进行数字签名验证。
|
||||
* @param pCertSerial 输入。 签名 X509 证书的序列号。
|
||||
* @param pOrgData 输入。 待签名的原始数据。
|
||||
* @param pSignData 输入。 签名数据(BASE64 编码)。
|
||||
* @return true 表示验证正确;false 表示失败;
|
||||
* 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。
|
||||
* 输入的sm2密文结构为C1C2C3格式
|
||||
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
|
||||
* @param enData 加密的数据,base64 编码。
|
||||
* @return 明文数据。
|
||||
*/
|
||||
// 12、对正文进行验签(内部会计算hash)
|
||||
boolean b = api.netVerify(sn, data.getBytes(), s);
|
||||
System.out.println(b);
|
||||
byte[] bytes = api.SM2DecryptOrder(certId, s);
|
||||
|
||||
System.out.println("decData:" + new String(bytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecryptDE4() {
|
||||
String sn = "1004282452";
|
||||
|
||||
String sn1 = "1004282452";
|
||||
/**
|
||||
* 产生对称密钥,通过公钥加密生成网联格式的数字信封。
|
||||
*
|
||||
* @param certSerial 对*方 X509 证书的序列号。
|
||||
* @param nAlg 算法标识,0:AES,1:SM4
|
||||
* @param orgCode 机构码
|
||||
* @return RetWrap 包含 CipherKey, SessionKey, KCV
|
||||
* CipherKey 公钥加密的会话密钥 ,BASE64 编码
|
||||
* SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。
|
||||
* KCV 会话密钥的检验值,HEX 格式,长度为 32H。
|
||||
*/
|
||||
RetWrap retWrap = api.generateDE(sn1, (byte) 0x31);
|
||||
String CipherKey = (String) retWrap.get("CipherKey");
|
||||
RetWrap retWrap = api.generateDEbyGS(sn, "00001111222233");
|
||||
String CipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY);
|
||||
String sessionKey = (String) retWrap.get(SydApi.RET_SESSION_KEY);
|
||||
String kcv = (String) retWrap.get(SydApi.RET_KCV);
|
||||
printRetWrap(retWrap);
|
||||
|
||||
/**
|
||||
* 接收用私钥解密数字信封,还原对称密钥。
|
||||
@@ -250,110 +256,38 @@ public class TestGSYH {
|
||||
* @return RetWrap 包含 SessionKey KCV
|
||||
* SessionKey 输出。 本地LMK 加密的会话密钥,格式为:密钥类型|密钥密文,比如:02|密钥密文
|
||||
* KCV 会话密钥的检验值,HEX 格式,长度为 36H。
|
||||
* orgCode 如果有机构码的话会返回机构码
|
||||
*/
|
||||
// 13、解密数字信封获取对称密钥
|
||||
RetWrap rw = api.decryptDE(sn1, CipherKey);
|
||||
String sessionKey = (String) rw.get("SessionKey");
|
||||
|
||||
/**
|
||||
* 用输入的会话密钥,对指定报文数据进行加密处理。填充模式为1
|
||||
*
|
||||
* @param nAlg 算法标识. 3:SM4。
|
||||
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
|
||||
* @param pINdata 要加密的报文明文。必须是 8 或16 的倍数。
|
||||
* @return 输出的报文密文, 长度为报文明文 + 16
|
||||
*/
|
||||
byte[] bytes = api.SYMEncryptData(3, sessionKey, "1111111111111111".getBytes());
|
||||
|
||||
/**
|
||||
* 用输入的会话密钥,对指定报文数据进行解密处理。填充模式为1
|
||||
*
|
||||
* @param nAlg 算法标识.3:SM4。
|
||||
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
|
||||
* @param pINdata 要解密的报文密文。长度必须是8 或16 的倍数。
|
||||
* @return 输出的报文明文。
|
||||
*/
|
||||
// 13、使用对称密钥解密敏感数据
|
||||
byte[] bytes1 = api.SYMDecryptData(3, sessionKey, bytes);
|
||||
System.out.println(new String(bytes1));
|
||||
|
||||
RetWrap retWrap1 = api.decryptDE(sn, CipherKey);
|
||||
printRetWrap(retWrap1);
|
||||
}
|
||||
|
||||
|
||||
// 签名验签流程
|
||||
@Test
|
||||
public void testNetGSSign() {
|
||||
// 本行的
|
||||
String sn = "10000000000000000000001042580423";
|
||||
String data = "111";
|
||||
// =========================工具方法=====================
|
||||
|
||||
/**
|
||||
* 用指定的证书私钥对指定的数据进行数字签名。
|
||||
* 最大签名原始数据为8161byte
|
||||
* @param publicKey 输入。公钥。
|
||||
* @param pCertSerial 输入。签名 X509 证书的序列号。
|
||||
* @param pOrgData 输入。 待签名的原始数据。
|
||||
* @return 签名数据(BASE64 编码)。
|
||||
*/
|
||||
String sign = api.netGSSign(sn, data.getBytes());
|
||||
System.out.println("签名结果: " + sign);
|
||||
|
||||
/**
|
||||
* 用指定证书对指定的原始数据进行数字签名验证。
|
||||
* @param publicKey 输入。公钥。
|
||||
* @param pCertSerial 输入。 签名 X509 证书的序列号。
|
||||
* @param pOrgData 输入。 待签名的原始数据。
|
||||
* @param pSignData 输入。 签名数据(BASE64 编码)。
|
||||
* @return true 表示验证正确;false 表示失败;
|
||||
*/
|
||||
boolean b = api.netGSVerify(sn, data.getBytes(), sign);
|
||||
System.out.println("验签结果: " + b);
|
||||
public static void printRetWrap(RetWrap rw) {
|
||||
printRetWrap(rw, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出
|
||||
* @param rw
|
||||
*/
|
||||
public static void printRetWrap(RetWrap rw, boolean flag) {
|
||||
for (String s : rw.keySet()) {
|
||||
|
||||
@Test
|
||||
public void testVerify() {
|
||||
|
||||
String orgData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<Document xmlns=\"urn:cbcc:std:dcep:2020:tech:xsd:dcep.433.001.01\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
|
||||
" <BankAttAcctReq>\n" +
|
||||
" <GrpHdr>\n" +
|
||||
" <MsgId>20211231058043300311422380336000</MsgId>\n" +
|
||||
" <CreDtTm>2021-12-31T14:22:38</CreDtTm>\n" +
|
||||
" <InstgPty>\n" +
|
||||
" <InstgDrctPty>C1030131001288</InstgDrctPty>\n" +
|
||||
" </InstgPty>\n" +
|
||||
" <InstdPty>\n" +
|
||||
" <InstdDrctPty>C1175662000017</InstdDrctPty>\n" +
|
||||
" </InstdPty>\n" +
|
||||
" </GrpHdr>\n" +
|
||||
" <MgmtTp>MT01</MgmtTp>\n" +
|
||||
" <SgnInf>\n" +
|
||||
" <SgnAcctPtyId>C1175662000017</SgnAcctPtyId>\n" +
|
||||
" <SgnAcctTp>AT00</SgnAcctTp>\n" +
|
||||
" <SgnAcctId>983zGfqfC3O7xbgYwsW9TfRp1ddVT7vfaAAGhZ7Y7M0=</SgnAcctId>\n" +
|
||||
" <SgnAcctNm>VbuPbl33/yi8OsQkme0kqZ0Tmvf8eJIyngC8CRyIk8E=</SgnAcctNm>\n" +
|
||||
" <IDTp>IT01</IDTp>\n" +
|
||||
" <IDNo>v1NPE/GPSooCXY4Z4RomtgDGpLxcm7RnF/VS16LEd3U=</IDNo>\n" +
|
||||
" <Tel>G8DUftbIJTJpjrIgvoF3KQ==</Tel>\n" +
|
||||
" <SgnTp>SG01</SgnTp>\n" +
|
||||
" </SgnInf>\n" +
|
||||
" <WltInf>\n" +
|
||||
" <WltPtyId>C1030131001288</WltPtyId>\n" +
|
||||
" <WltId>ZyBTxt3R/zN6AD7KqWotug==</WltId>\n" +
|
||||
" <WltTp>WT01</WltTp>\n" +
|
||||
" <WltLvl>WL01</WltLvl>\n" +
|
||||
" </WltInf>\n" +
|
||||
" </BankAttAcctReq>\n" +
|
||||
"</Document>";
|
||||
|
||||
String sn = "10000000000000000000001042580423";
|
||||
|
||||
String sign = "MEUCIGpByl+Q1uSLXVPHdRvPXufgGEru+kUDj13jBY68b3NrAiEA3WbN3tYTCK7GRIsfnVA+3jbGTYluKs/Xz+JZkFZ4tIM=";
|
||||
|
||||
boolean b = api.netGSVerify(sn, orgData.getBytes(), sign);
|
||||
System.out.println("验签结果: " + b);
|
||||
Object o = rw.get(s);
|
||||
if (o instanceof String) {
|
||||
System.out.println(s + ":" + o);
|
||||
} else if (o instanceof byte[]) {
|
||||
if (flag) {
|
||||
System.out.println(s + ": " + Util.bytes2HexString((byte[]) o));
|
||||
} else {
|
||||
System.out.println(s + ": " + new String((byte[]) o));
|
||||
}
|
||||
} else {
|
||||
System.out.println(s + ":" + o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -40,20 +40,33 @@ public class TestHT {
|
||||
@Test
|
||||
public void testSM2ConfirmSessionKeyC() {
|
||||
|
||||
String userId = "1111111111111149";
|
||||
String userId = "1111111111111151";
|
||||
String data = "12343242";
|
||||
|
||||
String pk = api.SM2GetPublicKeyC(userId, 1);
|
||||
// 通过用户id获取公钥
|
||||
String pk = api.SM2GetPublicKeyC(userId, SydApi.FOR_ENCRYPT);
|
||||
|
||||
// 生成数字信封
|
||||
RetWrap retWrap = api.SM2GenSessionKey(pk);
|
||||
printRetWrap(retWrap);
|
||||
String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY);
|
||||
String sessionKey = (String) retWrap.get(SydApi.RET_SESSION_KEY);
|
||||
String kcv = (String) retWrap.get(SydApi.RET_KCV);
|
||||
|
||||
// 使用生成的对称密钥加密数据
|
||||
byte[] dataEnc = api.SYMEncryptData(SydApi.NALG_SM4, sessionKey, data.getBytes());
|
||||
|
||||
|
||||
|
||||
// 解密数字信封
|
||||
RetWrap retWrap1 = api.SM2ConfirmSessionKeyC(userId, cipherKey);
|
||||
printRetWrap(retWrap1);
|
||||
sessionKey = (String) retWrap1.get(SydApi.RET_SESSION_KEY);
|
||||
kcv = (String) retWrap1.get(SydApi.RET_KCV);
|
||||
|
||||
// 使用解密出来的对称密钥解密数据
|
||||
byte[] bytes1 = api.SYMDecryptData(SydApi.NALG_SM4, sessionKey, dataEnc);
|
||||
System.out.println("解密后的数据:" + new String(bytes1));
|
||||
}
|
||||
|
||||
// 测试通过
|
||||
|
||||
Reference in New Issue
Block a user