完善RSA大数据数字信封

This commit is contained in:
yihzhou 2022-10-28 11:20:22 +08:00
parent c95130c6ed
commit fd6ef6050f
4 changed files with 501 additions and 193 deletions

View File

@ -1,229 +1,229 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<packet extend="base"> <packet extend="base">
<req> <req>
<command> <command>
<hex>6A</hex> <hex>6A</hex>
</command> </command>
<data extend="data"> <data extend="data">
<alg len="1" cn="算法标识"> <alg len="1" cn="算法标识">
<options> <options>
<option cn="RSA2048_AES256_ECB"> <option cn="RSA2048_AES256_ECB">
<hex>0</hex> <hex>0</hex>
</option> </option>
<option cn="SM2_SM4_ECB"> <option cn="SM2_SM4_ECB">
<hex>1</hex> <hex>1</hex>
</option> </option>
<option cn="SM2_SM4_ECB 机构码|02|密钥"> <option cn="SM2_SM4_ECB 机构码|02|密钥">
<hex>2</hex> <hex>2</hex>
</option> </option>
<option cn="PKCS7_SM2_SM4_ECB"> <option cn="PKCS7_SM2_SM4_ECB">
<hex>3</hex> <hex>3</hex>
</option> </option>
<option cn="RSA2048_AES256_CBC"> <option cn="RSA2048_AES256_CBC">
<hex>4</hex> <hex>4</hex>
</option> </option>
</options> </options>
</alg> </alg>
<pFlag len="1" required="false" cn="P标志"> <pFlag len="1" required="false" cn="P标志">
可选存在则固定值为P 可选存在则固定值为P
</pFlag> </pFlag>
<certificateModel len="1" cn="证书模式"> <certificateModel len="1" cn="证书模式">
<options> <options>
<option cn="证书序号"> <option cn="证书序号">
<hex>0</hex> <hex>0</hex>
</option> </option>
<option cn="证书 DN"> <option cn="证书 DN">
<hex>1</hex> <hex>1</hex>
</option> </option>
</options> </options>
</certificateModel> </certificateModel>
<certificateLen len="4" :value="certificateLen()" cn="证书内容长度"> <certificateLen len="4" :value="certificateLen()" cn="证书内容长度">
根据证书模式,需要输入内容项的长度 n 根据证书模式,需要输入内容项的长度 n
</certificateLen> </certificateLen>
<certificateSn :len="strlen()" :if="0 == $packet.data.certificateModel$option" cn="X509 证书序号"> <certificateSn :len="strlen()" :if="0 == $packet.data.certificateModel$option" cn="X509 证书序号">
可选项,只针对“证书模式”为 0时有。 可选项,只针对“证书模式”为 0时有。
</certificateSn> </certificateSn>
<certificateDn :len="strlen()" :if="1 == $packet.data.certificateModel$option" cn="X509 证书的 subject"> <certificateDn :len="strlen()" :if="1 == $packet.data.certificateModel$option" cn="X509 证书的 subject">
可选项,只针对“证书模式”为 1时有。 可选项,只针对“证书模式”为 1时有。
</certificateDn> </certificateDn>
<orgDataLen len="4" :value="dataLen()" :if="3 == $packet.data.alg$option||4 == $packet.data.alg$option" cn="数据长度"> <orgDataLen len="4" :value="dataLen()" :if="3 == $packet.data.alg$option||4 == $packet.data.alg$option" cn="数据长度">
只针对算法标识为3、4时传入 只针对算法标识为3、4时传入
</orgDataLen> </orgDataLen>
<orgData :if="3 == $packet.data.alg$option||4== $packet.data.alg$option" cn="数据长度"> <orgData :if="3 == $packet.data.alg$option||4== $packet.data.alg$option" cn="数据长度">
只针对算法标识为3、4时传入 只针对算法标识为3、4时传入
</orgData> </orgData>
<keyType len="1" cn="加密密钥方案"> <keyType len="1" cn="加密密钥方案">
LMK 下加密密钥的方案。 LMK 下加密密钥的方案。
</keyType> </keyType>
<orgCodeLen len="2" :value="orgCodeLen()" :if="hasOrgCode()" cn="机构码长度"> <orgCodeLen len="2" :value="orgCodeLen()" :if="hasOrgCode()" cn="机构码长度">
公钥加密的密钥格式3所需机构码长度仅当格式3以及'P'存在时存在 公钥加密的密钥格式3所需机构码长度仅当格式3以及'P'存在时存在
</orgCodeLen> </orgCodeLen>
<orgCode :if="hasOrgCode()" cn="机构码长度"> <orgCode :if="hasOrgCode()" cn="机构码长度">
公钥加密的密钥格式3所需机构码长度仅当格式3以及'P'存在时存在 公钥加密的密钥格式3所需机构码长度仅当格式3以及'P'存在时存在
</orgCode> </orgCode>
<!-- 新增功能--> <!-- 新增功能-->
<pSignFlag len="1" required="false" cn="可选字段"> <pSignFlag len="1" required="false" cn="可选字段">
签名数字信封标识符存在则为P 签名数字信封标识符存在则为P
</pSignFlag> </pSignFlag>
<signCertificateLen len="4" :value="signCertificateLen()" :if="hasOrgCN()" cn="签名证书DN长度"> <signCertificateLen len="4" :value="signCertificateLen()" :if="hasOrgCN()" cn="签名证书DN长度">
可选项,只针对"可选字段"为P时存在。 可选项,只针对"可选字段"为P时存在。
</signCertificateLen> </signCertificateLen>
<signCertificateDn :len="strlen()" :if="hasOrgCN()" cn="签名证书DN"> <signCertificateDn :len="strlen()" :if="hasOrgCN()" cn="签名证书DN">
可选项只针对“证书模式”为1时有,只针对"可选字段"为P时存在。 可选项只针对“证书模式”为1时有,只针对"可选字段"为P时存在。
</signCertificateDn> </signCertificateDn>
<signCertificateModel len="1" :if="hasOrgCN()" cn="是否附带公钥信息"> <signCertificateModel len="1" :if="hasOrgCN()" cn="是否附带公钥信息">
<options> <options>
<option cn="无需附带"> <option cn="无需附带">
<hex>0</hex> <hex>0</hex>
</option> </option>
<option cn="附带公钥信息"> <option cn="附带公钥信息">
<hex>1</hex> <hex>1</hex>
</option> </option>
</options> </options>
</signCertificateModel> </signCertificateModel>
<tailSep len="1" :if=" null != $packet.data.tail " cn="尾分隔"> <tailSep len="1" :if=" null != $packet.data.tail " cn="尾分隔">
可选项。如果显示消息尾域,则该域必须显示。值为 可选项。如果显示消息尾域,则该域必须显示。值为
“X19”。 “X19”。
<hex>19</hex> <hex>19</hex>
</tailSep> </tailSep>
<tail maxLen="32" required="false" cn="尾部"> <tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。 可选项。最大长度为 32个字符。
</tail> </tail>
</data> </data>
</req> </req>
<res> <res>
<command> <command>
<hex>6B</hex> <hex>6B</hex>
</command> </command>
<data> <data>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')"> <error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options> <options>
<option cn="无错误"> <option cn="无错误">
<hex>00</hex> <hex>00</hex>
</option> </option>
<option cn="公钥不符合编码规则"> <option cn="公钥不符合编码规则">
<hex>04</hex> <hex>04</hex>
</option> </option>
<option cn="无效的加密标识"> <option cn="无效的加密标识">
<hex>06</hex> <hex>06</hex>
</option> </option>
<option cn="无效的附加模式标识"> <option cn="无效的附加模式标识">
<hex>07</hex> <hex>07</hex>
</option> </option>
<option cn="密钥奇偶校验错误"> <option cn="密钥奇偶校验错误">
<hex>10</hex> <hex>10</hex>
</option> </option>
<option cn="LMK 错误"> <option cn="LMK 错误">
LMK 错误;报告给管理员。 LMK 错误;报告给管理员。
<hex>13</hex> <hex>13</hex>
</option> </option>
<option cn="输入数据错"> <option cn="输入数据错">
<hex>15</hex> <hex>15</hex>
</option> </option>
<option cn="DSP 错误"> <option cn="DSP 错误">
DSP 错误;报告给管理员。 DSP 错误;报告给管理员。
<hex>47</hex> <hex>47</hex>
</option> </option>
<option cn="密钥块长度错误"> <option cn="密钥块长度错误">
<hex>76</hex> <hex>76</hex>
</option> </option>
<option cn="输入数据长度错误"> <option cn="输入数据长度错误">
<hex>80</hex> <hex>80</hex>
</option> </option>
</options> </options>
</error> </error>
<keyLen len="4" cn="密钥密文长度"> <keyLen len="4" cn="密钥密文长度">
公钥加密的密钥密文长度 公钥加密的密钥密文长度
</keyLen> </keyLen>
<key :len="getKeyLen()" cn="密钥密文"> <key :len="getKeyLen()" cn="密钥密文">
公钥加密的密钥密文的 BASE64 编码 公钥加密的密钥密文的 BASE64 编码
</key> </key>
<lmkHead len="1" cn="lmk 头"> <lmkHead len="1" cn="lmk 头">
如果是 'L' lmk 32 个字节长,否则 lmk 64 个字节长。 如果是 'L' lmk 32 个字节长,否则 lmk 64 个字节长。
</lmkHead> </lmkHead>
<lmk :len="lmkLen()" cn="对称密钥的密文"> <lmk :len="lmkLen()" cn="对称密钥的密文">
对称密钥的密文,由 LMK30-31 保护。 对称密钥的密文,由 LMK30-31 保护。
</lmk> </lmk>
<keyCheck len="16" cn="密钥校验值"> <keyCheck len="16" cn="密钥校验值">
密钥校验值 密钥校验值
</keyCheck> </keyCheck>
<tailSep len="1" required="false" cn="尾分隔"> <tailSep len="1" required="false" cn="尾分隔">
可选项。如果显示消息尾域,则该域必须显示。值为 “X19”。 可选项。如果显示消息尾域,则该域必须显示。值为 “X19”。
<hex>19</hex> <hex>19</hex>
</tailSep> </tailSep>
<tail maxLen="32" required="false" cn="尾部"> <tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。 可选项。最大长度为 32个字符。
</tail> </tail>
</data> </data>
</res> </res>
<script> <script>
function certificateLen(){ function certificateLen(){
var data = $packet.data; var data = $packet.data;
if( 0 == data.certificateModel$option ){ if( 0 == data.certificateModel$option ){
return data.certificateSn.length return data.certificateSn.length
} }
if( 1 == data.certificateModel$option ){ if( 1 == data.certificateModel$option ){
return data.certificateDn.length return data.certificateDn.length
} }
} }
function signCertificateLen(){ function signCertificateLen(){
var data = $packet.data; var data = $packet.data;
if( 'P' == $packet.data.pSignFlag ){ if( 'P' == $packet.data.pSignFlag ){
return data.signCertificateDn.length return data.signCertificateDn.length
} }
return null; return null;
} }
function getKeyLen() { function getKeyLen() {
return Util.a2i( $final.getSection('data').getSection('keyLen') ); return Util.a2i( $final.getSection('data').getSection('keyLen') );
} }
function lmkLen() { function lmkLen() {
if( Arrays.equals("L".getBytes(), if( Arrays.equals("L".getBytes(),
$final.getSection('data').getSection('lmkHead').getValue() $final.getSection('data').getSection('lmkHead').getValue()
) ){ ) ){
return 64; return 64;
}else{ }else{
return 32; return 32;
} }
} }
function dataLen() { function dataLen() {
return $packet.data.orgData.length() return $packet.data.orgData.length
} }

191
DProto/6BRSA.xml Normal file
View File

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8" ?>
<packet extend="base">
<req>
<command>
<hex>6B</hex>
</command>
<data extend="data">
<pFlag len="1" required="false" cn="P标志">
可选如果输入P代表使用PKCS7_SM2_SM4_ECB模式解密数字信封
</pFlag>
<certificateModel len="1" cn="证书模式">
<options>
<option cn="证书序号">
<hex>0</hex>
</option>
<option cn="证书 DN">
<hex>1</hex>
</option>
</options>
</certificateModel>
<certificateLen len="4" :value="certificateLen()" cn="证书内容长度">
根据证书模式,需要输入内容项的长度 n
</certificateLen>
<certificateSn :len="strlen()" :if="0 == $packet.data.certificateModel$option" cn="X509 证书序号">
可选项,只针对“证书模式”为 0时有。
</certificateSn>
<certificateDn :if="1 == $packet.data.certificateModel$option" cn="X509 证书的 subject">
可选项,只针对“证书模式”为 1时有。
</certificateDn>
<keyLen len="4" :value="keyLen()" cn="密钥密文长度">
公钥加密的密钥密文长度
</keyLen>
<key :len="getKeyLen()" cn="密钥密文">
公钥加密的密钥密文的 BASE64 编码
</key>
<keyType len="1" cn="加密密钥方案">
LMK 下加密密钥的方案。
</keyType>
<tailSep len="1" :if=" null != $packet.data.tail " cn="尾分隔">
可选项。如果显示消息尾域,则该域必须显示。值为
“X19”。
<hex>19</hex>
</tailSep>
<tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。
</tail>
</data>
</req>
<res>
<command>
<hex>6C</hex>
</command>
<data>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options>
<option cn="无错误">
<hex>00</hex>
</option>
<option cn="公钥不符合编码规则">
<hex>04</hex>
</option>
<option cn="无效的加密标识">
<hex>06</hex>
</option>
<option cn="无效的附加模式标识">
<hex>07</hex>
</option>
<option cn="密钥奇偶校验错误">
<hex>10</hex>
</option>
<option cn="LMK 错误">
LMK 错误;报告给管理员。
<hex>13</hex>
</option>
<option cn="输入数据错">
<hex>15</hex>
</option>
<option cn="输入的数据格式错误">
<hex>21</hex>
</option>
<option cn="DSP 错误">
DSP 错误;报告给管理员。
<hex>47</hex>
</option>
<option cn="密钥块长度错误">
<hex>76</hex>
</option>
<option cn="输入数据长度错误">
<hex>80</hex>
</option>
</options>
</error>
<oDataLen len="4" cn="明文数据长度">
明文原始数据长度只针对P存在时无P时为0
</oDataLen>
<oData :len="oDataLen()" cn="明文数据">
原始数据只针对P存在时无P时不存在
</oData>
<!--<keyLen len="4" cn="密钥密文长度">-->
<!--公钥加密的密钥密文长度-->
<!--</keyLen>-->
<lmkHead len="1" cn="lmk 头">
如果是 'L' lmk 32 个字节长,否则 lmk 64 个字节长。
</lmkHead>
<lmk :len="lmkLen()" cn="对称密钥的密文">
对称密钥的密文,由 LMK30-31 保护。
</lmk>
<keyCheck len="16" cn="密钥校验值">
密钥校验值
</keyCheck>
<orgCodeLen len="4" cn="机构码长度">
公钥加密的密钥格式3所需机构码长度仅当格式3以及'P'存在时存在
</orgCodeLen>
<orgCode :len="orgCodeLen()" cn="机构码长度">
公钥加密的密钥格式3所需机构码长度仅当格式3以及'P'存在时存在
</orgCode>
<tailSep len="1" required="false" cn="尾分隔">
可选项。如果显示消息尾域,则该域必须显示。值为 “X19”。
<hex>19</hex>
</tailSep>
<tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。
</tail>
</data>
</res>
<script>
function certificateLen(){
var data = $packet.data;
if( 0 == data.certificateModel$option ){
return data.certificateSn.length
}
if( 1 == data.certificateModel$option ){
return data.certificateDn.length
}
}
function keyLen() {
return $packet.data.key.length
}
function getKeyLen() {
return Util.a2i( $final.getSection('data').getSection('keyLen') )
}
function lmkLen() {
if( Arrays.equals("L".getBytes(),
$final.getSection('data').getSection('lmkHead').getValue()
) ){
return 64
}else{
return 32
}
}
function orgCodeLen() {
return Util.a2i( $final.getSection('data').getSection('orgCodeLen') )
}
function oDataLen() {
return Util.a2i( $final.getSection('data').getSection('oDataLen') )
}
</script>
</packet>

View File

@ -2766,7 +2766,7 @@ public class SydApi4j implements SydApi {
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); e.printStackTrace();
} }
return generateDE(dnBytes, 0, 1, oData); return generateDE(dnBytes, 4, 1, oData);
} }
@Override @Override
@ -2786,11 +2786,15 @@ public class SydApi4j implements SydApi {
data.put("certificateDn", certSerial); data.put("certificateDn", certSerial);
} }
if (alg == 3 || alg == 0 ) { if (alg == 3 || alg == 4 ) {
data.put("orgData", oData); data.put("orgData", oData);
} }
data.put("keyType", "X"); data.put("keyType", "X");
if(alg == 4 ){
data.put("keyType", "L");
}
packet.put("data", data); packet.put("data", data);
// 渲染发送 耗时长 // 渲染发送 耗时长
@ -3072,12 +3076,12 @@ public class SydApi4j implements SydApi {
X500Principal issuser = x509.getIssuerX500Principal(); X500Principal issuser = x509.getIssuerX500Principal();
String pk = ByteUtils.toHexString(x509.getPublicKey().getEncoded()); String pk = ByteUtils.toHexString(x509.getPublicKey().getEncoded());
if (!pk.startsWith("03420004")) { if (!pk.startsWith("3082010")) {
int i = pk.indexOf("03420004"); int i = pk.indexOf("3082010");
if ( i >= 0 ) { if ( i >= 0 ) {
pk = pk.substring(i); pk = pk.substring(i);
} else { } else {
pk = "03420004" + pk; pk = "3082010" + pk;
} }
} }
@ -3098,7 +3102,7 @@ public class SydApi4j implements SydApi {
byte[] enData = (byte[]) retWrap.get("msg_all"); 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) , x509.getSerialNumber().toString(16) ,
dnToMap(issuser.getName() ) dnToMap(issuser.getName() )
); );
@ -3188,6 +3192,45 @@ public class SydApi4j implements SydApi {
return info; return info;
} }
public static ContentInfo genCMSEnvelopedDataRSA(byte[] sessionKeyDer, byte[] enData, String sn, Map<String, String>issuer) 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){ public RetWrap decryptDEByDN(String certSerial, byte[] pCipherKey){
if ( pCipherKey.length <= 4 * 1024 ) { if ( pCipherKey.length <= 4 * 1024 ) {
return decryptDEByDNHsm( certSerial, new String(pCipherKey) ); return decryptDEByDNHsm( certSerial, new String(pCipherKey) );
@ -3272,7 +3315,9 @@ public class SydApi4j implements SydApi {
iv = Util.bytes2HexString( iv ).getBytes(); 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") ); String sessionKey = new String((byte[]) ret.get("SessionKey") );
RetWrap retWrap = SYMEnDeData(false, 2, sessionKey, 1, 1, enData, iv, 0); RetWrap retWrap = SYMEnDeData(false, 2, sessionKey, 1, 1, enData, iv, 0);
@ -3364,8 +3409,9 @@ public class SydApi4j implements SydApi {
HashMap<String, Object> packet = new HashMap<String, Object>(); HashMap<String, Object> packet = new HashMap<String, Object>();
packet.put("header", sn.getSn().array()); packet.put("header", sn.getSn().array());
HashMap<String, Object> data = new HashMap<String, Object>(); HashMap<String, Object> data = new HashMap<String, Object>();
if (pFlag) { data.put("pFlag", "R");
data.put("pFlag", "R"); if (!pFlag) {
data.put("pFlag", "Q");
} }
data.put("certificateModel$option", model); data.put("certificateModel$option", model);
@ -3375,7 +3421,7 @@ public class SydApi4j implements SydApi {
data.put("certificateDn", certSerial); data.put("certificateDn", certSerial);
} }
data.put("key", pCipherKey); data.put("key", pCipherKey);
data.put("keyType", "X"); data.put("keyType", "L");
packet.put("data", data); packet.put("data", data);
// 渲染发送 // 渲染发送
@ -3401,10 +3447,79 @@ public class SydApi4j implements SydApi {
} }
RetWrap rw = new RetWrap(); RetWrap rw = new RetWrap();
if (pFlag) { // if (pFlag) {
rw.put("oData", ((PacketSection) ret.get("oData")).getBytes()); // 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<String, Object> packet = new HashMap<String, Object>();
packet.put("header", sn.getSn().array());
HashMap<String, Object> data = new HashMap<String, Object>();
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<String, Object> ret = p.toMap();
if (
!Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes())
) {
throw new SydApiException("包序号不匹配", -4);
}
ret = (Map<String, Object>) 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); int orgCodeLen = Util.a2i(((PacketSection) ret.get("orgCodeLen")).getBytes(), 10);
if (orgCodeLen != 0) { if (orgCodeLen != 0) {
rw.put("orgCode", ((PacketSection) ret.get("orgCode")).getBytes()); rw.put("orgCode", ((PacketSection) ret.get("orgCode")).getBytes());

View File

@ -21,7 +21,7 @@ import java.util.List;
import static com.sunyard.sydapi.util.PrintUtil.printRetWrap; import static com.sunyard.sydapi.util.PrintUtil.printRetWrap;
public class Shanghairenhang { 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 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"; 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: 明文数据 * @param pcData: 明文数据
* @return RetWrap: 数字信封 * @return RetWrap: 数字信封
*/ */
RetWrap signData = api.generateDEByDn(0,RSA, orgData.getBytes()); RetWrap signData = api.generateDEByDn(4,RSA, orgData2k);
byte[] cpkey2 = (byte[]) signData.get("CipherKey"); byte[] cpkey2 = (byte[]) signData.get("CipherKey");
System.out.println("加密信封:" + new String(cpkey2)); System.out.println("加密信封:" + new String(cpkey2));
@ -51,10 +51,12 @@ public class Shanghairenhang {
* @param cpkey: 数字信封 * @param cpkey: 数字信封
* @return preData: 原数据 * @return preData: 原数据
*/ */
RetWrap oDataWrap = api.decryptDEByDN(0,RSA, cpkey2); RetWrap oDataWrap = api.decryptDEByDN(4,RSA, cpkey2);
byte[] preData = (byte[]) oDataWrap.get("oData"); byte[] preData = (byte[]) oDataWrap.get("oData");
System.out.println("解密信封:" + Util.bytes2HexString(preData)); System.out.println("解密信封:" + Util.bytes2HexString(preData));
// //
} catch (Exception e) { } catch (Exception e) {