diff --git a/.gitignore b/.gitignore index 9d01510..d6436e9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ /public/ /.DS_Store src/test/java/com/sunyard/sydapi/sample/*.* +*.p7 diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index 25f73ed..21cba09 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -19,10 +19,7 @@ import com.sunyard.util.CoderUtil; import com.sunyard.util.FileUtil; import com.sunyard.util.MyUtil; import com.sunyard.util.SYMUtil; -import org.bouncycastle.asn1.ASN1Sequence; -import org.bouncycastle.asn1.ASN1Set; -import org.bouncycastle.asn1.ASN1TaggedObject; -import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.cms.SydCmsUtil; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -33,6 +30,7 @@ import racal.sunyard.main.dto.DTO79; import racal.sunyard.main.dto.DTO7A; import racal.sunyard.main.proto.*; +import javax.security.auth.x500.X500Principal; import java.io.*; import java.net.InetSocketAddress; import java.net.Socket; @@ -1423,7 +1421,7 @@ public class SydApi4j implements SydApi { final ByteBuffer bbs = ByteBuffer.allocate(v + 1024); - int packSize = 2048; + int packSize = 2048; // 2048/3072/4096 int packSizeDe = packSize + 16; // int fm = (int) data.get("fullMode$option"); int fm = (Integer) data.get("fullMode$option"); @@ -1625,7 +1623,9 @@ public class SydApi4j implements SydApi { } +// long t = System.currentTimeMillis(); bb = syncRead(syncSend(bb)); +// System.out.println("comm=" + ( System.currentTimeMillis() - t )); Packet p = proto.parse(bb, packet); @@ -2218,6 +2218,14 @@ public class SydApi4j implements SydApi { @Override public RetWrap generateDEByDn(String certSerial, String oData) { + if ( oData.length() <= 4 * 1024 ) { + return generateDEByDnHsm( certSerial, oData ); + } else { + return generateDEByDnSoft( certSerial, oData ); + } + } + + public RetWrap generateDEByDnHsm(String certSerial, String oData) { byte[] dnBytes = null; try { dnBytes = certSerial.getBytes("gbk"); @@ -2336,8 +2344,10 @@ public class SydApi4j implements SydApi { return rw; } - @Override - public RetWrap decryptDEByDN(String certSerial, String pCipherKey) { + + + + public RetWrap decryptDEByDNHsm(String certSerial, String pCipherKey) { byte[] dnBytes = null; try { dnBytes = certSerial.getBytes("gbk"); @@ -2442,6 +2452,7 @@ public class SydApi4j implements SydApi { try { X509Certificate x509 = getX509Certificate(new ByteArrayInputStream(cert.getBytes())); + X500Principal issuser = x509.getIssuerX500Principal(); String pk = ByteUtils.toHexString(x509.getPublicKey().getEncoded()); if (!pk.startsWith("03420004")) { @@ -2468,7 +2479,10 @@ public class SydApi4j implements SydApi { byte[] enData = (byte[]) retWrap.get("msg_all"); // 组织格式 - ContentInfo cms = genCMSEnvelopedData(Util.hexString2Bytes(ciperKey), enData); + ContentInfo cms = genCMSEnvelopedData(Util.hexString2Bytes(ciperKey), enData, + x509.getSerialNumber().toString(16) , + dnToMap(issuser.getName() ) + ); ret.put(SydApi.RET_CIPHER_KEY, Util.encodeBase64(cms.getEncoded())); @@ -2482,28 +2496,38 @@ public class SydApi4j implements SydApi { } } -// 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; -// } + private static MapdnToMap(String dn) { + Mapmap = new HashMap(); + String[] kvs = dn.split(","); + for ( String kv : kvs ) { + String[] ps = kv.split("="); + map.put( ps[0].trim() , ps[1].trim() ); + } + return map; + } - public static ContentInfo genCMSEnvelopedData(byte[] sessionKeyDer, byte[] enData) { + private RetWrap deCMSEnvelopedData(byte[] cms) { + 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 sn, Mapissuer) throws UnsupportedEncodingException { String tmpl = "3082014D06092A864886F70D010703A082013E3082013A0201003181F73081F40201003065305C310B300906035504061302434E3130302E060355040A0C274368696E612046696E616E6369616C2043657274696669636174696F6E20417574686F72697479311B301906035504030C1243464341205445535420534D32204F43413102051004282452300B06092A811CCF5501822D03047B307902203C3AF535307DA548DA02C0AD171D2BC24D22472B42E5E175FCAF2C5CD30B5443022100ED53E7594F35FFACEB57F05898123F78E5B2D045CC47D894CD2E7BD34D66DA1D042014BD71F8CDA9729093A7CC391E2009C5D5F007586C2EBFB55BC175A6E8BDA33E04104AB82510BFDDD4FEE79C3F107D6F7F94303B060A2A811CCF550601040201301B06072A811CCF55016804100000000000000000000000000000000080109FD3D4338DB19E672CC162AF5B9B03E9"; ContentInfo info = SydCmsUtil.getContentInfo(Util.hexString2Bytes(tmpl)); // 修改 @@ -2518,16 +2542,36 @@ public class SydApi4j implements SydApi { // 签发信息段 ASN1Sequence seq3 = (ASN1Sequence) seq2.getObjectAt(1).toASN1Primitive(); - System.out.println(seq3); + ASN1Integer isn = (ASN1Integer) seq3.getObjectAt(1 ).toASN1Primitive(); + BeanUtil.setFieldValue( isn, "bytes", Util.hexString2Bytes( sn ) ); + + ASN1Sequence seq4 = (ASN1Sequence) seq3.getObjectAt( 0 ).toASN1Primitive(); + ASN1Set setO = (ASN1Set) seq4.getObjectAt(1).toASN1Primitive(); + ASN1Sequence seqO = (ASN1Sequence) setO.getObjectAt(0).toASN1Primitive(); + DERUTF8String o = (DERUTF8String) seqO.getObjectAt(1).toASN1Primitive(); + BeanUtil.setFieldValue(o, "string", issuer.get("O").getBytes("UTF-8") ); + + ASN1Set setCN = (ASN1Set) seq4.getObjectAt(2).toASN1Primitive(); + ASN1Sequence seqCn = (ASN1Sequence) setCN.getObjectAt(0).toASN1Primitive(); + DERUTF8String Cn = (DERUTF8String) seqCn.getObjectAt(1).toASN1Primitive(); + BeanUtil.setFieldValue(Cn, "string", issuer.get("CN").getBytes("UTF-8") ); // 密文段 - ASN1Sequence seq4 = (ASN1Sequence) seq.getObjectAt(2).toASN1Primitive(); - ASN1TaggedObject tag = (ASN1TaggedObject) seq4.getObjectAt(2).toASN1Primitive(); + ASN1Sequence seq5 = (ASN1Sequence) seq.getObjectAt(2).toASN1Primitive(); + ASN1TaggedObject tag = (ASN1TaggedObject) seq5.getObjectAt(2).toASN1Primitive(); DEROctetString data = (DEROctetString) tag.getObject(); BeanUtil.setFieldValue(data, "string", enData); return info; } + public RetWrap decryptDEByDN(String certSerial, String pCipherKey){ + if ( pCipherKey.length() <= 4 * 1024 ) { + return decryptDEByDNHsm( certSerial, pCipherKey ); + } else { + return decryptDEByDNSoft( certSerial, pCipherKey ); + } + } + public RetWrap decryptDEByDNSoft(String certSerial, String pCipherKey) { byte[] dnBytes = null; try { @@ -2536,16 +2580,23 @@ public class SydApi4j implements SydApi { e.printStackTrace(); } -// RetWrap ret = deCMSEnvelopedData( Util.decodeBase64( pCipherKey ) ); + RetWrap ret = deCMSEnvelopedData( Util.decodeBase64( pCipherKey ) ); + byte[] sessionKeyDer = (byte[]) ret.get("sessionKeyDer"); + byte[] enData = (byte[]) ret.get("enData"); // 解密会话密钥 - - decryptDE(false, 1, dnBytes, pCipherKey); + ret = decryptDE(false, 1, dnBytes, Util.encodeBase64(sessionKeyDer) ); + String sessionKey = (String) ret.get("SessionKey"); // 解密原文 + byte[] iv = new byte[32]; + Arrays.fill(iv, (byte) 0x30); + RetWrap retWrap = SYMEnDeData(false, 1, sessionKey, 1, 1, enData, iv, 0); + byte[] data = (byte[]) retWrap.get("msg_all"); + ret.put("oData", data); - return null; + return ret; } diff --git a/src/test/java/com/sunyard/sydapi/test/TestE0.java b/src/test/java/com/sunyard/sydapi/test/TestE0.java new file mode 100644 index 0000000..2b38060 --- /dev/null +++ b/src/test/java/com/sunyard/sydapi/test/TestE0.java @@ -0,0 +1,45 @@ +package com.sunyard.sydapi.test; + +import com.sunyard.RetWrap; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import racal.sunyard.main.SydApi4j; + +import java.util.Arrays; + +public class TestE0 { + + private SydApi4j api; + private byte[] data = new byte[ 20 * 1024 * 1024 ]; + private byte[] iv = new byte[ 32 ]; + + @Before + public void before() { + // 通过设置debug的属性开启debug,如果不设置则默认不打开 + System.setProperty("com.sunyard.sydapi4j.debug", "true"); + api = (SydApi4j) new SydApi4j().connect("172.16.18.59", 8889, null, 1000); + Arrays.fill( iv, (byte) 0x38 ); + } + + @After + public void after() { + try { + this.api.disconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @Test + public void t1(){ + String sessionKeyByLMK = "X12345678123456781234567812345678"; + long start = System.currentTimeMillis(); + RetWrap retWrap = this.api.SYMEnDeData(true, 1, sessionKeyByLMK, 1, 1, data, iv, 0); + byte[] enData = (byte[]) retWrap.get("msg_all"); + long end = System.currentTimeMillis(); + System.out.println( "耗时=" + ( end - start ) ); + } + +} diff --git a/src/test/java/com/sunyard/sydapi/test/TestHT.java b/src/test/java/com/sunyard/sydapi/test/TestHT.java index 34ccec4..6202e5e 100644 --- a/src/test/java/com/sunyard/sydapi/test/TestHT.java +++ b/src/test/java/com/sunyard/sydapi/test/TestHT.java @@ -6,11 +6,15 @@ import com.sunyard.cert.X509; import com.sunyard.proto.Util; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import racal.sunyard.main.SydApi4j; +import java.io.File; +import java.io.FileOutputStream; import java.io.UnsupportedEncodingException; +import java.util.Arrays; /** * 衡泰例子 @@ -22,8 +26,8 @@ public class TestHT { @Before public void before() { // 通过设置debug的属性开启debug,如果不设置则默认不打开 - System.setProperty("com.sunyard.sydapi4j.debug", "true"); - api = (SydApi4j) new SydApi4j().connect("192.168.0.200", 8889, null, 1000); +// 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.66", 8889, null, 1000); } @@ -53,9 +57,11 @@ public class TestHT { @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"; + byte[] test = new byte[ 4 * 1024 ]; + Arrays.fill( test, (byte) 0x30 ); + String oData = new String(test); - RetWrap retWrap = api.generateDEByDnSoft(dn, oData); + RetWrap retWrap = api.generateDEByDn(dn, oData); String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); System.out.println("数字信封: " + cipherKey); @@ -66,17 +72,67 @@ public class TestHT { @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"; + String oData = "00001111222233000011112222330000111122223300001111222233000011112222330000111122223300001111222233"; - RetWrap retWrap = api.generateDEByDn(dn, oData); + RetWrap retWrap = api.generateDEByDnHsm(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")); + byte[] cat = (byte[]) retWrap1.get("oData"); + System.out.println("原数据: " + new String( cat )); + + Assert.assertEquals( oData, new String( cat )); } + @Test + public void testDecryptDE5Soft3() throws UnsupportedEncodingException { + + long t1 = System.currentTimeMillis(); + System.out.println("start"); + + String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1"; + byte[] aData = new byte[ 20 * 1024 * 1024 ]; + Arrays.fill( aData, (byte) 0x55 ); + + String oData = new String( aData ); + RetWrap retWrap = api.generateDEByDnSoft(dn, oData); + String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY); + System.out.println("数字信封: " + cipherKey); + write("./cms.p7", cipherKey.getBytes()); + long t2 = System.currentTimeMillis(); + System.out.println("加密耗时=" + ( t2 - t1 )); + + RetWrap retWrap1 = api.decryptDEByDNSoft(dn, cipherKey); + byte[] cat = (byte[]) retWrap1.get("oData"); + System.out.println("原数据: " + new String( cat )); + long t3 = System.currentTimeMillis(); + System.out.println("解密耗时=" + ( t3 - t2 )); + System.out.println("总耗时=" + ( t3 - t1 )); + + Assert.assertEquals( oData, new String( cat )); + } + + public static void write(String path, byte[] data){ + try { + File f = new File( path ); + if ( f.exists() ) { + f.createNewFile(); + } + FileOutputStream out = new FileOutputStream( f ); + try { + out.write( data ); + out.flush(); + out.close(); + } finally { + out.close(); + } + }catch ( Exception e ){ + e.printStackTrace(); + } + } + // // 测试通过 // 73 diff --git a/src/test/java/com/sunyard/sydapi/util/SydCmsUtilTest.java b/src/test/java/com/sunyard/sydapi/util/SydCmsUtilTest.java index c249d4f..9b83129 100644 --- a/src/test/java/com/sunyard/sydapi/util/SydCmsUtilTest.java +++ b/src/test/java/com/sunyard/sydapi/util/SydCmsUtilTest.java @@ -45,38 +45,38 @@ public class SydCmsUtilTest { 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(); - } - } +// 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(); +// } +// } }