diff --git a/DProto/6A.xml b/DProto/6A.xml index e04ff48..30f4544 100644 --- a/DProto/6A.xml +++ b/DProto/6A.xml @@ -17,6 +17,10 @@ + + 可选,存在,则固定值为‘P’ + + diff --git a/doc/java接口说明文档.docx b/doc/java接口说明文档.docx index 5c7e10b..be1c127 100644 Binary files a/doc/java接口说明文档.docx and b/doc/java接口说明文档.docx differ diff --git a/src/main/java/com/sunyard/inf/SydCertApi.java b/src/main/java/com/sunyard/inf/SydCertApi.java index 70167c4..251f09b 100644 --- a/src/main/java/com/sunyard/inf/SydCertApi.java +++ b/src/main/java/com/sunyard/inf/SydCertApi.java @@ -89,7 +89,7 @@ public interface SydCertApi { ); /** - * 从签名中获取证书 + * 从签名中获取证书并上载到加密机 * @param orgData 待签名的原始数据 * @param sign 签名数据 * @return 证书信息(包含公钥字段) @@ -120,4 +120,12 @@ public interface SydCertApi { */ RetWrap importCert(byte[] certData, byte[] organizationId); + /** + * 上传指定证书到加密设备,并在证书前后加上begin和end + * @param certData 证书的字节数组 + * @param organizationId 机构号的字节数组 + * @return + */ + RetWrap importCertAddHT(String certData, byte[] organizationId); + } diff --git a/src/main/java/com/sunyard/inf/SydGenApi.java b/src/main/java/com/sunyard/inf/SydGenApi.java index f96fed7..e13a18e 100644 --- a/src/main/java/com/sunyard/inf/SydGenApi.java +++ b/src/main/java/com/sunyard/inf/SydGenApi.java @@ -216,6 +216,18 @@ public interface SydGenApi { */ RetWrap generateDEByDn(byte[] dn, int alg, int model) throws Exception; + /** + * 产生对称密钥,通过公钥加密生成网联格式的数字信封。 + + * @param certSerial 对*方 X509 证书的序列号。 + * @param nAlg 算法标识,0:AES,1:SM4 + * @return RetWrap 包含 CipherKey, SessionKey, KCV + * CipherKey 公钥加密的会话密钥 ,BASE64 编码 + * SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。 + * KCV 会话密钥的检验值,HEX 格式,长度为 32H。 + */ + RetWrap generateDEbyGS(String certSerial, byte nAlg); + /** * 产生对称密钥,通过公钥加密生成网联格式的数字信封。 diff --git a/src/main/java/com/sunyard/inf/customize/SydQNUCApi.java b/src/main/java/com/sunyard/inf/customize/SydQNUCApi.java index 61da4ed..84bc52a 100644 --- a/src/main/java/com/sunyard/inf/customize/SydQNUCApi.java +++ b/src/main/java/com/sunyard/inf/customize/SydQNUCApi.java @@ -34,21 +34,19 @@ public interface SydQNUCApi { /** * 用指定的证书私钥对指定的数据进行数字签名。使用外部公钥做hash * 最大签名原始数据为8161byte - * @param publicKey 输入。公钥。 * @param pCertSerial 输入。签名 X509 证书的序列号。 * @param pOrgData 输入。 待签名的原始数据。 * @return 签名数据(BASE64 编码)。 */ - String netGSSign(String publicKey, String pCertSerial, byte[] pOrgData); + String netGSSign(String pCertSerial, byte[] pOrgData); /** * 用指定证书对指定的原始数据进行数字签名验证。使用外部公钥做hash - * @param publicKey 输入。公钥。 * @param pCertSerial 输入。 签名 X509 证书的序列号。 * @param pOrgData 输入。 待签名的原始数据。 * @param pSignData 输入。 签名数据(BASE64 编码)。 * @return true 表示验证正确;false 表示失败; */ - boolean netGSVerify(String publicKey, String pCertSerial, byte[] pOrgData, String pSignData); + boolean netGSVerify(String pCertSerial, byte[] pOrgData, String pSignData); } diff --git a/src/main/java/com/sunyard/util/CoderUtil.java b/src/main/java/com/sunyard/util/CoderUtil.java index 99f21d8..26c57df 100644 --- a/src/main/java/com/sunyard/util/CoderUtil.java +++ b/src/main/java/com/sunyard/util/CoderUtil.java @@ -171,4 +171,33 @@ public class CoderUtil { } } + /** + * 将证书前后加上begin和end,中间添加换行 + * @param certData + * @return + */ + public static String certAddHT(String certData) { + final String head = "-----BEGIN CERTIFICATE-----\n"; + final String tail = "-----END CERTIFICATE-----"; + final String wrap = "\n"; + + int num = certData.length() % 64 == 0 ? certData.length() / 64: certData.length() / 64 + 1; + + StringBuilder sb = new StringBuilder(); + sb.append(head); + + for (int i = 0; i < num; i++) { + String substring; + if (i == num - 1) { + substring = certData.substring(i * 64); + } else { + substring = certData.substring(i * 64, (i + 1) * 64); + } + sb.append(substring).append(wrap); + } + sb.append(tail); + + return sb.toString(); + } + } diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index 6f181f7..e9d5924 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -971,6 +971,19 @@ public class SydApi4j implements SydApi { return r; } + /** + * + * @param certData + * @param organizationId + * @return + */ + @Override + public RetWrap importCertAddHT(String certData, byte[] organizationId) { + String cert = CoderUtil.certAddHT(certData); + + return importCert(Util.getSafeBytes(cert), organizationId); + } + // 测试通过 @Override public RetWrap importCert(byte[] certData, byte[] organizationId) { @@ -2114,8 +2127,17 @@ public class SydApi4j implements SydApi { return rw; } + @Override + public RetWrap generateDEbyGS(String certSerial, byte nAlg) { + return generateDE(1, certSerial, nAlg); + } + @Override public RetWrap generateDE(String certSerial, byte nAlg) { + return generateDE(0, certSerial, nAlg); + } + + public RetWrap generateDE(int pFlag, String certSerial, byte nAlg) { // 获取协议 //ProtocolRender render = pset.getProtocolReqRender("6A"); Proto6A proto = new Proto6A(); @@ -2125,6 +2147,9 @@ public class SydApi4j implements SydApi { packet.put("header", sn.getSn().array()); HashMap data = new HashMap(); data.put("alg$option", nAlg - 0x30); + if (pFlag == 1) { + data.put("pFlag", 'P'); + } data.put("certificateModel$option", 0); data.put("certificateSn", certSerial.getBytes()); data.put("keyType", "X"); @@ -2453,14 +2478,14 @@ public class SydApi4j implements SydApi { return true; } - public String netGSSign(String publicKey, String pCertSerial, byte[] pOrgData) { - byte[] hash = SM3Hash(publicKey, pOrgData); - return _netSign(pCertSerial, hash); + @Override + public String netGSSign(String pCertSerial, byte[] pOrgData) { + return _netSign(pCertSerial, pOrgData); } - public boolean netGSVerify(String publicKey, String pCertSerial, byte[] pOrgData, String pSignData) { - byte[] hash = SM3Hash(publicKey, pOrgData); - return _netVerify(pCertSerial, hash, pSignData); + @Override + public boolean netGSVerify(String pCertSerial, byte[] pOrgData, String pSignData) { + return _netVerify(pCertSerial, pOrgData, pSignData); } // 测试通过 diff --git a/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java b/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java index 4d156b3..dc0b99b 100644 --- a/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java +++ b/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java @@ -4,6 +4,7 @@ import com.sunyard.RetWrap; import com.sunyard.SydApi; import com.sunyard.cert.X509; import com.sunyard.proto.Util; +import com.sunyard.util.CoderUtil; import com.sunyard.util.SYMUtil; import org.junit.After; import org.junit.Before; @@ -965,9 +966,9 @@ public class TestAllMethods { @Test public void testSM2ConfirmSessionKeyC() { - String userId = "1111111111111123"; + String userId = "1111111111111151"; - String pk="03420004AAFCB1EACA86272281A20FE1957EEB543AB97571048D5B6350C4227980D0F109A7D5797EC97D6D874D003C4AE7C5FBFFD755413264D85DA5B0AC61B6C661CA32"; + String pk="03420004E8582C0EF495E96D4FE20C8344097750546BD3EF3BE0E1931EF21D3977FBBC774264BA5D124EB9C72177556229B5FE289B2C15B3CD3BCA9F34C663A3B8EB851E"; RetWrap retWrap = api.SM2GenSessionKey(pk); printRetWrap(retWrap); @@ -1240,7 +1241,10 @@ public class TestAllMethods { String CipherKey = (String) retWrap.get("CipherKey"); String KCV = (String) retWrap.get("KCV"); + System.out.println("CipherKey: " + CipherKey); + RetWrap retWrap1 = api.decryptDE(sn, CipherKey); + sessionKey = (String) retWrap1.get("SessionKey"); printRetWrap(retWrap1); } @@ -1253,6 +1257,40 @@ public class TestAllMethods { String CipherKey = (String) retWrap.get("CipherKey"); printRetWrap(retWrap); + System.out.println("解base64: " + Util.bytes2HexString(Base64.getDecoder().decode(CipherKey))); + + RetWrap retWrap1 = api.decryptDE(sn, CipherKey); + printRetWrap(retWrap1); + } + + @Test + public void testDecryptDE3() { + String sn = "1004282452"; + + + /** + * 产生对称密钥,通过公钥加密生成网联格式的数字信封。 + * @param certSerial 对*方 X509 证书的序列号。 + * @param nAlg 算法标识,0:AES,1:SM4 + * @return RetWrap 包含 CipherKey, SessionKey, KCV + * CipherKey 公钥加密的会话密钥 ,BASE64 编码 + * SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。 + * KCV 会话密钥的检验值,HEX 格式,长度为 32H。 + */ + RetWrap retWrap = api.generateDEbyGS(sn, SydApi.ALG_SM4); + String CipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); + String sessionKey = (String) retWrap.get(SydApi.RET_SESSION_KEY); + printRetWrap(retWrap); + + /** + * 接收用私钥解密数字信封,还原对称密钥。 + * + * @param pCertSerial 输入。 对方 X509 证书的序列号。 + * @param pCipherKey 输入。 公钥加密的会话密钥,BASE64 编码 + * @return RetWrap 包含 SessionKey KCV + * SessionKey 输出。 本地LMK 加密的会话密钥,格式为:密钥类型|密钥密文,比如:02|密钥密文 + * KCV 会话密钥的检验值,HEX 格式,长度为 36H。 + */ RetWrap retWrap1 = api.decryptDE(sn, CipherKey); printRetWrap(retWrap1); } @@ -1302,47 +1340,26 @@ public class TestAllMethods { @Test public void testNetGSSign() { String sn = "1004282451"; - String data = "111"; - - /** - * 通过证书序号 sn 获取的 X509 证书文件。 - * @param sn sn,证书序号 - * @param nCertType 证书类型,0:签名证书, 1:加密证书 - * @return base64 编码的证书 - */ - String s = api.GetX509CertFileBySN(sn, 0); - System.out.println(s); - - /** - * 输入 X509 格式的证书,获取证书信息。 - * @param pCert base64 编码的证书 - * @return 证书信息类 - * 证书信息类,包含:颁发者DN、 证书序列号、 证书主题、证书有效期的起始时间、证书有效期的终止时间、DER编码的公钥。 - */ - X509 x509 = api.GetX509CertInfo(s); - byte[] pubKey = x509.getPubKey(); - + String data = "1111111111111111111111111111"; /** * 用指定的证书私钥对指定的数据进行数字签名。 * 最大签名原始数据为8161byte - * @param publicKey 输入。签名 X509 证书的公钥。 * @param pCertSerial 输入。签名 X509 证书的序列号。 * @param pOrgData 输入。 待签名的原始数据。 * @return 签名数据(BASE64 编码)。 */ - String sign = api.netGSSign(Util.bytes2HexString(pubKey), sn, data.getBytes()); + String sign = api.netGSSign(sn, data.getBytes()); System.out.println("签名: " + sign); /** * 用指定证书对指定的原始数据进行数字签名验证。 - * @param publicKey 输入。签名 X509 证书的公钥。 * @param pCertSerial 输入。 签名 X509 证书的序列号。 * @param pOrgData 输入。 待签名的原始数据。 * @param pSignData 输入。 签名数据(BASE64 编码)。 * @return true 表示验证正确;false 表示失败; */ - boolean b = api.netGSVerify(Util.bytes2HexString(pubKey), sn, data.getBytes(), sign); + boolean b = api.netGSVerify(sn, data.getBytes(), sign); System.out.println(b); } @@ -1451,20 +1468,6 @@ public class TestAllMethods { @Test public void testImportCert2() throws IOException { - String cert = "-----BEGIN CERTIFICATE-----\n" + - "MIICBTCCAamgAwIBAgIGAXn07c3CMAwGCCqBHM9VAYN1BQAwSzELMAkGA1UEBhMC\n" + - "Q04xDjAMBgNVBAoTBUdNU1NMMRAwDgYDVQQLEwdQS0kvU00yMRowGAYDVQQDExFN\n" + - "aWRkbGVDQSBmb3IgVGVzdDAiGA8yMDIxMDYwOTE2MDAwMFoYDzIwMjIwNjA5MTYw\n" + - "MDAwWjBbMQswCQYDVQQGEwJDTjEKMAgGA1UECBMBMTEKMAgGA1UEBxMBMTEKMAgG\n" + - "A1UEChMBMTEKMAgGA1UECxMBMTEKMAgGA1UEAxMBMTEQMA4GCSqGSIb3DQEJARYB\n" + - "NDBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABCnSUhgDDtjJZfOJoWoPxe/BTnox\n" + - "PtDLBgGJyVpj0eNde7u4LnZ+H8vqN+0QvgfLcVg84cyl76j9+RuWsmLw7USjYzBh\n" + - "MBsGA1UdIwQUMBKAEPl/VbQnlDNiplbKb8xdGv8wGQYDVR0OBBIEEJ6MbyKdO6IX\n" + - "d3VkNLCf/aAwDAYDVR0RBAUwA4IBMTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIA\n" + - "ODAMBggqgRzPVQGDdQUAA0gAMEUCIG0PqR+bbdNOb5Q4kfHq8cQZJ1wa/P+bqFfv\n" + - "6bbL9RZCAiEAiH1LKCjq9p7MS7qOK+su5I0kenCQ505ZuuAWDMph0xk=\n" + - "-----END CERTIFICATE-----"; - String cert2 = "-----BEGIN CERTIFICATE-----\n" + "MIIB4TCCAYSgAwIBAgIIPJMAAAAAACswDAYIKoEcz1UBg3UFADAmMQswCQYDVQQG\n" + "EwJDTjEXMBUGA1UEAwwOU3VueWFyZFNNMlJvb3QwHhcNMTcxMTE3MDIzMDUxWhcN\n" + @@ -1479,8 +1482,91 @@ public class TestAllMethods { "/ejZglI=\n" + "-----END CERTIFICATE-----"; + String cert = "-----BEGIN CERTIFICATE-----\n" + + "MIID3QYKKoEcz1UGAQQCAqCCA80wggPJAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoq\n" + + "gRzPVQYBBAIBoIICxDCCAsAwggJjoAMCAQICEBAAAAAAAAAAAAAAEEJYBCMwDAYI\n" + + "KoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j\n" + + "aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIFRFU1Qg\n" + + "U00yIE9DQTEwHhcNMjEwMTExMDk1MjI1WhcNMjIwMTExMDk1MjI1WjB2MQswCQYD\n" + + "VQQGEwJjbjEVMBMGA1UECgwMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLDAZDQ0ZDQ0Ix\n" + + "FDASBgNVBAsMC0VudGVycHJpc2VzMSkwJwYDVQQDDCAwNDFAODkwNDI5MDA5OTk5\n" + + "RkRAQ0JDQ0AwMDAwMDAwMTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABExU5zuJ\n" + + "3pVl49mS3rTBwUcPuiI/zDR/w117PkpCgJ7m0kGyyorj1h2bxM62PthpNy99KPnk\n" + + "9gEvS696ZE5s8LGjgeowgecwHwYDVR0jBBgwFoAUa/4Y2o9COqa4bbMuiIM6NKLB\n" + + "MOEwSAYDVR0gBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8v\n" + + "d3d3LmNmY2EuY29tLmNuL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhiho\n" + + "dHRwOi8vdWNybC5jZmNhLmNvbS5jbi9TTTIvY3JsMTY4NzYuY3JsMAsGA1UdDwQE\n" + + "AwID6DAdBgNVHQ4EFgQUypxjmN7VBcoruhBRWmmFNv9yG1IwEwYDVR0lBAwwCgYI\n" + + "KwYBBQUHAwIwDAYIKoEcz1UBg3UFAANJADBGAiEA1IQTRQf5aaDJzzVxWLRml1ZS\n" + + "qQd9FPFeKZJnbzGQIQMCIQD/gY5+H1nytcVAx8hGtUPssklmI+9+vTdOF5LaKMR+\n" + + "jzGB3TCB2gIBATBwMFwxCzAJBgNVBAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5h\n" + + "bmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGzAZBgNVBAMMEkNGQ0EgVEVT\n" + + "VCBTTTIgT0NBMQIQEAAAAAAAAAAAAAAQQlgEIzAMBggqgRzPVQGDEQUAMA0GCSqB\n" + + "HM9VAYItAQUABEYwRAIgXmjY/FIR8qudmZGsIQUivZDt3/73dGojVjj5L76OcJIC\n" + + "IAHu0G242uYPY2B8zMkGw7kQ1C1xgRipEmlC1GWwMCz0\n" + + "-----END CERTIFICATE-----"; + String jgh = "00000000"; - System.out.println(api.importCert(Util.getSafeBytes(cert2), jgh.getBytes())); + System.out.println(api.importCert(Util.getSafeBytes(cert), jgh.getBytes())); + } + + @Test + public void testimportCertAddHT() { + String cert1 = "MIIB4TCCAYSgAwIBAgIIPJMAAAAAACswDAYIKoEcz1UBg3UFADAmMQswCQYDVQQGEwJDTjEXMBUGA1UEAwwOU3VueWFyZFNNMlJvb3QwHhcNMTcxMTE3MDIzMDUxWhcNMjMwMTI1MDIzMDUxWjBZMQswCQYDVQQGEwJDTjELMAkGA1UECAwCWkoxCzAJBgNVBAcMAkhaMQ4wDAYDVQQKDAVISkpZUzERMA8GA1UECwwIMDAwMDAwMDAxDTALBgNVBAMMBDIyMjIwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAATxqegqlmc/lduzBaKREyeNuPf78RA3wfJuhAv8zymLwQ6doefs1Iul+kMOukhfwY9aEhVdqws34FZMm2vs1+wXo2cwZTAOBgNVHQ8BAf8EBAMCAMAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgwFoAU93/arv8hxtk6eq2g+6z+AqVO1cEwHQYDVR0OBBYEFHfjFl72707A6s+YVuGvEuyvFWTMMAwGCCqBHM9VAYN1BQADSQAwRgIhALzg7+QW7RU4phv+4arEv0IOeaA6dtR8VT4Bwin9oHTWAiEA9kLESGiYm8L5Htf7GBXgH+pk7BJ68clml41B/ejZglI="; + + String cert2 = "MIID3QYKKoEcz1UGAQQCAqCCA80wggPJAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICxDCCAsAwggJjoAMCAQICEBAAAAAAAAAAAAAAEEJYBCMwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1" + + "UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIFRFU1QgU00yIE9DQTEwHhcNMjEwMTExMDk1MjI1WhcNMjIwMTExMDk1MjI1WjB2MQswCQYDVQQGEwJjbjEVMBMGA1UECgwMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLDAZDQ0ZDQ0IxF" + + "DASBgNVBAsMC0VudGVycHJpc2VzMSkwJwYDVQQDDCAwNDFAODkwNDI5MDA5OTk5RkRAQ0JDQ0AwMDAwMDAwMTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABExU5zuJ3pVl49mS3rTBwUcPuiI/zDR/w117PkpCgJ7m0kGyyorj1h2bxM62PthpNy99KPnk9gEvS696ZE5s8LGjgeowgecw" + + "HwYDVR0jBBgwFoAUa/4Y2o9COqa4bbMuiIM6NKLBMOEwSAYDVR0gBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNybC5jZmNhLmNvbS5jbi9TTTIvY3JsMTY4NzY" + + "uY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUypxjmN7VBcoruhBRWmmFNv9yG1IwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYIKoEcz1UBg3UFAANJADBGAiEA1IQTRQf5aaDJzzVxWLRml1ZSqQd9FPFeKZJnbzGQIQMCIQD/gY5+H1nytcVAx8hGtUPssklmI+9+vTdOF5LaKMR+jzGB3T" + + "CB2gIBATBwMFwxCzAJBgNVBAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGzAZBgNVBAMMEkNGQ0EgVEVTVCBTTTIgT0NBMQIQEAAAAAAAAAAAAAAQQlgEIzAMBggqgRzPVQGDEQUAMA0GCSqBHM9VAYItAQUABEYwRAIgXmjY/FIR8" + + "qudmZGsIQUivZDt3/73dGojVjj5L76OcJICIAHu0G242uYPY2B8zMkGw7kQ1C1xgRipEmlC1GWwMCz0"; + + System.out.println(cert2); + + String jgh = "00000000"; + + String DN = "C=CN,O=Sunyard,OU=8001,CN=8001"; + + String sign = api.SYD_DetachedSign(cert2.getBytes(), DN); + System.out.println("签名结果: " + sign); + + /** + * 上传指定证书到加密设备,并在证书前后加上begin和end + * @param certData 证书的字节数组 + * @param organizationId 机构号的字节数组 + * @return + */ + RetWrap retWrap = api.importCertAddHT(sign, null); + System.out.println(retWrap); + } + + @Test + public void testags() { + + String certData = "11111111111111111111111111111111111111111111111111111111111111111111111111"; + + final String head = "-----BEGIN CERTIFICATE-----\n"; + final String tail = "-----END CERTIFICATE-----"; + final String wrap = "\n"; + + int num = certData.length() % 64 == 0 ? certData.length() / 64: certData.length() / 64 + 1; + + StringBuilder sb = new StringBuilder(); + sb.append(head); + + for (int i = 0; i < num; i++) { + String substring; + if (i == num - 1) { + substring = certData.substring(i * 64); + } else { + substring = certData.substring(i * 64, (i + 1) * 64); + } + sb.append(substring).append(wrap); + } + sb.append(tail); + + System.out.println(sb); } @@ -1619,7 +1705,7 @@ public class TestAllMethods { @Test public void testSYMEncryptData() { - byte[] bytes = api.SYMEncryptData(3,"XF356BCBA3204F6E6F356BCBA3204F6E6", "1111111111111111".getBytes()); + byte[] bytes = api.SYMEncryptData(SydApi.NALG_SM4,"XF356BCBA3204F6E6F356BCBA3204F6E6", "1111111111111111".getBytes()); byte[] bytes1 = api.SYMDecryptData(3, "XF356BCBA3204F6E6F356BCBA3204F6E6", bytes); System.out.println(new String(bytes1)); } @@ -1686,6 +1772,42 @@ public class TestAllMethods { System.out.println(x509); } + // 8012 + @Test + public void testSYD_Get_X509_CertInfo_HA1() { + + String orgData = "\n" + + "\n" + + " \n" + + " \n" + + " 20211230001190300000000032001000\n" + + " 2021-12-30T09:27:49\n" + + " \n" + + " G4000131000016\n" + + " \n" + + " \n" + + " C1175662000017\n" + + " \n" + + " \n" + + " \n" + + " CC00\n" + + " CS01\n" + + " \n" + + " \n" + + ""; + + String sign = "MIID3QYKKoEcz1UGAQQCAqCCA80wggPJAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICxDCCAsAwggJjoAMCAQICEBAAAAAAAAAAAAAAEEJYBCMwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1" + + "UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIFRFU1QgU00yIE9DQTEwHhcNMjEwMTExMDk1MjI1WhcNMjIwMTExMDk1MjI1WjB2MQswCQYDVQQGEwJjbjEVMBMGA1UECgwMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLDAZDQ0ZDQ0IxF" + + "DASBgNVBAsMC0VudGVycHJpc2VzMSkwJwYDVQQDDCAwNDFAODkwNDI5MDA5OTk5RkRAQ0JDQ0AwMDAwMDAwMTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABExU5zuJ3pVl49mS3rTBwUcPuiI/zDR/w117PkpCgJ7m0kGyyorj1h2bxM62PthpNy99KPnk9gEvS696ZE5s8LGjgeowgecw" + + "HwYDVR0jBBgwFoAUa/4Y2o9COqa4bbMuiIM6NKLBMOEwSAYDVR0gBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNybC5jZmNhLmNvbS5jbi9TTTIvY3JsMTY4NzY" + + "uY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUypxjmN7VBcoruhBRWmmFNv9yG1IwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYIKoEcz1UBg3UFAANJADBGAiEA1IQTRQf5aaDJzzVxWLRml1ZSqQd9FPFeKZJnbzGQIQMCIQD/gY5+H1nytcVAx8hGtUPssklmI+9+vTdOF5LaKMR+jzGB3T" + + "CB2gIBATBwMFwxCzAJBgNVBAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGzAZBgNVBAMMEkNGQ0EgVEVTVCBTTTIgT0NBMQIQEAAAAAAAAAAAAAAQQlgEIzAMBggqgRzPVQGDEQUAMA0GCSqBHM9VAYItAQUABEYwRAIgXmjY/FIR8" + + "qudmZGsIQUivZDt3/73dGojVjj5L76OcJICIAHu0G242uYPY2B8zMkGw7kQ1C1xgRipEmlC1GWwMCz0"; + + X509 x509 = api.SYD_Get_X509_CertInfo_HA(orgData.getBytes(), sign); + System.out.println(Util.bytes2HexString(x509.getPubKey())); + } + // 测试通过 // 8016 @Test @@ -1697,7 +1819,17 @@ public class TestAllMethods { // String path = "E:\\work\\sunyard\\证书\\sm2.q\\sm2.q.enc.crt.pem"; String pCert = "-----BEGIN CERTIFICATE-----\\r\\nMIIC0DCCAnSgAwIBAgIFEEBzAUEwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJD\\r\\nTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y\\r\\naXR5MRswGQYDVQQDDBJDRkNBIFRFU1QgU00yIE9DQTEwHhcNMjAxMTAzMDk1NTU4\\r\\nWhcNMjUxMTAzMDk1NTU4WjB1MQswCQYDVQQGEwJDTjEQMA4GA1UECgwHT0NBMVNN\\r\\nMjENMAsGA1UECwwEdGVzdDEZMBcGA1UECwwQT3JnYW5pemF0aW9uYWwtMjEqMCgG\\r\\nA1UEAwwhMDUxQGNoaW5hdW5pb25wYXlAWjkwNTI5MDAwMDAwOEAyMFkwEwYHKoZI\\r\\nzj0CAQYIKoEcz1UBgi0DQgAEkw27RvY8mAx6h7vnSW/+X3b++a1E6LzQTPWMOiKP\\r\\nAfZTqJMKeRnQNEKt+N7EA98YHVheOCT9TlZ3fkgtNZcH86OCAQYwggECMB8GA1Ud\\r\\nIwQYMBaAFGv+GNqPQjqmuG2zLoiDOjSiwTDhMAwGA1UdEwEB/wQCMAAwSAYDVR0g\\r\\nBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2Eu\\r\\nY29tLmNuL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNy\\r\\nbC5jZmNhLmNvbS5jbi9TTTIvY3JsMTM3MzYuY3JsMA4GA1UdDwEB/wQEAwIGwDAd\\r\\nBgNVHQ4EFgQUn9wz++O90r2Bc7qlzqeIhIVivD4wHQYDVR0lBBYwFAYIKwYBBQUH\\r\\nAwIGCCsGAQUFBwMEMAwGCCqBHM9VAYN1BQADSAAwRQIgNXTJts3vqvCbbhUKwnkI\\r\\nrv+HeDeyTwU4JJpBTWCR6TACIQCtQShpYt9jgxw6VSHpKEXnnWH9u4vYhXDoH42w\\r\\nWVaX6A==\\r\\n-----END CERTIFICATE-----"; - X509 x509 = api.GetX509CertInfo(pCert); + + String pCert1 = "MIID3QYKKoEcz1UGAQQCAqCCA80wggPJAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICxDCCAsAwggJjoAMCAQICEBAAAAAAAAAAAAAAEEJYBCMwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1" + + "UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIFRFU1QgU00yIE9DQTEwHhcNMjEwMTExMDk1MjI1WhcNMjIwMTExMDk1MjI1WjB2MQswCQYDVQQGEwJjbjEVMBMGA1UECgwMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLDAZDQ0ZDQ0IxF" + + "DASBgNVBAsMC0VudGVycHJpc2VzMSkwJwYDVQQDDCAwNDFAODkwNDI5MDA5OTk5RkRAQ0JDQ0AwMDAwMDAwMTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABExU5zuJ3pVl49mS3rTBwUcPuiI/zDR/w117PkpCgJ7m0kGyyorj1h2bxM62PthpNy99KPnk9gEvS696ZE5s8LGjgeowgecw" + + "HwYDVR0jBBgwFoAUa/4Y2o9COqa4bbMuiIM6NKLBMOEwSAYDVR0gBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNybC5jZmNhLmNvbS5jbi9TTTIvY3JsMTY4NzY" + + "uY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUypxjmN7VBcoruhBRWmmFNv9yG1IwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYIKoEcz1UBg3UFAANJADBGAiEA1IQTRQf5aaDJzzVxWLRml1ZSqQd9FPFeKZJnbzGQIQMCIQD/gY5+H1nytcVAx8hGtUPssklmI+9+vTdOF5LaKMR+jzGB3T" + + "CB2gIBATBwMFwxCzAJBgNVBAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGzAZBgNVBAMMEkNGQ0EgVEVTVCBTTTIgT0NBMQIQEAAAAAAAAAAAAAAQQlgEIzAMBggqgRzPVQGDEQUAMA0GCSqBHM9VAYItAQUABEYwRAIgXmjY/FIR8" + + "qudmZGsIQUivZDt3/73dGojVjj5L76OcJICIAHu0G242uYPY2B8zMkGw7kQ1C1xgRipEmlC1GWwMCz0"; + String s = CoderUtil.certAddHT(pCert1); + System.out.println(s); + X509 x509 = api.GetX509CertInfo(s); System.out.println(x509); } diff --git a/src/test/java/com/sunyard/sydapi/test/TestGSYH.java b/src/test/java/com/sunyard/sydapi/test/TestGSYH.java index 13eab58..c9355cd 100644 --- a/src/test/java/com/sunyard/sydapi/test/TestGSYH.java +++ b/src/test/java/com/sunyard/sydapi/test/TestGSYH.java @@ -144,11 +144,70 @@ public class TestGSYH { System.out.println(retWrap); } + @Test + public void testimportCertAddHT() { + String cert1 = "MIIB4TCCAYSgAwIBAgIIPJMAAAAAACswDAYIKoEcz1UBg3UFADAmMQswCQYDVQQGEwJDTjEXMBUGA1UEAwwOU3VueWFyZFNNMlJvb3QwHhcNMTcxMTE3MDIzMDUxWhcNMjMwMTI1MDIzMDUxWjBZMQswCQYDVQQGEwJDTjELMAkGA1UECAwCWkoxCzAJBgNVBAcMAkhaMQ4wDAYDVQQKDAVISkpZUzERMA8GA1UECwwIMDAwMDAwMDAxDTALBgNVBAMMBDIyMjIwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAATxqegqlmc/lduzBaKREyeNuPf78RA3wfJuhAv8zymLwQ6doefs1Iul+kMOukhfwY9aEhVdqws34FZMm2vs1+wXo2cwZTAOBgNVHQ8BAf8EBAMCAMAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgwFoAU93/arv8hxtk6eq2g+6z+AqVO1cEwHQYDVR0OBBYEFHfjFl72707A6s+YVuGvEuyvFWTMMAwGCCqBHM9VAYN1BQADSQAwRgIhALzg7+QW7RU4phv+4arEv0IOeaA6dtR8VT4Bwin9oHTWAiEA9kLESGiYm8L5Htf7GBXgH+pk7BJ68clml41B/ejZglI="; + + String jgh = "00000000"; + + /** + * 上传指定证书到加密设备,并在证书前后加上begin和end + * @param certData 证书的字节数组 + * @param organizationId 机构号的字节数组 + * @return + */ + RetWrap retWrap = api.importCertAddHT(cert1, jgh.getBytes()); + System.out.println(retWrap); + } + + // 8012 + @Test + public void testSYD_Get_X509_CertInfo_HA1() { + + String orgData = "\n" + + "\n" + + " \n" + + " \n" + + " 20211230001190300000000032001000\n" + + " 2021-12-30T09:27:49\n" + + " \n" + + " G4000131000016\n" + + " \n" + + " \n" + + " C1175662000017\n" + + " \n" + + " \n" + + " \n" + + " CC00\n" + + " CS01\n" + + " \n" + + " \n" + + ""; + + String sign = "MIID3QYKKoEcz1UGAQQCAqCCA80wggPJAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICxDCCAsAwggJjoAMCAQICEBAAAAAAAAAAAAAAEEJYBCMwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1" + + "UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIFRFU1QgU00yIE9DQTEwHhcNMjEwMTExMDk1MjI1WhcNMjIwMTExMDk1MjI1WjB2MQswCQYDVQQGEwJjbjEVMBMGA1UECgwMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLDAZDQ0ZDQ0IxF" + + "DASBgNVBAsMC0VudGVycHJpc2VzMSkwJwYDVQQDDCAwNDFAODkwNDI5MDA5OTk5RkRAQ0JDQ0AwMDAwMDAwMTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABExU5zuJ3pVl49mS3rTBwUcPuiI/zDR/w117PkpCgJ7m0kGyyorj1h2bxM62PthpNy99KPnk9gEvS696ZE5s8LGjgeowgecw" + + "HwYDVR0jBBgwFoAUa/4Y2o9COqa4bbMuiIM6NKLBMOEwSAYDVR0gBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNybC5jZmNhLmNvbS5jbi9TTTIvY3JsMTY4NzY" + + "uY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUypxjmN7VBcoruhBRWmmFNv9yG1IwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYIKoEcz1UBg3UFAANJADBGAiEA1IQTRQf5aaDJzzVxWLRml1ZSqQd9FPFeKZJnbzGQIQMCIQD/gY5+H1nytcVAx8hGtUPssklmI+9+vTdOF5LaKMR+jzGB3T" + + "CB2gIBATBwMFwxCzAJBgNVBAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGzAZBgNVBAMMEkNGQ0EgVEVTVCBTTTIgT0NBMQIQEAAAAAAAAAAAAAAQQlgEIzAMBggqgRzPVQGDEQUAMA0GCSqBHM9VAYItAQUABEYwRAIgXmjY/FIR8" + + "qudmZGsIQUivZDt3/73dGojVjj5L76OcJICIAHu0G242uYPY2B8zMkGw7kQ1C1xgRipEmlC1GWwMCz0"; + + /** + * 从签名中获取证书并上载到加密机 + * @param orgData 待签名的原始数据 + * @param sign 签名数据 + * @return 证书信息(包含公钥字段) + */ + X509 x509 = api.SYD_Get_X509_CertInfo_HA(orgData.getBytes(), sign); + System.out.println("证书公钥: " + Util.bytes2HexString(x509.getPubKey())); + } + @Test public void test() { // 证书序号 String sn = "1004282451"; String data = "111"; + /** * 用指定的证书私钥对指定的数据进行数字签名。 * @param pCertSerial 输入。签名 X509 证书的序列号。 @@ -224,28 +283,10 @@ public class TestGSYH { // 签名验签流程 @Test public void testNetGSSign() { - String sn = "1004282451"; + // 本行的 + String sn = "10000000000000000000001042580423"; String data = "111"; - /** - * 通过证书序号 sn 获取的 X509 证书文件。 - * @param sn sn,证书序号 - * @param nCertType 证书类型,0:签名证书, 1:加密证书 - * @return base64 编码的证书 - */ - String s = api.GetX509CertFileBySN(sn, 0); - System.out.println("证书信息为: " + s); - - /** - * 输入 X509 格式的证书,获取证书信息。 - * @param pCert base64 编码的证书 - * @return 证书信息类 - * 证书信息类,包含:颁发者DN、 证书序列号、 证书主题、证书有效期的起始时间、证书有效期的终止时间、DER编码的公钥。 - */ - X509 x509 = api.GetX509CertInfo(s); - byte[] pubKey = x509.getPubKey(); - - /** * 用指定的证书私钥对指定的数据进行数字签名。 * 最大签名原始数据为8161byte @@ -254,7 +295,7 @@ public class TestGSYH { * @param pOrgData 输入。 待签名的原始数据。 * @return 签名数据(BASE64 编码)。 */ - String sign = api.netGSSign(Util.bytes2HexString(pubKey), sn, data.getBytes()); + String sign = api.netGSSign(sn, data.getBytes()); System.out.println("签名结果: " + sign); /** @@ -265,7 +306,52 @@ public class TestGSYH { * @param pSignData 输入。 签名数据(BASE64 编码)。 * @return true 表示验证正确;false 表示失败; */ - boolean b = api.netGSVerify(Util.bytes2HexString(pubKey), sn, data.getBytes(), sign); + boolean b = api.netGSVerify(sn, data.getBytes(), sign); + System.out.println("验签结果: " + b); + } + + + @Test + public void testVerify() { + + String orgData = "\n" + + "\n" + + " \n" + + " \n" + + " 20211231058043300311422380336000\n" + + " 2021-12-31T14:22:38\n" + + " \n" + + " C1030131001288\n" + + " \n" + + " \n" + + " C1175662000017\n" + + " \n" + + " \n" + + " MT01\n" + + " \n" + + " C1175662000017\n" + + " AT00\n" + + " 983zGfqfC3O7xbgYwsW9TfRp1ddVT7vfaAAGhZ7Y7M0=\n" + + " VbuPbl33/yi8OsQkme0kqZ0Tmvf8eJIyngC8CRyIk8E=\n" + + " IT01\n" + + " v1NPE/GPSooCXY4Z4RomtgDGpLxcm7RnF/VS16LEd3U=\n" + + " G8DUftbIJTJpjrIgvoF3KQ==\n" + + " SG01\n" + + " \n" + + " \n" + + " C1030131001288\n" + + " ZyBTxt3R/zN6AD7KqWotug==\n" + + " WT01\n" + + " WL01\n" + + " \n" + + " \n" + + ""; + + String sn = "10000000000000000000001042580423"; + + String sign = "MEUCIGpByl+Q1uSLXVPHdRvPXufgGEru+kUDj13jBY68b3NrAiEA3WbN3tYTCK7GRIsfnVA+3jbGTYluKs/Xz+JZkFZ4tIM="; + + boolean b = api.netGSVerify(sn, orgData.getBytes(), sign); System.out.println("验签结果: " + b); }