diff --git a/src/main/java/com/sunyard/inf/SydCertApi.java b/src/main/java/com/sunyard/inf/SydCertApi.java index 830f66a..40d2546 100644 --- a/src/main/java/com/sunyard/inf/SydCertApi.java +++ b/src/main/java/com/sunyard/inf/SydCertApi.java @@ -73,7 +73,7 @@ public interface SydCertApi { /** * 通过使用者 ID 获取的 X509 证书文件。 * @param userId 使用者的 ID,最大长度为 16 位数字(要与生成实体的机构号保持一致)。 - * @param nCertType 证书类型,0x00:签名证书, 0x01:加密证书 + * @param nCertType 证书类型,0:签名证书, 1:加密证书 * @return base64 编码的证书 */ String GetX509CertFileC( diff --git a/src/main/java/com/sunyard/inf/SydCryptionApi.java b/src/main/java/com/sunyard/inf/SydCryptionApi.java index 5f45fbb..78f142f 100644 --- a/src/main/java/com/sunyard/inf/SydCryptionApi.java +++ b/src/main/java/com/sunyard/inf/SydCryptionApi.java @@ -193,7 +193,7 @@ interface SydSYMApi { /** * 用输入的会话密钥,对指定报文数据进行加密处理。填充模式为1 * - * @param nAlg 算法标识.,0x00:3DES,0x01:SM4。 + * @param nAlg 算法标识., 1:DES,2:AES256,3:SM4。 * @param seesionKey 本地LMK 加密的会话密钥,HEX 格式 * @param pINdata 要加密的报文明文。必须是 8 或16 的倍数。 * @return 输出的报文密文, 长度为报文明文 + 16 @@ -225,7 +225,7 @@ interface SydSYMApi { /** * 用输入的会话密钥,对指定报文数据进行解密处理。填充模式为1 * - * @param nAlg  算法标识.,0x00:3DES,0x01:SM4。 + * @param nAlg  算法标识.1:DES,2:AES256,3:SM4。 * @param seesionKey 本地LMK 加密的会话密钥,HEX 格式 * @param pINdata 要解密的报文密文。长度必须是8 或16 的倍数。 * @return 输出的报文明文。 diff --git a/src/main/java/com/sunyard/inf/customize/SydQNUCApi.java b/src/main/java/com/sunyard/inf/customize/SydQNUCApi.java index c73b266..562db2f 100644 --- a/src/main/java/com/sunyard/inf/customize/SydQNUCApi.java +++ b/src/main/java/com/sunyard/inf/customize/SydQNUCApi.java @@ -10,6 +10,7 @@ public interface SydQNUCApi { /** * 用指定的证书私钥对指定的数据进行数字签名。 + * 最大签名原始数据为8161byte * @param pCertSerial 输入。签名 X509 证书的序列号。 * @param pOrgData 输入。 待签名的原始数据。 * @return 签名数据(BASE64 编码)。 diff --git a/src/test/java/com/sunyard/sydapi/test/TestGSYH.java b/src/test/java/com/sunyard/sydapi/test/TestGSYH.java new file mode 100644 index 0000000..ce5d2e6 --- /dev/null +++ b/src/test/java/com/sunyard/sydapi/test/TestGSYH.java @@ -0,0 +1,195 @@ +package com.sunyard.sydapi.test; + +import com.sunyard.RetWrap; +import com.sunyard.cert.X509; +import com.sunyard.proto.Util; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import racal.sunyard.main.SydApi4j; + +import java.util.Base64; + +/** + * 甘肃银行数字货币 + */ +public class TestGSYH { + + SydApi4j api; + // 对方加密证书sn + String sn = "1004282452"; + // 自己签名证书sn + String sn1 = "1004282451"; + + @Before + public void before() { + // 通过设置debug的属性开启debug,如果不设置则默认不打开 + System.setProperty("com.sunyard.sydapi4j.debug", "true"); + api = (SydApi4j) new SydApi4j().connect("192.168.0.100", 8889, null, 1000); + + } + + @Test + public void test02() { + Base64.Encoder encoder = Base64.getEncoder(); + Base64.Decoder decoder = Base64.getDecoder(); + + // 2. + String data = "1111111111111111"; + // 随机生成对称密钥,由指定的公钥加密生成数字信封 + RetWrap retWrap = api.generateDE(sn, (byte) 0x31); + String sessionKey = (String) retWrap.get("SessionKey"); + + // sm4加密账号等数据 + byte[] dataEnc = api.SYMEncryptData(3, sessionKey, data.getBytes()); + // base64转码 + byte[] dataEncBs64 = encoder.encode(dataEnc); + + // 将sm2加密后的数据进行base64转码 + String cipherKey = (String) retWrap.get("CipherKey"); + byte[] cipherKeyBs64 = encoder.encode(cipherKey.getBytes()); + + + // 3. + // 报文正文 + String msg = "12313146464564"; + // 对报文正文签名(内部会计算hash) + String msgSign = api.netSign(sn1, msg.getBytes()); + // base64转码 + byte[] msgSignBs64 = encoder.encode(msgSign.getBytes()); + + + // -------------下面为城银清算步骤----------------- + // 7. + // base64解码 + byte[] msgSignB = decoder.decode(msgSignBs64); + // 对报文验签 + boolean b = api.netVerify(sn1, dataEncBs64, 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"); + + // 9. + // 使用对称密钥解密报文 + dataEnc = decoder.decode(dataEncBs64); + byte[] bytes1 = api.SYMDecryptData(3, sessionKey, dataEnc); + System.out.println("data: " + new String(bytes1)); + } + + @After + public void after() { + try { + this.api.disconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // 测试通过 + // 8017 + @Test + public void testGetX509CertFileC() { + String userId = "8001"; + + /** + * 通过使用者 ID 获取的 X509 证书文件。 + * @param userId 使用者的 ID,最大长度为 16 位数字(要与生成实体的机构号保持一致)。 + * @param nCertType 证书类型,0:签名证书, 1:加密证书 + * @return base64 编码的证书 + */ + String s = api.GetX509CertFileC(userId, 1); + System.out.println(s); + + /** + * 输入 X509 格式的证书,获取证书信息。 + * @param pCert base64 编码的证书 + * @return 证书信息类 + * 证书信息类,包含:颁发者DN、 证书序列号、 证书主题、证书有效期的起始时间、证书有效期的终止时间、DER编码的公钥。 + */ + X509 x509 = api.GetX509CertInfo(s); + byte[] pubKey = x509.getPubKey(); + System.out.println("publicKey: " + Util.bytes2HexString(pubKey)); + } + + @Test + public void test() { + // 证书序号 + String sn = "1004282451"; + String data = "111"; + /** + * 用指定的证书私钥对指定的数据进行数字签名。 + * @param pCertSerial 输入。签名 X509 证书的序列号。 + * @param pOrgData 输入。 待签名的原始数据。 + * @return 签名数据(BASE64 编码)。 + */ + String s = api.netSign(sn, data.getBytes()); + + /** + * 用指定证书对指定的原始数据进行数字签名验证。 + * @param pCertSerial 输入。 签名 X509 证书的序列号。 + * @param pOrgData 输入。 待签名的原始数据。 + * @param pSignData 输入。 签名数据(BASE64 编码)。 + * @return true 表示验证正确;false 表示失败; + */ + // 12、对正文进行验签(内部会计算hash) + boolean b = api.netVerify(sn, data.getBytes(), s); + System.out.println(b); + + + String sn1 = "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.generateDE(sn1, (byte) 0x31); + String CipherKey = (String) retWrap.get("CipherKey"); + + /** + * 接收用私钥解密数字信封,还原对称密钥。 + * + * @param pCertSerial 输入。 对方 X509 证书的序列号。 + * @param pCipherKey 输入。 公钥加密的会话密钥,BASE64 编码 + * @return RetWrap 包含 SessionKey KCV + * SessionKey 输出。 本地LMK 加密的会话密钥,格式为:密钥类型|密钥密文,比如:02|密钥密文 + * KCV 会话密钥的检验值,HEX 格式,长度为 36H。 + */ + // 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)); + + } + + +}