diff --git a/DProto/6A.xml b/DProto/6A.xml index 4c3c2f0..28e98ea 100644 --- a/DProto/6A.xml +++ b/DProto/6A.xml @@ -1,229 +1,229 @@ - + - - 6A - - - - - - - - - - - + + 6A + + + + + + + + + + + - - 可选,存在,则固定值为‘P’ - + + 可选,存在,则固定值为‘P’ + - - - - - - + + + + + + - - 根据证书模式,需要输入内容项的长度 n - + + 根据证书模式,需要输入内容项的长度 n + - - 可选项,只针对“证书模式”为 0时有。 - + + 可选项,只针对“证书模式”为 0时有。 + - - 可选项,只针对“证书模式”为 1时有。 - + + 可选项,只针对“证书模式”为 1时有。 + - - 只针对算法标识为3、4时传入 - + + 只针对算法标识为3、4时传入 + - - 只针对算法标识为3、4时传入 - + + 只针对算法标识为3、4时传入 + - - LMK 下加密密钥的方案。 - + + LMK 下加密密钥的方案。 + - - 公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在 - + + 公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在 + - - 公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在 - + + 公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在 + - - - 签名数字信封标识符,存在则为P - + + + 签名数字信封标识符,存在则为P + - - 可选项,只针对"可选字段"为P时存在。 - + + 可选项,只针对"可选字段"为P时存在。 + - - 可选项,只针对“证书模式”为1时有,只针对"可选字段"为P时存在。 - - - - - - - + + 可选项,只针对“证书模式”为1时有,只针对"可选字段"为P时存在。 + + + + + + + - - 可选项。如果显示消息尾域,则该域必须显示。值为 - “X’19”。 - 19 - + + 可选项。如果显示消息尾域,则该域必须显示。值为 + “X’19”。 + 19 + - - 可选项。最大长度为 32个字符。 - - + + 可选项。最大长度为 32个字符。 + + - + - - - 6B - - - - - - - - - - - - - - - - + + + 6B + + + + + + + + + + + + + + + + - - 公钥加密的密钥密文长度 - + + 公钥加密的密钥密文长度 + - - 公钥加密的密钥密文的 BASE64 编码 - + + 公钥加密的密钥密文的 BASE64 编码 + - - 如果是 'L' ,lmk 32 个字节长,否则 lmk 64 个字节长。 - + + 如果是 'L' ,lmk 32 个字节长,否则 lmk 64 个字节长。 + - - 对称密钥的密文,由 LMK30-31 保护。 - + + 对称密钥的密文,由 LMK30-31 保护。 + - - 密钥校验值 - + + 密钥校验值 + - - 可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。 - 19 - + + 可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。 + 19 + - - 可选项。最大长度为 32个字符。 - - + + 可选项。最大长度为 32个字符。 + + - - + diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index b35d542..2d68583 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -2766,7 +2766,7 @@ public class SydApi4j implements SydApi { } catch (UnsupportedEncodingException e) { e.printStackTrace(); } - return generateDE(dnBytes, 0, 1, oData); + return generateDE(dnBytes, 4, 1, oData); } @Override @@ -2786,11 +2786,15 @@ public class SydApi4j implements SydApi { data.put("certificateDn", certSerial); } - if (alg == 3 || alg == 0 ) { + if (alg == 3 || alg == 4 ) { data.put("orgData", oData); } data.put("keyType", "X"); + if(alg == 4 ){ + data.put("keyType", "L"); + } + packet.put("data", data); // 渲染发送 耗时长 @@ -3072,12 +3076,12 @@ public class SydApi4j implements SydApi { X500Principal issuser = x509.getIssuerX500Principal(); String pk = ByteUtils.toHexString(x509.getPublicKey().getEncoded()); - if (!pk.startsWith("03420004")) { - int i = pk.indexOf("03420004"); + if (!pk.startsWith("3082010")) { + int i = pk.indexOf("3082010"); if ( i >= 0 ) { pk = pk.substring(i); } else { - pk = "03420004" + pk; + pk = "3082010" + pk; } } @@ -3098,7 +3102,7 @@ public class SydApi4j implements SydApi { byte[] enData = (byte[]) retWrap.get("msg_all"); // 组织格式 - ContentInfo cms = genCMSEnvelopedData( Util.hexString2Bytes(ciperKey), enData, + ContentInfo cms = genCMSEnvelopedDataRSA( Util.hexString2Bytes(ciperKey), enData, x509.getSerialNumber().toString(16) , dnToMap(issuser.getName() ) ); @@ -3188,6 +3192,45 @@ public class SydApi4j implements SydApi { return info; } + public static ContentInfo genCMSEnvelopedDataRSA(byte[] sessionKeyDer, byte[] enData, String sn, Mapissuer) throws UnsupportedEncodingException { + String tmpl = "308201d506092a864886f70d010703a08201c6308201c20201003182017c3082017802010030623059310b300906035504061302434e3130302e060355040a13274368696e612046696e616e6369616c2043657274696669636174696f6e20417574686f72697479311830160603550403130f434643412054455354204f4341313102052003470933300b06092a864886f70d01010104820100e0f8d8cf94321e7b41452845e98d5998d8c0af8aaf63a5c67a05c27c82eac3f7251d0374e59a53af39898de43a6ed9e8ca642cf3b9d19be7529be767491452b990938199384f5f7f244055ed6472e29fec18103f868109cde28f40641ddaa3c408d0629c05ec8f34b1d629975f03e05734c9931f4eae9fce912a0f8e7f726b02f3696b31c6155c191b245c8ebbb381da6f19a0b5e00e3006a3084f6519874c871ae054eae1f723aaf20982d78864b72153e47960e606cc448ece1f75a8a2f08aab2b8773af1569089253c46b7c4deab20d47a671a7f5bf06546087b98885507b69bd186c73a658efbcdd2edd5b55ea515c38729dd386425132cd5a95b5cd8e2d303d060a2a811ccf550601040201301d060960864801650304012a041000000000000000000000000000000000801043cfb263acadf7f0a5071fd7f94282ab"; + 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(); + 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 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, byte[] pCipherKey){ if ( pCipherKey.length <= 4 * 1024 ) { return decryptDEByDNHsm( certSerial, new String(pCipherKey) ); @@ -3272,7 +3315,9 @@ public class SydApi4j implements SydApi { iv = Util.bytes2HexString( iv ).getBytes(); // 解密会话密钥 - ret = decryptDERSA(true, 1, dnBytes, Util.encodeBase64(sessionKeyDer) ); + //ret = decryptDERSA(false, 1, dnBytes, Util.encodeBase64(sessionKeyDer) ); + ret = decryptDERSA(false, 1, dnBytes,sessionKeyDer); + String sessionKey = new String((byte[]) ret.get("SessionKey") ); RetWrap retWrap = SYMEnDeData(false, 2, sessionKey, 1, 1, enData, iv, 0); @@ -3364,8 +3409,9 @@ public class SydApi4j implements SydApi { HashMap packet = new HashMap(); packet.put("header", sn.getSn().array()); HashMap data = new HashMap(); - if (pFlag) { - data.put("pFlag", "R"); + data.put("pFlag", "R"); + if (!pFlag) { + data.put("pFlag", "Q"); } data.put("certificateModel$option", model); @@ -3375,7 +3421,7 @@ public class SydApi4j implements SydApi { data.put("certificateDn", certSerial); } data.put("key", pCipherKey); - data.put("keyType", "X"); + data.put("keyType", "L"); packet.put("data", data); // 渲染发送 @@ -3401,10 +3447,79 @@ public class SydApi4j implements SydApi { } RetWrap rw = new RetWrap(); - if (pFlag) { - rw.put("oData", ((PacketSection) ret.get("oData")).getBytes()); +// if (pFlag) { +// rw.put("oData", ((PacketSection) ret.get("oData")).getBytes()); +// } + rw.put("oData", ((PacketSection) ret.get("oData")).getBytes()); + + int orgCodeLen = Util.a2i(((PacketSection) ret.get("orgCodeLen")).getBytes(), 10); + if (orgCodeLen != 0) { + rw.put("orgCode", ((PacketSection) ret.get("orgCode")).getBytes()); } + rw.put(SydApi.RET_SESSION_KEY, (((PacketSection) ret.get("lmkHead")).getString() + + ((PacketSection) ret.get("lmk")).getString()).getBytes() + ); + + rw.put(SydApi.RET_KCV, ((PacketSection) ret.get("keyCheck")).getBytes()); + + return rw; + } + + + public RetWrap decryptDERSA(boolean pFlag, int model, byte[] certSerial, byte[] pCipherKey) { + // 获取协议 + //ProtocolRender render = pset.getProtocolReqRender("6B"); + // 与6B相同 + Proto6BRSA proto = new Proto6BRSA(); + // 填充数据 + PacketSN sn = PacketSN.gen(); + HashMap packet = new HashMap(); + packet.put("header", sn.getSn().array()); + HashMap data = new HashMap(); + data.put("pFlag", "R"); + if (!pFlag) { + data.put("pFlag", "Q"); + } + data.put("certificateModel$option", model); + + if (model == 0) { + data.put("certificateSn", certSerial); + } else { + data.put("certificateDn", certSerial); + } + data.put("key", pCipherKey); + data.put("keyType", "L"); + packet.put("data", data); + + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + //ProtocolParser parser = pset.getProtocolResParse(); + Packet p = proto.parse(bb); + + Map ret = p.toMap(); + if ( + !Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes()) + ) { + throw new SydApiException("包序号不匹配", -4); + } + ret = (Map) ret.get("data"); + PacketSection error = (PacketSection) ret.get("error"); + if (!"00".equals(error.getString())) { + throw new SydApiException(error.getInfo(), error.autoInt()); + } + RetWrap rw = new RetWrap(); + +// if (pFlag) { +// rw.put("oData", ((PacketSection) ret.get("oData")).getBytes()); +// } + rw.put("oData", ((PacketSection) ret.get("oData")).getBytes()); + int orgCodeLen = Util.a2i(((PacketSection) ret.get("orgCodeLen")).getBytes(), 10); if (orgCodeLen != 0) { rw.put("orgCode", ((PacketSection) ret.get("orgCode")).getBytes()); diff --git a/src/test/java/sample/Shanghairenhang.java b/src/test/java/sample/Shanghairenhang.java index 8f0599c..1eb2aa1 100644 --- a/src/test/java/sample/Shanghairenhang.java +++ b/src/test/java/sample/Shanghairenhang.java @@ -21,7 +21,7 @@ import java.util.List; import static com.sunyard.sydapi.util.PrintUtil.printRetWrap; public class Shanghairenhang { - private static final byte[] orgData2k = new byte[ 16 ]; + private static final byte[] orgData2k = new byte[ 5*1024 ]; private static final String pcDnEN = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1"; private static final String RSA = "C=cn,O=CFCA TEST CA,OU=NCS2,OU=Enterprises,CN=041@Z402451000010@ShanDong@00000001"; @@ -41,7 +41,7 @@ public class Shanghairenhang { * @param pcData: 明文数据。 * @return RetWrap: 数字信封 */ - RetWrap signData = api.generateDEByDn(0,RSA, orgData.getBytes()); + RetWrap signData = api.generateDEByDn(4,RSA, orgData2k); byte[] cpkey2 = (byte[]) signData.get("CipherKey"); System.out.println("加密信封:" + new String(cpkey2)); @@ -51,10 +51,12 @@ public class Shanghairenhang { * @param cpkey: 数字信封。 * @return preData: 原数据 */ - RetWrap oDataWrap = api.decryptDEByDN(0,RSA, cpkey2); + RetWrap oDataWrap = api.decryptDEByDN(4,RSA, cpkey2); byte[] preData = (byte[]) oDataWrap.get("oData"); System.out.println("解密信封:" + Util.bytes2HexString(preData)); + + // } catch (Exception e) {