diff --git a/DProto/4D41.xml b/DProto/4D41.xml index 420cbee..6c9b20f 100644 --- a/DProto/4D41.xml +++ b/DProto/4D41.xml @@ -34,11 +34,9 @@ - 0 - 1 diff --git a/DProto/4D43.xml b/DProto/4D43.xml index 79fdf86..9ec141f 100644 --- a/DProto/4D43.xml +++ b/DProto/4D43.xml @@ -34,11 +34,9 @@ - 0 - 1 diff --git a/DProto/8008.xml b/DProto/8008.xml new file mode 100644 index 0000000..4cbd3c0 --- /dev/null +++ b/DProto/8008.xml @@ -0,0 +1,116 @@ + + + + + + 8008 + + + + + + + + + + + + + 若没有特别查询条件,则值为“ 1 = 1 ” + + + + + + + + 8009 + + + + + + + + + + + + + + + + + + + + 0:起始包 + 1:中间包 + 2:结束包 + (可能hi因为字节对此,后三字节为垃圾值) + + + + 主机字节序 + + + + 主机字节序 + + + + 0:固定长度包 + 1:变长包,用@分隔 + 目前默认为0, + + + + 目前固定128,若不够用,可用考虑改为256 + + + + 证书DN + + + + + + + + + diff --git a/DProto/8009.xml b/DProto/8009.xml new file mode 100644 index 0000000..cce0845 --- /dev/null +++ b/DProto/8009.xml @@ -0,0 +1,96 @@ + + + + + + 8009 + + + + + + + + + + + 机构号长度 + + + + 机构号,可选 + + + + + + + + 800A + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/sunyard/RetWrap.java b/src/main/java/com/sunyard/RetWrap.java index 17cbb2a..f94fb75 100644 --- a/src/main/java/com/sunyard/RetWrap.java +++ b/src/main/java/com/sunyard/RetWrap.java @@ -8,4 +8,202 @@ import java.util.HashMap; */ public class RetWrap extends HashMap{ + public static String transMsg(int retCode){ + String msg; + switch (retCode){ + case -1: + case -2: + case -3: + msg = "网络错误"; + break; + case -4: + msg = "返回包的序列号有误"; + break; + case -5: + msg = "返回包的命令码有误"; + break; + case -6: + msg = "输出缓冲区预留太小"; + break; + case -25: + msg = "输入的 HASH 值长度应该为 32 个字节"; + break; + case -26: + msg = "用户标识超长(应该<=16) "; + break; + case -27: + msg = "数据类型不合法 "; + break; + case 33: + msg = "检索的数据或密钥不存在 "; + break; + case 4: + msg = "DER 编码格式错误(公钥) "; + break; + case 21: + msg = "输入的数据格式错误 "; + break; + case 19: + msg = "数据解密错(C3) "; + break; + case 2: + msg = "签名验证错误 "; + break; + case 32770: + msg = "签名验证错误(P7) "; + break; + case 36868: + msg = "DN 所指向的实体不存在 "; + break; + case 32884: + msg = "证书或签名数据的格式错 "; + break; + case 36865: + msg = "不支持的命令"; + break; + case 36866: + msg = "数据库操作错误"; + break; + case 36867: + msg = "数据记录已经存在"; + break; + case 36869: + msg = "加密卡错误"; + break; + case 36870: + msg = "系统错误(加密数据)"; + break; + case 36871: + msg = "CRL文件中包含的废除证书太多(系统限制200个)"; + break; + case 36872: + msg = "用户证书不在此废除的证书之列"; + break; + case 36874: + msg = "IC卡错误"; + break; + case 36875: + msg = "IC卡口令验证错误,请重新连接"; + break; + case 36876: + msg = "IC卡编号错误,请重新连接"; + break; + case 36877: + msg = "IC卡角色错误,请重新连接"; + break; + case 36878: + msg = "IC卡初始化错误,请重新插入"; + break; + case 36879: + msg = "IC卡已初始化"; + break; + case 36880: + msg = "不是空白卡"; + break; + case 36881: + msg = "IC卡未初始化"; + break; + case 32769: + msg = "签名出错,请核对索引号"; + break; + case 32772: + msg = "证书过期"; + break; + case 32773: + msg = "该证书发行者不可信"; + break; + case 32774: + msg = "证书格式错"; + break; + case 32775: + msg = "机构ID不合法"; + break; + case 32776: + msg = "此证书属于根证书,不在用户证书管理范围"; + break; + case 32777: + msg = "产生证书请求出错"; + break; + case 32784: + msg = "该证书已被废弃"; + break; + case 28673: + msg = "随机数的时效已过"; + break; + case 28674: + msg = "登录超时"; + break; + case 28675: + msg = "登录口令错"; + break; + case 28677: + msg = "操作功能非法使用"; + break; + case 28678: + msg = "系统已签退,请重新登录"; + break; + case 28679: + msg = "操作权限限制"; + break; + case 28680: + msg = "随机数据长度超过系统的要求"; + break; + case 28681: + msg = "此操作员不存在"; + break; + case 28688: + msg = "此操作员已经存在"; + break; + case 28689: + msg = "该IP是本地IP,不能进行分发"; + break; + case 24581: + msg = "文件在设备后端读写失败"; + break; + case 24582: + msg = "ERROR_HANDLE_NULL"; + break; + case 24585: + msg = "升级文件格式有误,请核对后再操作"; + break; + case 24592: + msg = "命令执行过程中出现系统错误"; + break; + case 24593: + msg = "本功能升级已经结束,不用重复操作"; + break; + case 24594: + msg = "数据不合法或格式不正确"; + break; + case 24595: + msg = "中心标识未设,请先设置中心标识"; + break; + case 24596: + msg = "加密密钥不存在"; + break; + case 24597: + msg = "密钥应用超过10个(密钥必须索引0-9)"; + break; + case 24598: + msg = "行标识没有设置"; + break; + case 24577: + msg = "查询类型错误"; + break; + case 24578: + msg = "查询格式错误"; + break; + case 24579: + msg = "数据不合法"; + break; + case 24580: + msg = "系统的口令错误"; + break; + default: + msg = "未定义的错误"; + } + + return msg; + } + } diff --git a/src/main/java/com/sunyard/SydApi.java b/src/main/java/com/sunyard/SydApi.java index 8070a70..8311bb3 100644 --- a/src/main/java/com/sunyard/SydApi.java +++ b/src/main/java/com/sunyard/SydApi.java @@ -20,6 +20,14 @@ public interface SydApi extends SydRawApi, SydCertApi, SydCryptionApi, SydGenApi int NALG_SM4 = 0x01; int NALG_AES = 0x02; + //清算总行密押MAC填充模式 + byte MIYA_FULL_WEAK = 0x30; + byte MIYA_FULL_FORCE = 0x31; + //清算总行密押MAC长度标识 + byte MIYA_MAC_LEN_4 = 0x31; + byte MIYA_MAC_LEN_8 = 0x32; + byte MIYA_MAC_LEN_16 = 0x33; + String RET_CIPHER_KEY = "CipherKey"; String RET_SESSION_KEY = "SessionKey"; String RET_PUBLIC_KEY = "PublicKey"; diff --git a/src/main/java/com/sunyard/inf/SydCertApi.java b/src/main/java/com/sunyard/inf/SydCertApi.java index 0816dbb..34a53f5 100644 --- a/src/main/java/com/sunyard/inf/SydCertApi.java +++ b/src/main/java/com/sunyard/inf/SydCertApi.java @@ -1,8 +1,11 @@ package com.sunyard.inf; +import com.sunyard.RetWrap; import com.sunyard.cert.X509; +import java.io.UnsupportedEncodingException; + /** * 证书操作相关接口 */ @@ -29,6 +32,11 @@ public interface SydCertApi { byte[] dn ); + String RSAGetPublicKeyC( + String userId, + int nKeyTypes + ); + /** * 通过使用者 ID 获得使用者的 SM2 公钥(DER 编码)。 * @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。 @@ -79,4 +87,19 @@ public interface SydCertApi { String sign ); + /** + * 查询所有证书 + * @param dataFlag 数据包标志 0:起始包 1:中间包 2:结束包 + * @return + */ + RetWrap getAllCert(int dataFlag) throws UnsupportedEncodingException; + + /** + * 上传指定证书到加密设备 + * @param certData 证书的字节数组 + * @param organizationId 机构号的字节数组 + * @return + */ + RetWrap importCert(byte[] certData, byte[] organizationId); + } diff --git a/src/main/java/com/sunyard/inf/SydCryptionApi.java b/src/main/java/com/sunyard/inf/SydCryptionApi.java index 586e152..409e86f 100644 --- a/src/main/java/com/sunyard/inf/SydCryptionApi.java +++ b/src/main/java/com/sunyard/inf/SydCryptionApi.java @@ -1,5 +1,6 @@ package com.sunyard.inf; +import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; import com.sunyard.RetWrap; /** @@ -94,6 +95,77 @@ interface SydASYMApi { String userId, String pEnData ); + + /** + * 使用外部私钥解密 + * @param sk + * @param enData + * @return + */ + byte[] SM2Decrypt(byte[] sk, String enData); + + /** + * 用指定的 RSA 私钥对指定的密文数据进行加密。 + * + * @param publicKey 私钥串,DER 编码,HEX 格式。 + * @param pOrgData 加密的数据。 + * @return 加密的数据 base64 编码。 + */ + String RSAEncrypt( + String publicKey, + byte[] pOrgData + ); + + /** + * 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。 + * + * @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。 + * @param pEnData 加密的数据,base64 编码。 + * @return 明文数据。 + */ + byte[] RSADecryptC( + String userId, + String pEnData + ) throws Base64DecodingException; + + + /** + * 使用外部私钥解密 + * @param sk + * @param enData + * @return + */ + public byte[] RSADecrypt(String sk, String enData) throws Base64DecodingException; + + + /** + * 非对称公钥加密 + * @param alg + * @param pk + * @param data + * @return + */ + public byte[] encryptByPk(int alg, String pk, byte[] data); + + + /** + * 非对称私钥解密 + * @param alg + * @param sk 私钥值 + * @param data + * @return + */ + public byte[] decryptBySk(int alg, String sk, byte[] data); + + + /** + * 非对称私钥解密 + * @param alg + * @param user + * @param data + * @return + */ + public byte[] decryptBySkC(int alg, String user, byte[] data); } diff --git a/src/main/java/com/sunyard/inf/SydPledge.java b/src/main/java/com/sunyard/inf/SydPledge.java index d6e70ef..44b637a 100644 --- a/src/main/java/com/sunyard/inf/SydPledge.java +++ b/src/main/java/com/sunyard/inf/SydPledge.java @@ -10,7 +10,19 @@ public interface SydPledge { * @param Data 原始数据 * @return MAC 长度为 8 的 HEX字符串 */ - public String GenerateMIYA(String AreaCode, int Version, int Alg, byte[] Data); + String GenerateMIYA(String AreaCode, int Version, int Alg, byte[] Data); + + /** + * + * @param AreaCode 地区代码 6 位 + * @param Version 版本号 + * @param Alg SydApi.NALG_3DES/SydApi.NALG_SM4 + * @param Data 原始数据 + * @param fullFlag 填充类型 + * @param macLenFlag MAC 长度标识 + * @return + */ + String GenerateMIYA(String AreaCode, int Version, int Alg, byte[] Data, byte fullFlag, byte macLenFlag); /** * @@ -21,6 +33,19 @@ public interface SydPledge { * @param Data 原始数据 * @return true=核押通过 false=核押不通过 */ - public boolean VerifyMIYA(String AreaCode, int Version, int Alg, String MAC, byte[] Data); + boolean VerifyMIYA(String AreaCode, int Version, int Alg, String MAC, byte[] Data); + + /** + * + * @param AreaCode 地区代码 6 位 + * @param Version 版本号 + * @param Alg SydApi.NALG_3DES/SydApi.NALG_SM4 + * @param mac 长度为 8 的 HEX字符串 + * @param Data 原始数据 + * @param fullFlag 填充类型 + * @param macLenFlag MAC 长度标识 + * @return + */ + boolean VerifyMIYA(String AreaCode, int Version, int Alg, String mac, byte[] Data, byte fullFlag, byte macLenFlag); } diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index 760a6b4..1817c17 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -535,6 +535,7 @@ public class SydApi4j implements SydApi { } + @Override public RetWrap genComposeKey(String keyType, char keySolution, String keyClearPattern) { ProtoAA proto = new ProtoAA(); @@ -825,6 +826,127 @@ public class SydApi4j implements SydApi { return GetX509CertInfo(new String(pCertInfo)); } + @Override + public RetWrap getAllCert(int dataFlag) throws UnsupportedEncodingException { + Proto8008 proto = new Proto8008(); + + // 填充数据 + HashMap packet = new HashMap(); + + HashMap data = new HashMap(); + packet.put("data", data); + + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("dataFlag$option", dataFlag); + + String sqlite3 = "1 = 1 "; + data.put("sqlite3", sqlite3); + + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + Packet p = proto.parse(bb, packet); + 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"); + byte[] be = error.getBytes(); + if ( ( 0 != (be[0] ^ be[1]))) { + + throw new SydApiException(error.getInfo(), error.autoInt()); + } + + RetWrap r = new RetWrap(); + + PacketSection resDataFlag = (PacketSection) ret.get("dataFlag"); + r.put("dataFlag", (int) resDataFlag.getBytes()[0]); + PacketSection certAllNum = (PacketSection) ret.get("certAllNum"); + r.put("certAllNum", (int) certAllNum.getBytes()[0]); + PacketSection realCertNum = (PacketSection) ret.get("realCertNum"); + r.put("realCertNum", (int) realCertNum.getBytes()[0]); + PacketSection dataAttrFlag = (PacketSection) ret.get("dataAttrFlag"); + r.put("dataAttrFlag", (int) dataAttrFlag.getBytes()[0]); + r.put("certLenMax", Integer.parseInt(Util.bytes2HexString(Util.toArray(bb)).substring(60, 62), 16)); + + List certs = new ArrayList(); + while( bb.limit() - bb.position() >= 128 ) { + byte[] cert = new byte[ 128 ]; + bb.get( cert ); + certs.add( new String(cert, "GBK") ); + } + + r.put("certDNs", certs.toArray(new String[0])); + + return r; + } + + @Override + public RetWrap importCert(byte[] certData, byte[] organizationId) { + + Proto8009 proto = new Proto8009(); + + // 填充数据 + HashMap packet = new HashMap(); + + HashMap data = new HashMap(); + packet.put("data", data); + + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("certData", certData ); + + if(null != organizationId && organizationId.length > 0){ + data.put("organizationId", organizationId ); + } + +// int length = certData.length; +// System.out.println("dataLength: " + length); + + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + +// String s = Util.bytes2HexString(Util.toArray(bb)); +// System.out.println(s); + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + Packet p = proto.parse(bb, packet); + 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"); + byte[] be = error.getBytes(); + +// String s1 = Util.bytes2HexString(be); +// System.out.println(s1); + RetWrap r = new RetWrap(); + r.put("retCode", true); + + if ( ( 0 != (be[0] ^ be[1]))) { + + r.put("retCode", false); + r.put("msg", error.getInfo() == null || "".equals(error.getInfo()) ? RetWrap.transMsg(error.autoInt()) : error.getInfo()); + } + return r; + } public SydApi4j() { // if (null == pset) { @@ -1146,7 +1268,7 @@ public class SydApi4j implements SydApi { } - private byte[] repackEncrypt(HashMap packet) { + private byte[] repackEncrypt(HashMap packet) { HashMap data = (HashMap) packet.get("data"); int v = ((byte[]) data.get("msg")).length; @@ -1155,7 +1277,7 @@ public class SydApi4j implements SydApi { repack("E0", 2048, packet, new PackCallBack() { @Override - public void circle(int packSn, HashMap packet, Map ret) { + public void circle(int packSn, HashMap packet, Map ret) { bbs.put(((PacketSection) ret.get("msg")).getBytes()); } @@ -1164,20 +1286,20 @@ public class SydApi4j implements SydApi { return Util.toArray(bbs); } - private RetWrap repackEncrypt(HashMap packet,Boolean isDe) { + private RetWrap repackEncrypt(HashMap packet, Boolean isDe) { HashMap data = (HashMap) packet.get("data"); int v = ((byte[]) data.get("msg")).length; final ByteBuffer bbs = ByteBuffer.allocate(v + 1024); - int packSize=2048; - int packSizeDe=packSize+16; + int packSize = 2048; + int packSizeDe = packSize + 16; // int fm = (int) data.get("fullMode$option"); int fm = (Integer) data.get("fullMode$option"); - if (isDe && 1 == fm && v<=packSizeDe && v>packSize) { + if (isDe && 1 == fm && v <= packSizeDe && v > packSize) { //说明传入数据正好是2048,pkcs模式下机密来的,解密时需当做唯一包处理 - packSize=packSizeDe; + packSize = packSizeDe; } RetWrap retWrap = repack("E0", packSize, packet, new PackCallBack() { @Override @@ -1230,9 +1352,9 @@ public class SydApi4j implements SydApi { //>2k,即进行分块,首尾包进行解密-> 报错 //如果是PKCS模式,packSize应为2064,才能当做唯一包进行解密 - int fm= (Integer) data.get("fullMode$option"); - int loop=0; - int tailLen=0; + int fm = (Integer) data.get("fullMode$option"); + int loop = 0; + int tailLen = 0; //解密时,PKCS,2048 data = new HashMap(); // 确认算法 - if ( isEn ){ + if (isEn) { switch (nAlg) { case 0: data.put("alg$option", 0x0); @@ -1684,20 +1804,19 @@ public class SydApi4j implements SydApi { data.put("msg", pInData); packet.put("data", data); - // Map map=new HashMap<>(); + // Map map=new HashMap<>(); - // Map map = repackEncrypt(packet); + // Map map = repackEncrypt(packet); - // Map map = repackEncrypt(packet,!isEn); + // Map map = repackEncrypt(packet,!isEn); RetWrap retWrap = repackEncrypt(packet, !isEn); - // System.out.println(retWrap); + // System.out.println(retWrap); return retWrap; } - @Override public byte[] SYMEncryptData(int nAlg, String seesionKey, int fullMode, byte[] pInData) { @@ -1737,6 +1856,7 @@ public class SydApi4j implements SydApi { } + @Override public byte[] SYMEncryptData_nofill(int nAlg, String seesionKey, byte[] pInData) { if (2 == nAlg && 'L' != seesionKey.charAt(0)) { @@ -2206,7 +2326,7 @@ public class SydApi4j implements SydApi { @Override public RetWrap SM2OrRSAGenKeyPair(int keyType, String index, int length) { - System.out.println( getClass().getClassLoader().hashCode() ); + System.out.println(getClass().getClassLoader().hashCode()); ProtoE2 proto = new ProtoE2(); HashMap packet = new HashMap(); @@ -2256,7 +2376,8 @@ public class SydApi4j implements SydApi { } - public boolean RSAVerify(int HashMark, int nOrgDataType, byte[] publickey, byte[] orgData, byte[] base64Sign) { + @Override + public boolean RSAVerify(int HashMark, int nOrgDataType, byte[] publicKey, byte[] orgData, byte[] base64Sign) { Proto7C proto = new Proto7C(); byte[] sign = base64Sign; @@ -2269,7 +2390,7 @@ public class SydApi4j implements SydApi { data.put("hashMark$option", HashMark); data.put("signature", sign); data.put("hashData", orgData); - data.put("publicKey", publickey); + data.put("publicKey", publicKey); ByteBuffer bb = proto.rend(packet); @@ -2294,6 +2415,7 @@ public class SydApi4j implements SydApi { } } + @Override public byte[] RSASignC(String privateKeyIndex, int HashMark, int nOrgDataType, byte[] orgData) { Proto7B proto = new Proto7B(); HashMap packet = new HashMap(); @@ -2308,7 +2430,6 @@ public class SydApi4j implements SydApi { data.put("privateKeyTag", SYMUtil.genPrivateKeyMark(privateKeyIndex, "000", "00000001")); - ByteBuffer bb = proto.rend(packet); synchronized (this) { @@ -2370,7 +2491,7 @@ public class SydApi4j implements SydApi { RetWrap rw = new RetWrap(); byte[] lmks = ((PacketSection) ret.get("lmk")).getBytes(); byte[] lmkHeads = ((PacketSection) ret.get("lmkHead")).getBytes(); - byte[] bs= new byte[lmks.length + lmkHeads.length]; + byte[] bs = new byte[lmks.length + lmkHeads.length]; System.arraycopy(lmkHeads, 0, bs, 0, lmkHeads.length); System.arraycopy(lmks, 0, bs, lmkHeads.length, lmks.length); rw.put("lmkKey", bs); @@ -2380,6 +2501,46 @@ public class SydApi4j implements SydApi { } } + @Override + public String RSAGetPublicKeyC(String userId, int nKeyType) { + + //ProtocolRender render = pset.getProtocolReqRender("QQ"); + ProtoQQ proto = new ProtoQQ(); + HashMap packet = new HashMap(); + HashMap data = new HashMap(); + packet.put("data", data); + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("privateKeyTag", SYMUtil.genPrivateKeyMark(userId, 0 == nKeyType ? "000" : "001", "00000001")); + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + //System.out.println(Util.bytes2HexString(Util.toArray(bb))); + 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()); + } + int len = Integer.parseInt(((PacketSection) ret.get("publicLen")).getString()); + if (len == 128) { + return "03420004" + ((PacketSection) ret.get("publicKey")).getString(); + } + + System.out.println("len=" + len); + return Util.bytes2HexString(((PacketSection) ret.get("publicKey")).getBytes()); + } + @Override public String SM2GetPublicKeyC(String userId, int nKeyType) { @@ -2688,13 +2849,12 @@ public class SydApi4j implements SydApi { } - public boolean SM2Verify( int nOrgDataType, byte[] publicKey, byte[] orgData, String base64Sign - ){ + ) { String certNo = "1234567812345678"; //ProtocolRender render = pset.getProtocolReqRender("75"); Proto75 proto = new Proto75(); @@ -2732,7 +2892,6 @@ public class SydApi4j implements SydApi { } - @Override public String SM2Sign( int nOrgDataType, @@ -2781,8 +2940,6 @@ public class SydApi4j implements SydApi { } - - @Override public boolean SM2VerifyCustomized(String certNo, byte[] orgData, String base64Sign) { @@ -2950,6 +3107,7 @@ public class SydApi4j implements SydApi { * @param pk HEX 格式的公钥 * @return */ + @Override public byte[] encryptByPk(int alg, String pk, byte[] data) { byte[] algBin = 0 == alg ? DTO77.Req.Data.AlgorithmKeyOptions.OPVRSA.getBin() : DTO77.Req.Data.AlgorithmKeyOptions.OPVSM2.getBin(); @@ -2990,6 +3148,38 @@ public class SydApi4j implements SydApi { return decryptBySk(alg, sk, SYMUtil.base64EnData2DerEnData(data)); } + @Override + public byte[] decryptBySkC(int alg, String userId, byte[] data) { + byte[] algBin = 0 == alg ? DTO78.Req.Data.AlgorithmKeyOptions.OPVRSA.getBin() : DTO78.Req.Data.AlgorithmKeyOptions.OPVSM2.getBin(); + + Proto78 proto = new Proto78(); + DTO78.Req req = new DTO78.Req() + .setHeader( PacketSN.gen().getSn().array() ) + .buildData() + .setAlgorithmKey( algBin ) + .setFillKey( DTO78.Req.Data.FillKeyOptions.OPVPKCS1v15填充方式.getBin() ) + .setPrivateKeyTag( SYMUtil.genPrivateKeyMark(userId, SYMUtil.KT_ENCRYPT, "00000001").getBytes() ) + .setInfoData( data ) + .closeBuilding(); + + ByteBuffer bb = proto.rend( req.toSoup() ); + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + Packet p = proto.parse(bb); + DTO78.Res res = new DTO78.Res(); + res = res.fullFromSoup( proto.parse(bb).resSoup() ); + + if ( "3030".equals(res.getData().getErrorAsHex()) ){ + return res.getData().getDataAsBin(); + } else { + throw SydApiException.fromBin(res.getData().getErrorAsBin(), res.getData().getErrorCn()); + } + } + + @Override public byte[] decryptBySk(int alg, String sk, byte[] data) { byte[] algBin = 0 == alg ? DTO78.Req.Data.AlgorithmKeyOptions.OPVRSA.getBin() : DTO78.Req.Data.AlgorithmKeyOptions.OPVSM2.getBin(); @@ -3023,6 +3213,56 @@ public class SydApi4j implements SydApi { } } + + /** + * 用指定的 RSA 私钥对指定的密文数据进行加密。 + * + * @param publicKey 私钥串,DER 编码,HEX 格式。 + * @param pOrgData 加密的数据。 + * @return 加密的数据 base64 编码。 + */ + @Override + public String RSAEncrypt( + String publicKey, + byte[] pOrgData + ) { + return Util.encodeBase64(encryptByPk(0, publicKey, pOrgData)); + } + + + /** + * 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。 + * + * @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。 + * @param pEnData 加密的数据,base64 编码。 + * @return 明文数据。 + */ + @Override + public byte[] RSADecryptC( + String userId, + String pEnData + ) { + + return decryptBySk(0, userId, Util.decodeBase64(pEnData)); + + } + + + /** + * 使用外部私钥解密 + * + * @param sk HEX 私钥值 + * @param enData base64 值 + * @return + */ + @Override + public byte[] RSADecrypt(String sk, String enData) { + + return decryptBySk(0, sk, Util.decodeBase64(enData)); + + } + + @Override public String SM2Encrypt(byte[] publicKey, byte[] pOrgData) { Proto77 proto = new Proto77(); @@ -3059,6 +3299,48 @@ public class SydApi4j implements SydApi { return SYMUtil.derEnData2Base64EnData(((PacketSection) ret.get("cipherData")).getBytes()); } + + @Override + public byte[] SM2Decrypt(byte[] sk, String enData) { + //ProtocolRender render = pset.getProtocolReqRender("78"); + Proto78 proto = new Proto78(); + + byte[] pOrgData = SYMUtil.base64EnData2DerEnData(enData); + + // 填充数据 + HashMap packet = new HashMap(); + HashMap data = new HashMap(); + packet.put("data", data); + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("AlgorithmKey$option", 1); + data.put("infoData", pOrgData); + data.put("privateKeyTag", "999999999999999999999999999"); + data.put("privateKey", sk); + // 渲染发送 + 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()); + } + + return ((PacketSection) ret.get("data")).getBytes(); + } + + @Override public byte[] SM2DecryptC(String userId, String enData) { //ProtocolRender render = pset.getProtocolReqRender("78"); @@ -3380,8 +3662,8 @@ public class SydApi4j implements SydApi { } RetWrap rw = new RetWrap(); - System.out.println("lmkHead" + ((PacketSection) ret.get("lmkHead")).getString() + - "\nlmk" + ((PacketSection) ret.get("lmk")).getString()); +// System.out.println("lmkHead" + ((PacketSection) ret.get("lmkHead")).getString() + +// "\nlmk" + ((PacketSection) ret.get("lmk")).getString()); rw.put(SydApi.RET_SESSION_KEY, ((PacketSection) ret.get("lmkHead")).getString() + @@ -4247,6 +4529,12 @@ public class SydApi4j implements SydApi { @Override public String GenerateMIYA(String AreaCode, int Version, int Alg, byte[] Data) { + return GenerateMIYA(AreaCode, Version, Alg, Data, MIYA_FULL_WEAK, MIYA_MAC_LEN_4); + } + + + @Override + public String GenerateMIYA(String AreaCode, int Version, int Alg, byte[] Data, byte fullFlag, byte macLenFlag) { if (Version < 0 || Version > 999) { throw new SydApiException("Version 范围不对", 21); } @@ -4287,6 +4575,8 @@ public class SydApi4j implements SydApi { data.put("MACData", Util.bytes2HexString(Data).getBytes()); data.put("key", key); + data.put("full", fullFlag); + data.put("macLen", macLenFlag); // 渲染发送 ByteBuffer bb = proto.rend(packet); @@ -4317,6 +4607,11 @@ public class SydApi4j implements SydApi { @Override public boolean VerifyMIYA(String AreaCode, int Version, int Alg, String mac, byte[] Data) { + return VerifyMIYA(AreaCode, Version, Alg, mac, Data, MIYA_FULL_WEAK, MIYA_MAC_LEN_4); + } + + @Override + public boolean VerifyMIYA(String AreaCode, int Version, int Alg, String mac, byte[] Data, byte fullFlag, byte macLenFlag) { if (Version < 0 || Version > 999) { throw new SydApiException("Version 范围不对", 21); @@ -4359,6 +4654,8 @@ public class SydApi4j implements SydApi { data.put("MAC", mac); data.put("MACData", Util.bytes2HexString(Data).getBytes()); data.put("key", key); + data.put("full", fullFlag); + data.put("macLen", macLenFlag); // 渲染发送 ByteBuffer bb = proto.rend(packet); @@ -4735,7 +5032,7 @@ public class SydApi4j implements SydApi { bb = syncRead(syncSend(bb)); } - Packet p = proto.parse(bb,packet); + Packet p = proto.parse(bb, packet); Map ret = p.toMap(); if ( @@ -5578,7 +5875,7 @@ public class SydApi4j implements SydApi { RetWrap rw = new RetWrap(); byte[] keys = ((PacketSection) ret.get("key")).getBytes(); byte[] keyHeads = ((PacketSection) ret.get("keyHead")).getBytes(); - byte[] bs= new byte[keys.length + keyHeads.length]; + byte[] bs = new byte[keys.length + keyHeads.length]; System.arraycopy(keyHeads, 0, bs, 0, keyHeads.length); System.arraycopy(keys, 0, bs, keyHeads.length, keys.length); rw.put("key", bs); @@ -5645,7 +5942,19 @@ public class SydApi4j implements SydApi { return true; } - //9.2 数据转加密指令(Y0)(=) -> pass (注:密文数据那项不一定需要传加密出来的数据) + /** + * 数据转加密指令(Y0)(=) -> pass (注:密文数据那项不一定需要传加密出来的数据) + * @param srcType 源密钥类型 + * @param sca 源算法SCA + * @param desKeyType 目的秘钥类型 + * @param dca 目的算法SCA + * @param roundModel 加密模式 + * @param sDEK 源秘钥DEK + * @param dDEK 目的秘钥DEK + * @param infoData 密文数据 + * @param vector 向量 + * @return byte[] 目的密钥加密的密文数据 + */ public byte[] switchEncryY(String srcType, int sca, String desKeyType, int dca, int roundModel, String sDEK, String dDEK, byte[] infoData, String vector) { ProtoY0 proto = new ProtoY0(); HashMap packet = new HashMap(); @@ -7047,7 +7356,7 @@ public class SydApi4j implements SydApi { } //1.1生成一个对称密钥(*) -> pass (对比之前添加了可产生ZMK加密下的密钥) - public RetWrap genSymKey(int mode,String keyType, char solution,String zmk) { + public RetWrap genSymKey(int mode, String keyType, char solution, String zmk) { ProtoA0 proto = new ProtoA0(); HashMap packet = new HashMap(); HashMap data = new HashMap(); @@ -7055,7 +7364,7 @@ public class SydApi4j implements SydApi { packet.put("data", data); PacketSN sn = PacketSN.gen(); packet.put("header", sn.getSn().array()); - data.put("mode$option",mode); + data.put("mode$option", mode); data.put("keyType", keyType); data.put("solution", solution); data.put("zmk", zmk); @@ -7086,7 +7395,7 @@ public class SydApi4j implements SydApi { System.arraycopy(lmkHeads, 0, bs1, 0, lmkHeads.length); System.arraycopy(lmks, 0, bs1, lmkHeads.length, lmks.length); rw.put("lmkKey", bs1); - if(1== mode) { + if (1 == mode) { byte[] zmks = ((PacketSection) ret.get("zmk")).getBytes(); byte[] zmkHeads = ((PacketSection) ret.get("zmkHead")).getBytes(); byte[] bs2 = new byte[zmks.length + zmkHeads.length]; @@ -7110,7 +7419,7 @@ public class SydApi4j implements SydApi { packet.put("data", data); PacketSN sn = PacketSN.gen(); packet.put("header", sn.getSn().array()); - data.put("roleInfo",roleInfo.getBytes()); + data.put("roleInfo", roleInfo.getBytes()); ByteBuffer bb = proto.rend(packet); @@ -7189,7 +7498,7 @@ public class SydApi4j implements SydApi { } //17.11 获取应用密钥明文(+) -> PASS - public RetWrap getPlainText(String key, int checkAlg){ + public RetWrap getPlainText(String key, int checkAlg) { ProtoAB proto = new ProtoAB(); // 填充数据 @@ -7213,7 +7522,7 @@ public class SydApi4j implements SydApi { bb = syncRead(syncSend(bb)); } //ProtocolParser parser = pset.getProtocolResParse(); - Packet p = proto.parse(bb,packet); + Packet p = proto.parse(bb, packet); Map ret = p.toMap(); if ( !Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes()) @@ -7235,7 +7544,7 @@ public class SydApi4j implements SydApi { } @Override - public byte[] directBytes(byte[] data){ + public byte[] directBytes(byte[] data) { //初始化一个和byte长度一样的bb ByteBuffer bb = ByteBuffer.allocate(data.length); // 数组放到bb中 @@ -7248,13 +7557,15 @@ public class SydApi4j implements SydApi { //重置 limit 和postion 值 bb.flip(); //获取bb中有效大小 - int len=bb.limit() - bb.position(); + int len = bb.limit() - bb.position(); - byte [] bytes=new byte[len]; + byte[] bytes = new byte[len]; for (int i = 0; i < bytes.length; i++) { - bytes[i]=bb.get(); + bytes[i] = bb.get(); } return bytes; - }; + } + + ; }