20M 数字信封支持

This commit is contained in:
cheney 2022-06-21 15:39:55 +08:00
parent 4404f89dd6
commit 787be6e294
5 changed files with 228 additions and 75 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@
/public/
/.DS_Store
src/test/java/com/sunyard/sydapi/sample/*.*
*.p7

View File

@ -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 Map<String, String>dnToMap(String dn) {
Map<String, String>map = new HashMap<String, String>();
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, Map<String, String>issuer) 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;
}

View File

@ -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 ) );
}
}

View File

@ -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

View File

@ -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();
// }
// }
}