diff --git a/DProto/8018.xml b/DProto/8018.xml index e9cf04e..12f757b 100644 --- a/DProto/8018.xml +++ b/DProto/8018.xml @@ -1,7 +1,6 @@ - 8018 @@ -11,7 +10,7 @@ X509证书序号 - + 数据长度 @@ -20,14 +19,12 @@ - - - - + + - 8006 + 8019 @@ -71,7 +68,7 @@ - + 签名的字节长度 @@ -80,14 +77,22 @@ - - - - + + + \ No newline at end of file diff --git a/DProto/8019.xml b/DProto/8019.xml index 2f01c74..a613619 100644 --- a/DProto/8019.xml +++ b/DProto/8019.xml @@ -1,23 +1,18 @@ - 8019 - - X509证书序号 - - 已签名数据长度 - + 已签名数据 - + @@ -31,14 +26,12 @@ - - - - + + - 8007 + 8020 @@ -82,11 +75,11 @@ - + 信息长度 - + 若发送报文返回证书信息标志位为0,则返回已签名数据, 若发送报文返回证书信息标志位为1,则返回CERT_INFO结构的证书数据 @@ -94,12 +87,25 @@ - - + \ No newline at end of file diff --git a/doc/java接口说明文档.docx b/doc/java接口说明文档.docx index be1c127..307f873 100644 Binary files a/doc/java接口说明文档.docx and b/doc/java接口说明文档.docx differ diff --git a/src/main/java/com/sunyard/inf/SydSVApi.java b/src/main/java/com/sunyard/inf/SydSVApi.java index a74c5ec..ed87360 100644 --- a/src/main/java/com/sunyard/inf/SydSVApi.java +++ b/src/main/java/com/sunyard/inf/SydSVApi.java @@ -167,6 +167,28 @@ interface SydAttachedSVApi { byte[] orgData, String sign ); + + /** + * 带公钥证书与原始数据的数字签名(遵循 PKCS#7) + * 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制带公钥证书的数字签名(遵循 PKCS#7)。 + * + * @param orgData 待签名数据 + * @param sCertDN 证书DN + * @return + * 符合PKCS7标准的签名结果 + */ + String attachedSign(byte[] orgData, String sCertDN); + + /** + * 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7) + * 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。 + * + * @param sign 已签名数据 + * @return + * 若发送报文返回证书信息标志位为0,则返回已签名数据, + * 若发送报文返回证书信息标志位为1,则返回CERT_INFO结构的证书数据 + */ + X509 attachedVerify(String sign); } diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index e9d5924..ea3af6d 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -9668,6 +9668,121 @@ public class SydApi4j implements SydApi { } + /** + * 带公钥证书与原始数据的数字签名(遵循 PKCS#7) + * 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制带公钥证书的数字签名(遵循 PKCS#7)。 + * + * @param orgData 待签名数据 + * @param sCertDN 证书DN + * @return + * 符合PKCS7标准的签名结果 + */ + @Override + public String attachedSign(byte[] orgData, String sCertDN) { + Proto8018 proto = new Proto8018(); //pset.getProtocolReqRender("75"); + byte[] dn = new byte[256]; + byte[] s = null; + try { + s = sCertDN.getBytes("GBK"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + System.arraycopy(s, 0, dn, 0, s.length); + + // 填充数据 + HashMap packet = new HashMap(); + HashMap data = new HashMap(); + packet.put("data", data); + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("DN", dn); + data.put("infoData", orgData); + + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + Packet p = proto.parse(bb); + Map ret = p.toMap(); + + if ( + !Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes()) + ) { + throw new SydApiException("包序号不匹配", -4); + } + ret = (Map) ret.get("data"); + PacketSection error = (PacketSection) ret.get("error"); + byte[] be = error.getBytes(); + if ((0 != (be[0] ^ be[1]))) { + + throw new SydApiException(error.getInfo(), error.autoInt()); + } + + return ((PacketSection) ret.get("signature")).getString(); + } + + /** + * 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7) + * 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。 + * + * @param sign 已签名数据 + * @return + * 返回CERT_INFO结构的证书数据 + */ + @Override + public X509 attachedVerify(String sign) { + Proto8019 proto = new Proto8019(); //pset.getProtocolReqRender("75"); + + // 填充数据 + HashMap packet = new HashMap(); + HashMap data = new HashMap(); + packet.put("data", data); + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + + data.put("signData", sign.getBytes()); + data.put("flag$option", 1); + + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + Packet p = proto.parse(bb, packet); + Map ret = p.toMap(); + + if ( + !Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes()) + ) { + throw new SydApiException("包序号不匹配", -4); + } + ret = (Map) ret.get("data"); + PacketSection error = (PacketSection) ret.get("error"); + byte[] be = error.getBytes(); + if ((0 != (be[0] ^ be[1]))) { + return null; + } + + PacketSection info = (PacketSection) ret.get("info"); + byte[] pCertInfo = info.getBytes(); + + String certInfo = new String(pCertInfo); + int index = certInfo.indexOf("-----BEGIN CERTIFICATE-----"); + certInfo = certInfo.substring(index); +// System.out.println("证书信息: " + certInfo); + X509 x509 = GetX509CertInfo(certInfo); + return x509; + } + + // ------------------------中移指令接口-------------------------------- /** diff --git a/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java b/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java index dc0b99b..64afa2f 100644 --- a/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java +++ b/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java @@ -30,7 +30,8 @@ public class TestAllMethods { 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); +// api = (SydApi4j) new SydApi4j().connect("192.168.0.66", 8889, null, 1000); // api = (SydApi4j) new SydApi4j().connect("192.168.0.100", 8889, null, 1000); // api = (SydApi4j) new SydApi4j().connect("192.168.0.99", 8889, null, 1000); // api = (SydApi4j) new SydApi4j().connect("172.16.17.162", 8889, null, 1000); @@ -2088,6 +2089,20 @@ public class TestAllMethods { System.out.println(s); } + // todo: 需要测试 + // 8018 + @Test + public void testAttachedSignAndVerify() { + String dn = "C=CN,O=Sunyard,OU=8001,CN=8001"; + String orgData = "111111213323143243243"; + String sign = api.attachedSign(orgData.getBytes(), dn); + System.out.println("签名结果: " + sign); + +// String sign = "MIICsgYKKoEcz1UGAQQCAqCCAqIwggKeAgEBMQwwCgYIKoEcz1UBgxEwIAYKKoEcz1UGAQQCAaASBBAzMjE0MzEyMzQxMjQzMjE0oIIByTCCAcUwggFooAMCAQICCDyTAAAAAAAlMAwGCCqBHM9VAYN1BQAwJjELMAkGA1UEBhMCQ04xFzAVBgNVBAMMDlN1bnlhcmRTTTJSb290MB4XDTE3MDUxNzAyNTI0NFoXDTIyMDcyNTAyNTI0NFowPTELMAkGA1UEBhMCQ04xEDAOBgNVBAoMB1N1bnlhcmQxDTALBgNVBAsMBDgwMDExDTALBgNVBAMMBDgwMDEwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAQ+2joQe3zDXMAFx/vwu05rQ6B+4U42BgPSLsoqYAstD6AwVdQA0SQDAPVGSLhJ0T9QszD/FDUbVkWxNoaCCmW7o2cwZTAOBgNVHQ8BAf8EBAMCAMAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgwFoAU93/arv8hxtk6eq2g+6z+AqVO1cEwHQYDVR0OBBYEFAMWZaY2AwaQTNiFLpsa0dyCzBZ6MAwGCCqBHM9VAYN1BQADSQAwRgIhAIl2ZHGfln5hedcousARzZ2yeUjUbxSFMmhMmr5t6Q6nAiEAvqYX/KpIcvnPyB/Yiil+oq6DFdVM6P3vDxBhU/8taXExgZswgZgCAQEwMjAmMQswCQYDVQQGEwJDTjEXMBUGA1UEAwwOU3VueWFyZFNNMlJvb3QCCDyTAAAAAAAlMAoGCCqBHM9VAYMRMAsGCSqBHM9VAYItAQRGMEQCIEons2hit2967ciJo3QipM4lJgd1K3QmwOp9O/n8Tl86AiB9V6Z7jQogZFtoIz6kwAI6OQVnjbtJlmO31bZxgYRwKg=="; + X509 verify = api.attachedVerify(sign); + System.out.println("验签结果: " + Util.bytes2HexString(verify.getPubKey())); + } + // 00883030303030303030 // 3938 // 30313232