From 4404f89dd65c22da369e00eb52e250ebdcb8e759 Mon Sep 17 00:00:00 2001 From: cheney Date: Mon, 20 Jun 2022 16:15:38 +0800 Subject: [PATCH] =?UTF-8?q?p7=20=E8=AF=81=E4=B9=A6=E7=9B=B8=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 18 + .../java/org/bouncycastle/cms/SydCmsUtil.java | 139 +++++ .../java/racal/sunyard/main/SydApi4j.java | 559 +++++++++++++----- .../java/com/sunyard/sydapi/test/TestHT.java | 64 +- .../sunyard/sydapi/util/SydCmsUtilTest.java | 83 +++ 5 files changed, 689 insertions(+), 174 deletions(-) create mode 100644 src/main/java/org/bouncycastle/cms/SydCmsUtil.java create mode 100644 src/test/java/com/sunyard/sydapi/util/SydCmsUtilTest.java diff --git a/pom.xml b/pom.xml index b812d9f..faee038 100644 --- a/pom.xml +++ b/pom.xml @@ -76,6 +76,24 @@ + + org.bouncycastle + bcpkix-jdk15on + 1.65 + + + + org.bouncycastle + bcprov-jdk15on + 1.65 + + + + cn.hutool + hutool-all + 5.8.4.M1 + + diff --git a/src/main/java/org/bouncycastle/cms/SydCmsUtil.java b/src/main/java/org/bouncycastle/cms/SydCmsUtil.java new file mode 100644 index 0000000..79f45ba --- /dev/null +++ b/src/main/java/org/bouncycastle/cms/SydCmsUtil.java @@ -0,0 +1,139 @@ +package org.bouncycastle.cms; + +import com.sunyard.SydApiException; +import org.bouncycastle.asn1.*; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.asn1.cms.EncryptedContentInfo; +import org.bouncycastle.asn1.cms.OriginatorInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + + +public class SydCmsUtil { + + public static Object readContentInfo( + byte[] input) { + ASN1InputStream is = new ASN1InputStream(input); + Object v = null; + try { + v = is.readObject(); + } catch (IOException e) { + e.printStackTrace(); + } + return v; + } + + + public static Map getEncryptedContentInfo(ASN1Encodable obj){ + Mapmap = new HashMap(); + ASN1Sequence seq = ASN1Sequence.getInstance(obj ); + if (seq.size() < 2) + { + throw new IllegalArgumentException("Truncated Sequence Found"); + } + + ASN1ObjectIdentifier contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0); + map.put( "contentType", contentType ); + + AlgorithmIdentifier contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance( + seq.getObjectAt(1)); + + map.put( "contentEncryptionAlgorithm", contentEncryptionAlgorithm ); + + if (seq.size() > 2) + { + ASN1OctetString encryptedContent = ASN1OctetString.getInstance( + (ASN1TaggedObject)seq.getObjectAt(2), false); + map.put( "encryptedContent", encryptedContent ); + } + return map; + } + + public static Map getOriginatorInfo(ASN1TaggedObject obj, + boolean explicit){ + Mapmap = new HashMap(); + ASN1Sequence seq = ASN1Sequence.getInstance(obj, explicit); + switch (seq.size()) + { + case 0: // empty + break; + case 1: + ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0); + switch (o.getTagNo()) + { + case 0 : + ASN1Set certs = ASN1Set.getInstance(o, false); + map.put("certs", certs); + break; + case 1 : + ASN1Set crls = ASN1Set.getInstance(o, false); + map.put("crls", crls); + break; + default: + throw new IllegalArgumentException("Bad tag in OriginatorInfo: " + o.getTagNo()); + } + break; + case 2: + ASN1Set certs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(0), false); + map.put("certs", certs); + ASN1Set crls = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false); + map.put("crls", crls); + break; + default: + throw new IllegalArgumentException("OriginatorInfo too big"); + } + + return map; + } + + public static ContentInfo getContentInfo( byte[] input ) { + Object content = readContentInfo( input ); + ASN1Sequence seq = ASN1Sequence.getInstance( content ); + return new ContentInfo(seq); + } + + public static Map readCmsInfo( byte[] input ) throws CMSException { + Mapmap = new HashMap(); + + Object content = readContentInfo( input ); + ASN1Sequence seq = ASN1Sequence.getInstance( content ); + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) seq.getObjectAt(0); + map.put("oid", oid); + + seq = ASN1Sequence.getInstance((ASN1TaggedObject) seq.getObjectAt(1), true); + + int index = 0; + + ASN1Integer version = (ASN1Integer)seq.getObjectAt(index++); + map.put( "version", version ); + + Object tmp = seq.getObjectAt(index++); + + if (tmp instanceof ASN1TaggedObject) + { + OriginatorInfo originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false); +// MaporiginatorInfo = getOriginatorInfo((ASN1TaggedObject)tmp, false); + map.put( "originatorInfo", originatorInfo ); + tmp = seq.getObjectAt(index++); + } + + ASN1Set recipientInfos = ASN1Set.getInstance(tmp); + map.put( "recipientInfos", recipientInfos ); + + EncryptedContentInfo encryptedContentInfo = EncryptedContentInfo.getInstance( seq.getObjectAt(index++) ); +// Map encryptedContentInfo = getEncryptedContentInfo(seq.getObjectAt(index++)); + map.put( "encryptedContentInfo", encryptedContentInfo ); + + if(seq.size() > index) + { + ASN1Set unprotectedAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false); + map.put( "unprotectedAttrs", unprotectedAttrs ); + } + + return map; + } + +} diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index 4f25bd6..25f73ed 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -1,5 +1,6 @@ package racal.sunyard.main; +import cn.hutool.core.bean.BeanUtil; import com.sunyard.RetWrap; import com.sunyard.SYMEnDeLongData; import com.sunyard.SydApi; @@ -10,7 +11,6 @@ import com.sunyard.proto.Packet; import com.sunyard.proto.PacketSection; import com.sunyard.proto.Util; import com.sunyard.proto.section.SectionValue; -import com.sunyard.proto.value.Str; import com.sunyard.trans.Alg; import com.sunyard.trans.FullMode; import com.sunyard.trans.PacketSN; @@ -19,7 +19,18 @@ import com.sunyard.util.CoderUtil; import com.sunyard.util.FileUtil; import com.sunyard.util.MyUtil; import com.sunyard.util.SYMUtil; -import racal.sunyard.main.dto.*; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.cms.SydCmsUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import racal.sunyard.main.dto.DTO77; +import racal.sunyard.main.dto.DTO78; +import racal.sunyard.main.dto.DTO79; +import racal.sunyard.main.dto.DTO7A; import racal.sunyard.main.proto.*; import java.io.*; @@ -27,14 +38,22 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketTimeoutException; -import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.*; public class SydApi4j implements SydApi { + static { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + } + private static boolean debug = false; private static long sTime = System.currentTimeMillis(); @@ -465,7 +484,7 @@ public class SydApi4j implements SydApi { byte[] be = error.getBytes(); if ((0 != (be[0] ^ be[1]))) { SydApiException e = new SydApiException(error.getInfo(), error.autoInt()); - println("验签失败=" + e.toString() ); + println("验签失败=" + e.toString()); return false; } return true; @@ -713,7 +732,7 @@ public class SydApi4j implements SydApi { byte[] be = error.getBytes(); if ((0 != (be[0] ^ be[1]))) { SydApiException e = new SydApiException(error.getInfo(), error.autoInt()); - println("验签失败=" + e.toString() ); + println("验签失败=" + e.toString()); return false; } @@ -976,7 +995,6 @@ public class SydApi4j implements SydApi { } /** - * * @param certData * @param organizationId * @return @@ -1916,10 +1934,11 @@ public class SydApi4j implements SydApi { /** * 对指定报文数据进行SM4加密 - * @param type 密钥类型。0: ZEK,1: TEK + * + * @param type 密钥类型。0: ZEK,1: TEK * @param userId 生成密钥时的机构号。 - * @param index 密钥索引 - * @param data 待加密的数据 + * @param index 密钥索引 + * @param data 待加密的数据 * @return */ public byte[] SYMSM4EncDataByIndex(int type, String userId, String index, byte[] data) { @@ -2057,13 +2076,14 @@ public class SydApi4j implements SydApi { /** * 对指定报文数据进行SM4解密 - * @param type 密钥类型。0: ZEK,1: TEK - * @param userId 生成密钥时的机构号 - * @param index 密钥索引 + * + * @param type 密钥类型。0: ZEK,1: TEK + * @param userId 生成密钥时的机构号 + * @param index 密钥索引 * @param pINdata 要解密的报文密文。长度必须是8 或16 的倍数 * @return */ - public byte[] SYMSM4DecDataByIndex (int type, String userId, String index, byte[] pINdata) { + public byte[] SYMSM4DecDataByIndex(int type, String userId, String index, byte[] pINdata) { if (userId.length() > 16 || index.length() > 8) { throw new SydApiException("机构号或索引长度不匹配", -27); @@ -2327,6 +2347,208 @@ public class SydApi4j implements SydApi { return decryptDE(true, 1, dnBytes, pCipherKey); } + + /** + * 通过 DN 查找证书 + * + * @param dn + * @return + */ + public String getCertByDn(String dn) throws UnsupportedEncodingException { + byte[] dnBytes = null; + try { + dnBytes = dn.getBytes("gbk"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + throw e; + } + return getCertByDn(dnBytes); + } + + public String getCertByDn(byte[] dnBytes) { + // 8010 指令,没有指令配置文件 + + // head + PacketSN sn = PacketSN.gen(); + HashMap packet = new HashMap(); + + // data + byte[] data = new byte[256]; + Arrays.fill(data, (byte) 0); + System.arraycopy(dnBytes, 0, data, 0, dnBytes.length); + + ByteBuffer bb = ByteBuffer.allocate(2 + 8 + 2 + data.length +1 ); + // 2 报文总长 + bb.put((byte) 0x01); + bb.put((byte) 0x0B); + + // 8 SN + bb.put(sn.getSn().array()); + + // 2 CMD + bb.put((byte) 0x80); + bb.put((byte) 0x10); + + // 256 Data + bb.put(data); + + // 加密 + bb.put((byte)0x31); + + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + byte[] success = new byte[2]; + Arrays.fill(success, (byte) 0); + + byte[] ret = new byte[2]; + bb.position(12); + bb.get(ret); + + if (!Arrays.equals(ret, success)) { + throw new SydApiException("获取证书异常", ret[0] * 256 + ret[1]); + } + + byte[] len = new byte[2]; + bb.get(len); + + int l = len[0] * 256 + len[1]; + byte[] cert = new byte[l]; + bb.get(cert); + + return new String(cert); + } + + public static X509Certificate getX509Certificate(InputStream is) throws CertificateException, + NoSuchProviderException { + CertificateFactory cf = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME); + return (X509Certificate) cf.generateCertificate(is); + } + + public RetWrap generateDEByDnSoft(String certSerial, String oData) { + RetWrap ret = new RetWrap(); + byte[] dnBytes = null; + try { + dnBytes = certSerial.getBytes("gbk"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + // 查询完整证书 + String cert = getCertByDn(dnBytes); + println("cert=" + cert); + + try { + X509Certificate x509 = getX509Certificate(new ByteArrayInputStream(cert.getBytes())); + + String pk = ByteUtils.toHexString(x509.getPublicKey().getEncoded()); + if (!pk.startsWith("03420004")) { + int i = pk.indexOf("03420004"); + if ( i >= 0 ) { + pk = pk.substring(i); + } else { + pk = "03420004" + pk; + } + } + + + // 生成会话密钥 + ret = SM2GenSessionKey(pk); + String ciperKey = ret.get(SydApi.RET_CIPHER_KEY).toString(); + String sessionKeyByLMK = ret.get(SydApi.RET_SESSION_KEY).toString(); + + println("ciperKey=" + ciperKey); + + // 加密数据 + byte[] iv = new byte[32]; + Arrays.fill(iv, (byte) 0x30); + RetWrap retWrap = SYMEnDeData(true, 1, sessionKeyByLMK, 1, 1, oData.getBytes(), iv, 0); + byte[] enData = (byte[]) retWrap.get("msg_all"); + + // 组织格式 + ContentInfo cms = genCMSEnvelopedData(Util.hexString2Bytes(ciperKey), enData); + + ret.put(SydApi.RET_CIPHER_KEY, Util.encodeBase64(cms.getEncoded())); + + return ret; + + } catch (SydApiException syde) { + throw syde; + } catch (Exception e) { + e.printStackTrace(); + throw new SydApiException("生成数字信封错误", -5); + } + } + +// private RetWrap deCMSEnvelopedData(byte[] cms) throws CMSException { +// RetWrap ret = new RetWrap(); +// ContentInfo info = SydCmsUtil.getContentInfo( cms ); +// // 修改 +// ASN1Sequence seq = (ASN1Sequence) info.getContent().toASN1Primitive(); +// +// ASN1Set set = ASN1Set.getInstance(seq.getObjectAt(1).toASN1Primitive()); +// ASN1Sequence seq2 = (ASN1Sequence) set.getObjectAt( 0 ).toASN1Primitive(); +// +// // 会话密钥 +// DEROctetString key = (DEROctetString) seq2.getObjectAt( 3 ); +// ret.put("sessionKeyDer", key.getOctets() ); +// +// // 密文段 +// ASN1Sequence seq5 = (ASN1Sequence) seq.getObjectAt( 2 ).toASN1Primitive(); +// ASN1TaggedObject tag = (ASN1TaggedObject) seq5.getObjectAt(2).toASN1Primitive(); +// DEROctetString data = (DEROctetString) tag.getObject(); +// ret.put("enData", data.getOctets() ); +// return ret; +// } + + public static ContentInfo genCMSEnvelopedData(byte[] sessionKeyDer, byte[] enData) { + String tmpl = "3082014D06092A864886F70D010703A082013E3082013A0201003181F73081F40201003065305C310B300906035504061302434E3130302E060355040A0C274368696E612046696E616E6369616C2043657274696669636174696F6E20417574686F72697479311B301906035504030C1243464341205445535420534D32204F43413102051004282452300B06092A811CCF5501822D03047B307902203C3AF535307DA548DA02C0AD171D2BC24D22472B42E5E175FCAF2C5CD30B5443022100ED53E7594F35FFACEB57F05898123F78E5B2D045CC47D894CD2E7BD34D66DA1D042014BD71F8CDA9729093A7CC391E2009C5D5F007586C2EBFB55BC175A6E8BDA33E04104AB82510BFDDD4FEE79C3F107D6F7F94303B060A2A811CCF550601040201301B06072A811CCF55016804100000000000000000000000000000000080109FD3D4338DB19E672CC162AF5B9B03E9"; + ContentInfo info = SydCmsUtil.getContentInfo(Util.hexString2Bytes(tmpl)); + // 修改 + ASN1Sequence seq = (ASN1Sequence) info.getContent().toASN1Primitive(); + + ASN1Set set = ASN1Set.getInstance(seq.getObjectAt(1).toASN1Primitive()); + ASN1Sequence seq2 = (ASN1Sequence) set.getObjectAt(0).toASN1Primitive(); + + // 会话密钥 + DEROctetString key = (DEROctetString) seq2.getObjectAt(3); + BeanUtil.setFieldValue(key, "string", sessionKeyDer); + + // 签发信息段 + ASN1Sequence seq3 = (ASN1Sequence) seq2.getObjectAt(1).toASN1Primitive(); + System.out.println(seq3); + + // 密文段 + ASN1Sequence seq4 = (ASN1Sequence) seq.getObjectAt(2).toASN1Primitive(); + ASN1TaggedObject tag = (ASN1TaggedObject) seq4.getObjectAt(2).toASN1Primitive(); + DEROctetString data = (DEROctetString) tag.getObject(); + BeanUtil.setFieldValue(data, "string", enData); + return info; + } + + public RetWrap decryptDEByDNSoft(String certSerial, String pCipherKey) { + byte[] dnBytes = null; + try { + dnBytes = certSerial.getBytes("gbk"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + +// RetWrap ret = deCMSEnvelopedData( Util.decodeBase64( pCipherKey ) ); + + // 解密会话密钥 + + decryptDE(false, 1, dnBytes, pCipherKey); + + // 解密原文 + + + return null; + } + + // 测试通过 @Override public RetWrap decryptDE(boolean pFlag, int model, byte[] certSerial, String pCipherKey) { @@ -2434,9 +2656,10 @@ public class SydApi4j implements SydApi { /** * 用指定的证书私钥对指定的数据进行数字签名。 * 银联 + * * @param pCertSerial 输入。签名 X509 证书的序列号。 - * @param userId 输入。用户id。 - * @param pOrgData 输入。 待签名的原始数据。 + * @param userId 输入。用户id。 + * @param pOrgData 输入。 待签名的原始数据。 * @return 签名数据(BASE64 编码)。 */ @Override @@ -2447,7 +2670,7 @@ public class SydApi4j implements SydApi { Proto6C proto = new Proto6C(); // 先进行 HASH - pOrgData = SM3HashSNaId(pCertSerial, userId, pOrgData ); + pOrgData = SM3HashSNaId(pCertSerial, userId, pOrgData); // 填充数据 PacketSN sn = PacketSN.gen(); @@ -2487,18 +2710,19 @@ public class SydApi4j implements SydApi { /** * 用指定证书对指定的原始数据进行数字签名验证。 * 银联 + * * @param pCertSerial 输入。 签名 X509 证书的序列号。 - * @param userId 输入。用户id。 - * @param pOrgData 输入。 待签名的原始数据。 - * @param pSignData 输入。 签名数据(BASE64 编码)。 + * @param userId 输入。用户id。 + * @param pOrgData 输入。 待签名的原始数据。 + * @param pSignData 输入。 签名数据(BASE64 编码)。 * @return true 表示验证正确;false 表示失败; */ @Override public boolean unPVerify(String pCertSerial, String userId, byte[] pOrgData, String pSignData) { // 获取协议 - Proto6D proto=new Proto6D(); + Proto6D proto = new Proto6D(); - pOrgData = SM3HashSNaId(pCertSerial, userId, pOrgData ); + pOrgData = SM3HashSNaId(pCertSerial, userId, pOrgData); // 填充数据 PacketSN sn = PacketSN.gen(); @@ -2516,7 +2740,7 @@ public class SydApi4j implements SydApi { ByteBuffer bb = proto.rend(packet); synchronized (this) { // 响应解析 - bb = syncRead( syncSend(bb) ); + bb = syncRead(syncSend(bb)); } //ProtocolParser parser = pset.getProtocolResParse(); Packet p = proto.parse(bb); @@ -2538,8 +2762,9 @@ public class SydApi4j implements SydApi { /** * 用指定的证书私钥对指定的数据进行数字签名。 * 网联 + * * @param pCertSerial 输入。签名 X509 证书的序列号。 - * @param pOrgData 输入。 待签名的原始数据。 + * @param pOrgData 输入。 待签名的原始数据。 * @return 签名数据(BASE64 编码)。 */ @Override @@ -2550,7 +2775,7 @@ public class SydApi4j implements SydApi { Proto6C proto = new Proto6C(); // 先进行 HASH - pOrgData = SM3HashSNaId( pCertSerial, null, pOrgData ); + pOrgData = SM3HashSNaId(pCertSerial, null, pOrgData); // 填充数据 PacketSN sn = PacketSN.gen(); @@ -2590,18 +2815,19 @@ public class SydApi4j implements SydApi { /** * 用指定证书对指定的原始数据进行数字签名验证。 * 网联 + * * @param pCertSerial 输入。 签名 X509 证书的序列号。 - * @param pOrgData 输入。 待签名的原始数据。 - * @param pSignData 输入。 签名数据(BASE64 编码)。 + * @param pOrgData 输入。 待签名的原始数据。 + * @param pSignData 输入。 签名数据(BASE64 编码)。 * @return true 表示验证正确;false 表示失败; */ @Override public boolean netVerify(String pCertSerial, byte[] pOrgData, String pSignData) { // 获取协议 //ProtocolRender render = pset.getProtocolReqRender("6D"); - Proto6D proto=new Proto6D(); + Proto6D proto = new Proto6D(); - pOrgData = SM3HashSNaId( pCertSerial, null, pOrgData ); + pOrgData = SM3HashSNaId(pCertSerial, null, pOrgData); // 填充数据 PacketSN sn = PacketSN.gen(); @@ -2619,7 +2845,7 @@ public class SydApi4j implements SydApi { ByteBuffer bb = proto.rend(packet); synchronized (this) { // 响应解析 - bb = syncRead( syncSend(bb) ); + bb = syncRead(syncSend(bb)); } //ProtocolParser parser = pset.getProtocolResParse(); Packet p = proto.parse(bb); @@ -3144,6 +3370,7 @@ public class SydApi4j implements SydApi { /** * 通过密钥索引获得 SM2 公钥(DER 编码)。 + * * @param privateKeyTag 指示用户密钥存储区的27位地址,27位的索引号:16位机构号+3位密钥类型+8位密钥索引号 * @return 公钥数据的der编码 */ @@ -3228,6 +3455,7 @@ public class SydApi4j implements SydApi { /** * 导出一个SM2私钥。 + * * @param privateKeyTag 要导出密钥的索引,27位的索引号:16位机构号+3位密钥类型+8位密钥索引号 * @return LMK下加密的私钥 */ @@ -3391,7 +3619,8 @@ public class SydApi4j implements SydApi { /** * 通过SN获取证书信息 - * @param sn sn + * + * @param sn sn * @param nCertType 证书类型,0:签名证书, 1:加密证书 * @return */ @@ -3408,8 +3637,9 @@ public class SydApi4j implements SydApi { /** * 通过sn或机构号获取证书 - * @param flag 0: SN,1: 机构号 - * @param userId 根据flag确定传入的数据 + * + * @param flag 0: SN,1: 机构号 + * @param userId 根据flag确定传入的数据 * @param nCertType 证书类型,0:签名证书, 1:加密证书 * @return */ @@ -3472,15 +3702,16 @@ public class SydApi4j implements SydApi { * 用户id默认为1234567812345678 * 签名结果R/S序列串先进行der编码,再进行base64编码 * - * @param flag 私钥标志位,当为1时第二个参数传入存储私钥的索引,当为0时第二个参数传入私钥 + * @param flag 私钥标志位,当为1时第二个参数传入存储私钥的索引,当为0时第二个参数传入私钥 * @param privateKey 当私钥标志位为1时传入存储私钥的索引,当为0时传入私钥 - * @param publicKey 公钥 - * @param orgData 要签名的信息 + * @param publicKey 公钥 + * @param orgData 要签名的信息 * @return 签名结果 */ public String SM2SignC(int flag, String privateKey, byte[] publicKey, byte[] orgData) { - return SM2SignC( flag, "1234567812345678", privateKey, publicKey, orgData); + return SM2SignC(flag, "1234567812345678", privateKey, publicKey, orgData); } + // 测试通过 @Override public String SM2SignC(int flag, String uid, String privateKey, byte[] publicKey, byte[] orgData) { @@ -3532,8 +3763,8 @@ public class SydApi4j implements SydApi { * sm2验签 * 用户id默认为1234567812345678 * - * @param publicKey 公钥的 DER 编码 - * @param orgData 签名信息 + * @param publicKey 公钥的 DER 编码 + * @param orgData 签名信息 * @param base64Sign 计算的签名,签名结果R/S序列串先进行der编码,再进行base64编码后的结果 * @return true 验签成功,false 验签失败 */ @@ -3701,7 +3932,7 @@ public class SydApi4j implements SydApi { byte[] publicKey, byte[] orgData, String base64Sign - ){ + ) { String certNo = "1234567812345678"; return SM2Verify(certNo, nOrgDataType, publicKey, orgData, base64Sign); } @@ -3854,8 +4085,9 @@ public class SydApi4j implements SydApi { /** * 用私钥加密数据 - * @param alg 算法标识,0:RSA 1:SM2 - * @param sk 指示私钥位置的标记,数字为存储私钥的索引,除了全 9 表示使用由命令中提供的密钥。 + * + * @param alg 算法标识,0:RSA 1:SM2 + * @param sk 指示私钥位置的标记,数字为存储私钥的索引,除了全 9 表示使用由命令中提供的密钥。 * @param data 数据 * @return 密文的 DER 编码(对于 RSA 算法,数据类型为 BIT). */ @@ -3894,8 +4126,9 @@ public class SydApi4j implements SydApi { /** * 用公钥解密数据 - * @param alg 算法标识,0:RSA 1:SM2 - * @param pk 公钥的 DER 编码 + * + * @param alg 算法标识,0:RSA 1:SM2 + * @param pk 公钥的 DER 编码 * @param data 数据 * @return 明文 */ @@ -3967,8 +4200,9 @@ public class SydApi4j implements SydApi { /** * 非对称公钥加密 - * @param alg 算法标识,0 = RSA 1 = SM2 - * @param pk 公钥的 DER 编码 + * + * @param alg 算法标识,0 = RSA 1 = SM2 + * @param pk 公钥的 DER 编码 * @param data 数据 * @return 公钥加密的密文的 DER 编码(对于 RSA 算法,数据类型为 BIT). */ @@ -3978,8 +4212,9 @@ public class SydApi4j implements SydApi { /** * 非对称私钥解密 - * @param alg 算法标识:0 = RSA 1 = SM2 - * @param sk 私钥值,LMK下加密的私钥 + * + * @param alg 算法标识:0 = RSA 1 = SM2 + * @param sk 私钥值,LMK下加密的私钥 * @param data 密文数据(DER 编码) * @return 公钥加密的密文的 DER 编码(对于 RSA 算法,数据类型为 BIT) */ @@ -4332,8 +4567,9 @@ public class SydApi4j implements SydApi { /** * 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。 * 输入的sm2密文结构为C1C2C3格式 + * * @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。 - * @param enData 加密的数据,base64 编码。 + * @param enData 加密的数据,base64 编码。 * @param keyType 密钥类型,0:签名证书, 1:加密证书。 * @return 明文数据。 */ @@ -4382,11 +4618,12 @@ public class SydApi4j implements SydApi { /** * 计算SM3散列值 + * * @param publicKey 公钥的 DER 编码(可以为空) - * @param csn 证书序号 - * @param cdn 证书DN - * @param userId 用户ID - * @param msg 原始数据,二进制的消息块 + * @param csn 证书序号 + * @param cdn 证书DN + * @param userId 用户ID + * @param msg 原始数据,二进制的消息块 * @return */ private byte[] SM3Hash(String publicKey, String csn, String cdn, String userId, byte[] msg) { @@ -4438,7 +4675,7 @@ public class SydApi4j implements SydApi { if ('0' == packtype || '1' == packtype) { - if ( null != csn || null != cdn ){ + if (null != csn || null != cdn) { if (userId != null) { bb.put(String.format("%02d", userId.length()).getBytes()); bb.put(userId.getBytes()); @@ -4450,18 +4687,17 @@ public class SydApi4j implements SydApi { // 通过证书查找公钥 bb.put("P".getBytes()); byte[] content; - if ( null != csn ){ + if (null != csn) { content = csn.getBytes(); - bb.put( "0".getBytes() ); + bb.put("0".getBytes()); } else { content = cdn.getBytes(); - bb.put( "1".getBytes() ); + bb.put("1".getBytes()); } - bb.put( String.format("%04d", content.length ).getBytes() ); - bb.put( content ); - } - else if (null == publicKey) { + bb.put(String.format("%04d", content.length).getBytes()); + bb.put(content); + } else if (null == publicKey) { // 无公钥 @@ -4469,8 +4705,7 @@ public class SydApi4j implements SydApi { bb.put("".getBytes()); bb.put(String.format("%04d", 0).getBytes()); bb.put("".getBytes()); - } - else { + } else { // 传入公钥 bb.put(String.format("%02d", 16).getBytes()); bb.put("1234567812345678".getBytes()); @@ -4555,7 +4790,6 @@ public class SydApi4j implements SydApi { } - @Override public byte[] SM3Hash(String publicKey, byte[] msg, int block, byte[] mac) { @@ -4797,9 +5031,10 @@ public class SydApi4j implements SydApi { /** * 数字信封加密数据 会员定制格式 - * @param keyValue 公钥值 + * + * @param keyValue 公钥值 * @param inPutDataStr 报文明文 - * @param msgId 设备认证内容 + * @param msgId 设备认证内容 * @return 格式:sessionByPk(base64)+\r\n+头(base64)+\r\n+密文(base64) * @throws UnsupportedEncodingException */ @@ -4973,11 +5208,12 @@ public class SydApi4j implements SydApi { * 使用SM4算法进行加密,其中加密模式为CBC, * Ⅳ使用缺省值0X 00000000000000000000000000000000, * 补位模式为 PKCS5 PADDING 。 - * @param keyType 密钥类型 0: ZEK,1: TEK - * @param key 密钥 - * @param inType 输入消息类型 0:二进制 1:扩展十六进制 - * @param outType 输出消息类型 0:二进制 1:扩展十六进制 - * @param inFilePath 需要加密的数据文件所在的路径 + * + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param inFilePath 需要加密的数据文件所在的路径 * @param outFilePath 加密后的密文数据将要保存的文件路径 * @return 加密是否成功。false为失败,true为成功 */ @@ -5011,21 +5247,21 @@ public class SydApi4j implements SydApi { File in = new File(inFilePath); - if ( !in.exists() ){ + if (!in.exists()) { throw new SydApiException("要加密的文件不存在", -27); } long length = in.length(); int l = new Long(length).intValue(); - int n = l / ( 2 * 1024); - println("n 个 2k:"+n); + int n = l / (2 * 1024); + println("n 个 2k:" + n); - if (l % ( 2 * 1024) != 0) { + if (l % (2 * 1024) != 0) { n++; } File out = new File(outFilePath); - if ( out.exists() ){ + if (out.exists()) { out.delete(); } try { @@ -5033,34 +5269,34 @@ public class SydApi4j implements SydApi { } catch (IOException e) { e.printStackTrace(); } - BufferedInputStream fis =null; - BufferedOutputStream fos=null; + BufferedInputStream fis = null; + BufferedOutputStream fos = null; try { fis = new BufferedInputStream(new FileInputStream(in)); fos = new BufferedOutputStream(new FileOutputStream(out)); byte[] buff = new byte[2 * 1024]; - for (int i = 0; i < n-1; i++) { - int len = fis.read( buff ); + for (int i = 0; i < n - 1; i++) { + int len = fis.read(buff); //先判断是否是最后一块/唯一块,是->calc, //首块和中间块才->update - if ( len == buff.length){ - println("len长度_update:"+len); - byte[] en = sym.update( buff ); - println("en长度:"+en.length); - fos.write( en ); + if (len == buff.length) { + println("len长度_update:" + len); + byte[] en = sym.update(buff); + println("en长度:" + en.length); + fos.write(en); } } - int len = fis.read( buff ); + int len = fis.read(buff); //先判断是否是最后一块/唯一块,是->calc, //首块和中间块才->update - if ( len <= buff.length && len>-1) { + if (len <= buff.length && len > -1) { println("len长度_calc:" + len); byte[] en = sym.calc(buff, len); println("en长度:" + en.length); - fos.write( en ); + fos.write(en); } } catch (IOException e) { e.printStackTrace(); @@ -5094,14 +5330,15 @@ public class SydApi4j implements SydApi { * 使用SM4算法进行加密,其中加密模式为CBC, * Ⅳ使用缺省值0X 00000000000000000000000000000000, * 补位模式为 PKCS5 PADDING 。 - * @param isEn 是否加密 + * + * @param isEn 是否加密 * @param keyType 密钥类型 0: ZEK,1: TEK - * @param key 密钥 - * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 * @param outType 输出消息类型 0:二进制 1:扩展十六进制 - * @param msg 消息数据 - * @param iv iv - * @param block 消息块号 + * @param msg 消息数据 + * @param iv iv + * @param block 消息块号 * @return */ // @Override @@ -5148,11 +5385,12 @@ public class SydApi4j implements SydApi { * 使用SM4算法进行加密,其中加密模式为CBC, * Ⅳ使用缺省值0X 00000000000000000000000000000000, * 补位模式为 PKCS5 PADDING 。 + * * @param keyType 密钥类型 0: ZEK,1: TEK - * @param key 密钥 - * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 * @param outType 输出消息类型 0:二进制 1:扩展十六进制 - * @param msg 消息数据 + * @param msg 消息数据 * @return 输出的报文密文 */ // 测试通过 @@ -5186,11 +5424,12 @@ public class SydApi4j implements SydApi { * 使用SM4算法进行解密,其中加密模式为CBC, * Ⅳ使用缺省值0X 00000000000000000000000000000000, * 补位模式为 PKCS5 PADDING 。 - * @param keyType 密钥类型 0: ZEK,1: TEK - * @param key 密钥 - * @param inType 输入消息类型 0:二进制 1:扩展十六进制 - * @param outType 输出消息类型 0:二进制 1:扩展十六进制 - * @param inFilePath 加密后的密文数据将要保存的文件路径 + * + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param inFilePath 加密后的密文数据将要保存的文件路径 * @param outFilePath 解密后的数据文件所在的路径 * @return 解密是否成功。false为失败,true为成功 */ @@ -5224,21 +5463,21 @@ public class SydApi4j implements SydApi { File in = new File(inFilePath); - if ( !in.exists() ){ + if (!in.exists()) { throw new SydApiException("要解密的文件不存在", -27); } long length = in.length(); int l = new Long(length).intValue(); - int n = l / ( 2 * 1024); - println("n 个 2k:"+n); + int n = l / (2 * 1024); + println("n 个 2k:" + n); - if (l % ( 2 * 1024) != 0) { + if (l % (2 * 1024) != 0) { n++; } File out = new File(outFilePath); - if ( out.exists() ){ + if (out.exists()) { out.delete(); } try { @@ -5255,22 +5494,22 @@ public class SydApi4j implements SydApi { byte[] buff = new byte[2 * 1024]; byte[] buff1 = new byte[2 * 1024 + 16]; - for (int i = 0; i < n-1; i++) { - int len = fis.read( buff ); + for (int i = 0; i < n - 1; i++) { + int len = fis.read(buff); //先判断是否是最后一块/唯一块,是->calc, //首块和中间块才->update - if ( len == buff.length){ - println("len长度_update:"+len); - byte[] en = sym.update( buff ); - println("en长度:"+en.length); - fos.write( en ); + if (len == buff.length) { + println("len长度_update:" + len); + byte[] en = sym.update(buff); + println("en长度:" + en.length); + fos.write(en); } } - int len = fis.read( buff1 ); + int len = fis.read(buff1); //先判断是否是最后一块/唯一块,是->calc, //首块和中间块才->update - if ( len <= buff1.length && len>-1) { + if (len <= buff1.length && len > -1) { println("len长度_calc:" + len); byte[] en = sym.calc(buff1, len); println("en长度:" + en.length); @@ -5303,11 +5542,12 @@ public class SydApi4j implements SydApi { * 使用SM4算法进行解密,其中加密模式为CBC, * Ⅳ使用缺省值0X 00000000000000000000000000000000, * 补位模式为 PKCS5 PADDING 。 + * * @param keyType 密钥类型 0: ZEK,1: TEK - * @param key 密钥 - * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 * @param outType 输出消息类型 0:二进制 1:扩展十六进制 - * @param msg 加密后的消息数据 + * @param msg 加密后的消息数据 * @return 输出的报文明文 */ // 测试通过 @@ -5783,7 +6023,7 @@ public class SydApi4j implements SydApi { /** * 8.1生成一个MAC(=) * - * @param TAK tak类型的密钥 + * @param TAK tak类型的密钥 * @param infoData MAC数据,数据长度应该为8的整数倍,如果不是8的整数倍,系统默认在数据后面填充0x00组成8的整数倍。 * @param IV IV * @return 所计算出的MAC hex 格式 @@ -6011,12 +6251,13 @@ public class SydApi4j implements SydApi { /** * 生成一个MAC - * @param alg 算法,0=DES 1=3DES 2=SM4 3=AES 4=IDEA 5=SM1 6=3DES-X9.19 - * @param keyType 密钥类型,0-TAK 1-ZAK - * @param AK 密钥 + * + * @param alg 算法,0=DES 1=3DES 2=SM4 3=AES 4=IDEA 5=SM1 6=3DES-X9.19 + * @param keyType 密钥类型,0-TAK 1-ZAK + * @param AK 密钥 * @param fullMode 填充类型,0-弱填充 1 强填充 * @param infoData MAC数据 - * @param macLen MAC数据长度,1=4Byte 2=8Byte 3=16Byte(仅在SM4/AES 下有效) + * @param macLen MAC数据长度,1=4Byte 2=8Byte 3=16Byte(仅在SM4/AES 下有效) * @return mac 值 hex 格式 */ // 测试通过 @@ -6979,7 +7220,7 @@ public class SydApi4j implements SydApi { packet.put("data", data); PacketSN sn = PacketSN.gen(); packet.put("header", sn.getSn().array()); - if (num != null && !"".equals(num)){ + if (num != null && !"".equals(num)) { data.put("num", num); } @@ -7927,22 +8168,23 @@ public class SydApi4j implements SydApi { /** * 自动 4k 分包 + * * @param keyType * @param mode * @param key * @param msg * @return MAC 值 */ - public String genMAB(int mode, int keyType, String key, byte[] msg){ + public String genMAB(int mode, int keyType, String key, byte[] msg) { final int blockSize = 4 * 1024; - if ( null == msg || msg.length == 0 ) { + if (null == msg || msg.length == 0) { throw new SydApiException("输入数据为空", 21); } - if( msg.length <= blockSize ) { + if (msg.length <= blockSize) { // 唯一包 - RetWrap retWrap = this.genMAB(0, keyType, 2, key, null, msg ); - return new String( (byte[]) retWrap.get("MAB") ); + RetWrap retWrap = this.genMAB(0, keyType, 2, key, null, msg); + return new String((byte[]) retWrap.get("MAB")); } int loop = 0; @@ -7961,31 +8203,31 @@ public class SydApi4j implements SydApi { // 首包 // 必然有 - data = new byte[ blockSize ]; - System.arraycopy( msg, 0, data, 0 , data.length ); - RetWrap retWrap = this.genMAB(1, keyType, 2, key, null, data ); + data = new byte[blockSize]; + System.arraycopy(msg, 0, data, 0, data.length); + RetWrap retWrap = this.genMAB(1, keyType, 2, key, null, data); byte[] iv = (byte[]) retWrap.get("MAB"); // 中间包 - for ( int i = 0 ; i < (loop - 2); i++ ) { - data = new byte[ blockSize ]; - System.arraycopy( msg, (i + 1) * blockSize , data, 0 , data.length ); - retWrap = this.genMAB(2, keyType, 2, key, iv, data ); + for (int i = 0; i < (loop - 2); i++) { + data = new byte[blockSize]; + System.arraycopy(msg, (i + 1) * blockSize, data, 0, data.length); + retWrap = this.genMAB(2, keyType, 2, key, iv, data); iv = (byte[]) retWrap.get("MAB"); } // 尾包 // 必然有 - if( 0 == tailLen ) { + if (0 == tailLen) { // 恰好是分包整倍数 tailLen = blockSize; } - data = new byte[ tailLen ]; - System.arraycopy( msg, (loop - 1) * blockSize , data, 0 , data.length ); - retWrap = this.genMAB(3, keyType, 2, key, iv , data); - return new String( (byte[]) retWrap.get("MAB") ); + data = new byte[tailLen]; + System.arraycopy(msg, (loop - 1) * blockSize, data, 0, data.length); + retWrap = this.genMAB(3, keyType, 2, key, iv, data); + return new String((byte[]) retWrap.get("MAB")); } /** @@ -9591,9 +9833,6 @@ public class SydApi4j implements SydApi { } - - - /** * 17.9 角色认证(+) -> -> : code = 2 ( 0x2 ) msg = 签名验证错误 * @@ -9856,11 +10095,11 @@ public class SydApi4j implements SydApi { /** * 查询设备证书信息 - * @return - * equipType: 设备型号 - * equipNo: 设备序号 - * equipPk: 设备密钥公钥 - * authSign: 授权签名 + * + * @return equipType: 设备型号 + * equipNo: 设备序号 + * equipPk: 设备密钥公钥 + * authSign: 授权签名 */ // 测试通过 @Override @@ -10022,8 +10261,7 @@ public class SydApi4j implements SydApi { * * @param orgData 待签名数据 * @param sCertDN 证书DN - * @return - * 符合PKCS7标准的签名结果 + * @return 符合PKCS7标准的签名结果 */ @Override public String attachedSign(byte[] orgData, String sCertDN) { @@ -10109,7 +10347,7 @@ public class SydApi4j implements SydApi { byte[] be = error.getBytes(); if ((0 != (be[0] ^ be[1]))) { SydApiException e = new SydApiException(error.getInfo(), error.autoInt()); - println("验签失败=" + e.toString() ); + println("验签失败=" + e.toString()); return false; } @@ -10131,8 +10369,7 @@ public class SydApi4j implements SydApi { * 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。 * * @param sign 已签名数据 - * @return - * 返回CERT_INFO结构的证书数据 + * @return 返回CERT_INFO结构的证书数据 */ public X509 attachedVerifyAndGetX509(String sign) { RetWrap retWrap = attachedVerifyAndGetAll(sign); @@ -11218,13 +11455,13 @@ public class SydApi4j implements SydApi { int algorithmKey = MyUtil.transAlg(algFlag); bb.put(String.format("%02d", algorithmKey).getBytes()); - if (6==algorithmKey || 8==algorithmKey || 2==algorithmKey || 4==algorithmKey || 10==algorithmKey) { + if (6 == algorithmKey || 8 == algorithmKey || 2 == algorithmKey || 4 == algorithmKey || 10 == algorithmKey) { // IV 数据域 bb.put(iv); } // 保护密钥分散级数 - bb.put(( String.valueOf( protectedKeyDivNum ) ).getBytes()); + bb.put((String.valueOf(protectedKeyDivNum)).getBytes()); if (protectedKeyDivNum != 0) { // 分散因子 @@ -11247,11 +11484,11 @@ public class SydApi4j implements SydApi { bb.put(String.format("%02d", exportKeyNum).getBytes()); //导出的密钥结构体 - byte[] b = new byte[ 144 * exportKeyNum ]; - int destPos=0; - for(Struct struct:structList){ - System.arraycopy(struct.getByte(),0,b,destPos,struct.getByte().length); - destPos+=struct.getByte().length; + byte[] b = new byte[144 * exportKeyNum]; + int destPos = 0; + for (Struct struct : structList) { + System.arraycopy(struct.getByte(), 0, b, destPos, struct.getByte().length); + destPos += struct.getByte().length; } bb.put(b); diff --git a/src/test/java/com/sunyard/sydapi/test/TestHT.java b/src/test/java/com/sunyard/sydapi/test/TestHT.java index b2ef83b..34ccec4 100644 --- a/src/test/java/com/sunyard/sydapi/test/TestHT.java +++ b/src/test/java/com/sunyard/sydapi/test/TestHT.java @@ -4,15 +4,13 @@ import com.sunyard.RetWrap; import com.sunyard.SydApi; 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.io.UnsupportedEncodingException; -import java.util.Base64; - -import static com.sunyard.sydapi.util.PrintUtil.printRetWrap; /** * 衡泰例子 @@ -25,7 +23,7 @@ public class TestHT { public void before() { // 通过设置debug的属性开启debug,如果不设置则默认不打开 System.setProperty("com.sunyard.sydapi4j.debug", "true"); - api = (SydApi4j) new SydApi4j().connect("172.16.18.59", 8889, null, 1000); + api = (SydApi4j) new SydApi4j().connect("192.168.0.200", 8889, null, 1000); // api = (SydApi4j) new SydApi4j().connect("192.168.0.66", 8889, null, 1000); } @@ -39,6 +37,46 @@ public class TestHT { } + @Test + public void testDecryptDE5() throws UnsupportedEncodingException { + String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1"; + String oData = "00001111222233"; + + RetWrap retWrap = api.generateDEByDn(dn, oData); + String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); + System.out.println("数字信封: " + cipherKey); + + RetWrap retWrap1 = api.decryptDEByDN(dn, cipherKey); + System.out.println("原数据: " + retWrap1.get("oData")); + } + + @Test + public void testDecryptDE5Soft1() throws UnsupportedEncodingException { + String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1"; + String oData = "00001111222233"; + + RetWrap retWrap = api.generateDEByDnSoft(dn, oData); + String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); + System.out.println("数字信封: " + cipherKey); + + RetWrap retWrap1 = api.decryptDEByDN(dn, cipherKey); + System.out.println("原数据: " + retWrap1.get("oData")); + } + + @Test + public void testDecryptDE5Soft2() throws UnsupportedEncodingException { + String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1"; + String oData = "00001111222233"; + + RetWrap retWrap = api.generateDEByDn(dn, oData); + String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); + System.out.println("数字信封: " + cipherKey); + + RetWrap retWrap1 = api.decryptDEByDNSoft(dn, cipherKey); + System.out.println("原数据: " + retWrap1.get("oData")); + } + + // // 测试通过 // 73 @@ -121,19 +159,19 @@ public class TestHT { } } + + + @Test - public void testDecryptDE5() throws UnsupportedEncodingException { + public void getCert(){ String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1"; - String oData = "00001111222233"; - - RetWrap retWrap = api.generateDEByDn(dn, oData); - String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); - System.out.println("数字信封: " + cipherKey); - - RetWrap retWrap1 = api.decryptDEByDN(dn, cipherKey); - System.out.println("原数据: " + retWrap1.get("oData")); + String cert = api.GetX509CertFileBySN("1111111111111151", SydApi.FOR_ENCRYPT ); + System.out.println( cert ); } + + + /** * 流程演示 */ diff --git a/src/test/java/com/sunyard/sydapi/util/SydCmsUtilTest.java b/src/test/java/com/sunyard/sydapi/util/SydCmsUtilTest.java new file mode 100644 index 0000000..c249d4f --- /dev/null +++ b/src/test/java/com/sunyard/sydapi/util/SydCmsUtilTest.java @@ -0,0 +1,83 @@ +package com.sunyard.sydapi.util; + +import com.sunyard.RetWrap; +import com.sunyard.SydApi; +import com.sunyard.proto.Util; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.cms.SydCmsUtil; + +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.cms.SydCmsUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.junit.Test; +import racal.sunyard.main.SydApi4j; + + +public class SydCmsUtilTest { + + @Test + public void test(){ + SydApi4j api = (SydApi4j) new SydApi4j().connect("192.168.0.200", 8889, null, 1000); + + try { + String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1"; + String oData = "00001111222233"; + + RetWrap retWrap = api.generateDEByDnSoft(dn, oData); + String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); + System.out.println("数字信封: " + cipherKey); + + RetWrap retWrap1 = api.decryptDEByDN(dn, cipherKey); + System.out.println("原数据: " + retWrap1.get("oData")); + }catch ( Exception e ) { + e.printStackTrace(); + } finally { + if ( null != api ) { + api.disconnect(); + } + } + } + + + public static void main(String[] args) { + System.setProperty("com.sunyard.sydapi4j.debug", "true"); + + + String tmpl = "3082014D06092A864886F70D010703A082013E3082013A0201003181F73081F40201003065305C310B300906035504061302434E3130302E060355040A0C274368696E612046696E616E6369616C2043657274696669636174696F6E20417574686F72697479311B301906035504030C1243464341205445535420534D32204F43413102051004282452300B06092A811CCF5501822D03047B307902203C3AF535307DA548DA02C0AD171D2BC24D22472B42E5E175FCAF2C5CD30B5443022100ED53E7594F35FFACEB57F05898123F78E5B2D045CC47D894CD2E7BD34D66DA1D042014BD71F8CDA9729093A7CC391E2009C5D5F007586C2EBFB55BC175A6E8BDA33E04104AB82510BFDDD4FEE79C3F107D6F7F94303B060A2A811CCF550601040201301B06072A811CCF55016804100000000000000000000000000000000080109FD3D4338DB19E672CC162AF5B9B03E9"; + + System.out.println( SydCmsUtil.class.getClassLoader() ); + + ContentInfo info = SydCmsUtil.getContentInfo(Util.hexString2Bytes( tmpl ) ); + + System.out.println( info ); + + info = SydApi4j.genCMSEnvelopedData(new byte[0], new byte[0]); + + SydApi4j api = (SydApi4j) new SydApi4j().connect("192.168.0.200", 8889, null, 1000); + + try { + String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1"; + String oData = "00001111222233"; + + RetWrap retWrap = api.generateDEByDnSoft(dn, oData); + String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); + System.out.println("数字信封: " + cipherKey); + + RetWrap retWrap1 = api.decryptDEByDN(dn, cipherKey); + System.out.println("原数据: " + retWrap1.get("oData")); + }catch ( Exception e ) { + e.printStackTrace(); + } finally { + if ( null != api ) { + api.disconnect(); + } + } + + + } +}