init files

This commit is contained in:
Cheney
2021-06-29 11:32:24 +08:00
commit bbf0cb2fb9
337 changed files with 167274 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
package com.sunyard;
import com.sunyard.proto.Util;
import racal.sunyard.main.SydApi4j;
import java.security.Key;
public class DaToSHCA {
private SydApi key;
private da_handle daHandle;
public boolean DA_OpenHsmServer(da_handle daHandle, String IP,int Port){
try {
SydApi key = new SydApi4j().connect(IP,Port,null,10000);
this.key= key;
}catch (SydApiException e){
e.printStackTrace();
return false;
}
return true;
}
public boolean DA_CloseHsmServer (da_handle daHandle){
int disconnect = key.disconnect();
if (disconnect == 0){
return true;
}
return false;
}
public Key DA_GetSM2PublicKey(da_handle daHandle, int keyNum){
// final String s = key.SM2GetPublicKeyC("" + keyNum, 0);
final String s = key.SM2GetPublicKeyC_QX(keyNum, 0);
return new Key() {
@Override
public String getAlgorithm() {
return null;
}
@Override
public String getFormat() {
return null;
}
@Override
public byte[] getEncoded() {
return Util.hexString2Bytes(s);
}
};
}
public void SM3_Init(da_handle daHandle, byte[] pubKey){
this.daHandle = daHandle;
RetWrap retWrap = key.SM3Hash(1, "1234567812345678", new byte[0], new byte[0], new byte[0]);
byte[] filterData = (byte[])retWrap.get("filterData");
daHandle.setFilterData(filterData);
}
public void SM3_Updata(da_handle daHandle, byte[] InData){
byte[] filterData = daHandle.getFilterData();
RetWrap retWrap = key.SM3Hash(2, "",new byte[0], InData, filterData);
filterData = (byte[])retWrap.get("filterData");
daHandle.setFilterData(filterData);
}
public byte[] SM3_Final(da_handle daHandle){
byte[] filterData = daHandle.getFilterData();
RetWrap retWrap = key.SM3Hash(3, "",new byte[0], new byte[0], filterData);
byte[] hash = (byte[])retWrap.get("hash");
return hash;
}
public byte[] DA_SM2Sgin(da_handle daHandle, int keyNum, byte[] InData){
byte[] s = key.detachedSign(0,InData,keyNum);
return s;
}
public boolean DA_SM2Verify(da_handle daHandle, byte[] InData, String SignData, byte[] sm2Pub){
return key.detachedVerify(0, InData, SignData.getBytes());
}
public static class da_handle{
public da_handle(){
super();
}
private byte[] filterData;
public void setFilterData(byte[] filterData) {
this.filterData = filterData;
}
public byte[] getFilterData() {
return filterData;
}
}
}
+11
View File
@@ -0,0 +1,11 @@
package com.sunyard;
import java.util.HashMap;
/**
* 包装多返回值
*/
public class RetWrap extends HashMap<String, Object>{
}
+87
View File
@@ -0,0 +1,87 @@
package com.sunyard;
import com.sunyard.inf.*;
import com.sunyard.inf.customize.SydHAApi;
import com.sunyard.inf.customize.SydQNUCApi;
import com.sunyard.inf.customize.SydSDNXApi;
import java.io.InputStream;
/**
* Created by Cheney on 2017/11/11.
* 程序调用接口
*/
public interface SydApi extends SydRawApi, SydCertApi, SydCryptionApi, SydGenApi, SydSVApi, SydHAApi, SydQNUCApi, SydPledge, SydPINOpt {
byte ALG_AES = 0x30;
byte ALG_SM4 = 0x31;
int NALG_3DES = 0x00;
int NALG_SM4 = 0x01;
int NALG_AES = 0x02;
String RET_CIPHER_KEY = "CipherKey";
String RET_SESSION_KEY = "SessionKey";
String RET_PUBLIC_KEY = "PublicKey";
String RET_PRIVATE_KEY = "PrivateKey";
String RET_KCV = "KCV";
int FOR_SIGN = 0;
int FOR_ENCRYPT = 1;
int DATA_HASH = 0;
int DATA_ORIGIN = 1;
byte KCV_S = 0x53;
/**
* 建立到指定地址和端口号的加密设备的TCP/IP 连接,返回 TCP/IP 连接句柄。
* 如果采用短连接,交易结束,要调用 disconnect() 进行释放连接。
* @param ip 加密设备的 IP 地址。
* @param port 加密设备的端口号。
* @param pwd 保留。
* @param timeout 超时时间。
* @return 设备操作对象
*/
SydApi connect(String ip, int port, String pwd, int timeout);
/**
* 建立到指定地址和端口号的加密设备的TCP/IP 连接,返回 TCP/IP 连接句柄。
* 如果采用短连接,交易结束,要调用 disconnect() 进行释放连接。
* @param ip 加密设备的 IP 地址。
* @param port 加密设备的端口号。
* @param pwd 保留。
* @param connectTimeout 链接超时时间。
* @param readTimeout 通信超时时间
* @return 设备操作对象
*/
SydApi connect(String ip, int port, String pwd, int connectTimeout, int readTimeout);
/**
* 断开连接
* @return 0 表示成功;非 0 表示失败;
*/
int disconnect();
// 方便链接池扩展
// 单例可以不实现
void free();
// 方便链接池扩展
// 单例可以不实现
void error();
/**
* 获取加密机状态
* @return CPU/MEM/DISK
*/
RetWrap getStatus();
byte[] directBytes(byte[] data);
}
@@ -0,0 +1,116 @@
package com.sunyard;
import com.sunyard.proto.Util;
/**
* Created by Cheney on 2017/8/3.
*/
public class SydApiException extends RuntimeException{
private int retCode;
private String msg;
public int getRetCode() {
return retCode;
}
public void transMsg(){
switch (this.retCode){
case -1:
case -2:
case -3:
this.msg = "网络错误";
break;
case -4:
this.msg = "返回包的序列号有误";
break;
case -5:
this.msg = "返回包的命令码有误";
break;
case -6:
this.msg = "输出缓冲区预留太小";
break;
case -25:
this.msg = "输入的 HASH 值长度应该为 32 个字节";
break;
case -26:
this.msg = "用户标识超长(应该<=16) ";
break;
case -27:
this.msg = "数据类型不合法 ";
break;
case 33:
this.msg = "检索的数据或密钥不存在";
break;
case 4:
this.msg = "DER 编码格式错误(公钥) ";
break;
case 21:
this.msg = "输入的数据格式错误 ";
break;
case 19:
this.msg = "数据解密错(C3) ";
break;
case 2:
this.msg = "签名验证错误 ";
break;
case 32770:
this.msg = "签名验证错误(P7) ";
break;
case 32773:
this.msg = "证书不可信";
break;
case 32884:
this.msg = "证书或签名数据的格式错";
break;
case 36868:
this.msg = "DN 所指向的实体不存在";
break;
case 40000:
this.msg = "输入的大数据处理异常";
default:
this.msg = "未定义的错误";
}
}
public SydApiException(int retCode) {
this.retCode = retCode;
transMsg();
}
public SydApiException(String msg, int ret){
this(ret);
if (null == msg || "".equals(msg)){
transMsg();
}else {
this.msg = msg;
}
}
public static SydApiException fromBin( byte[] b , String msg){
int code = null != b && b[0] >= 48 && b[0] <= 57 ? Util.a2i( b , 10) : Util.b2i( b );
return new SydApiException(msg, code);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(SydApiException.class.getName());
sb.append(" : ");
sb.append("code = ");
sb.append(this.retCode);
sb.append(" ( 0x");
sb.append(Integer.toHexString(this.retCode));
sb.append(" ) ");
sb.append(" msg = ");
sb.append(this.msg);
return sb.toString();
}
}
+26
View File
@@ -0,0 +1,26 @@
package com.sunyard.cert;
import com.sunyard.proto.Util;
public class Cert extends CertInfo {
// 公钥数据
private byte[] pubKey;
public byte[] getPubKey() {
return pubKey;
}
public void setPubKey(byte[] pubKey) {
this.pubKey = pubKey;
}
public void setPubKey(byte[] pubKey, int offsize, int len) {
int l = (0xFF & pubKey[offsize]) * 256 + (0xFF & pubKey[offsize + 1]);
byte[] pk = new byte[ l ];
System.arraycopy(pubKey, offsize + 2, pk , 0, l);
this.pubKey = Util.hexString2Bytes(new String(pk));
}
}
@@ -0,0 +1,14 @@
package com.sunyard.cert;
public class CertInfo extends Info {
private String cert;
public String getCert() {
return cert;
}
public void setCert(String cert) {
this.cert = cert;
}
}
+62
View File
@@ -0,0 +1,62 @@
package com.sunyard.cert;
import com.sunyard.proto.Util;
/**
* Created by Ztt on 2017/8/3.
*/
abstract public class Info {
// 颁发者 DN
private String issuer;
// 证书序列号
private String serialNumber;
// 证书主题
private String subject;
// 证书有效期的起始时间
private String notBefore;
// 证书有效期的终止时间
private String notAfter;
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getNotBefore() {
return notBefore;
}
public void setNotBefore(String notBefore) {
this.notBefore = notBefore;
}
public String getNotAfter() {
return notAfter;
}
public void setNotAfter(String notAfter) {
this.notAfter = notAfter;
}
}
+8
View File
@@ -0,0 +1,8 @@
package com.sunyard.cert;
/**
* Created by Ztt on 2017/8/3.
*/
public class X509 extends Cert {
}
@@ -0,0 +1,82 @@
package com.sunyard.inf;
import com.sunyard.cert.X509;
/**
* 证书操作相关接口
*/
public interface SydCertApi {
/**
* 通过证书的 DN,获取证书的序号。
* @param nCertType 输入 证书类型,0x00:签名证书,0x01:加密证书
* @param certDN 输入。证书 subject 的 DN。
* @return CertSerial 证书有 SN。
*/
String getX509SN(
int nCertType,
byte[] certDN
);
/**
* 通过证书 获得 DER编码的公钥。
* @param dnType 证书类型 0:签名证书, 1:加密证书
* @param dn 传入的证书
* @return 输出的公钥串,DER 编码,HEX 格式。输出的公钥串,DER 编码,HEX 格式。
*/
String GetDNPublicKey(
int dnType,
byte[] dn
);
/**
* 通过使用者 ID 获得使用者的 SM2 公钥(DER 编码)。
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param nKeyTypes 密钥类型,0x00:签名公钥, 0x01:加密公钥。
* @return 输出的公钥串,DER 编码,HEX 格式。输出的公钥串,DER 编码,HEX 格式。
*/
String SM2GetPublicKeyC(
String userId,
int nKeyTypes
);
String SM2GetPublicKeyC_QX(
int userId,
int nKeyTypes
);
/**
* 输入 X509 格式的证书,获取证书信息。
* @param pCert base64 编码的证书
* @return 证书信息类
*/
X509 GetX509CertInfo(
String pCert
);
/**
* 通过使用者 ID 获取的 X509 证书文件。
* @param userId 使用者的 ID,最大长度为 16 位数字(要与生成实体的机构号保持一致)。
* @param nCertType 证书类型,0x00:签名证书, 0x01:加密证书
* @return base64 编码的证书
*/
String GetX509CertFileC(
String userId,
int nCertType
);
/**
* 从签名中获取证书
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 证书信息(包含公钥字段)
*/
public X509 SYD_Get_X509_CertInfo_HA(
byte[] orgData,
String sign
);
}
@@ -0,0 +1,210 @@
package com.sunyard.inf;
/**
* 对称加解密相关接口
*/
public interface SydCryptionApi extends SydSYMApi, SydASYMApi, SydHashApi {
}
/**
* Hash 算法接口
*/
interface SydHashApi {
/**
* 输入对指定的原始数据和公钥,通过 SM3 算法计算数据的散列值。
*
* @param publicKey 公钥(可以为空)
* @param data 原始数据
* @param mac 上一轮 mac 值
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(String publicKey, byte[] data, int i, byte[] mac);
/**
* 输入对指定的原始数据和公钥,通过 SM3 算法计算数据的散列值。
*
* @param publicKey 公钥(可以为空)
* @param data 原始数据
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(String publicKey, byte[] data);
/**
* 输入对指定的原始数据 (无公钥),通过 SM3 算法计算数据的散列值。
*
* @param data 原始数据
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(byte[] data);
public byte[] MACCalc(int alg, int keyType, int fullmode, int maclen, String key, byte[] infoData);
/**
* mac 计算
* @param alg 0=DES 1=3DES 2=SM4 3=AES 4=IDEA 5=SM1 6=3DES-X9.19
* @param keyType 0-TAK 1-ZAK
* @param fullMode 0-弱填充 1 强填充
* @param AK 密钥
* @param infoData <=1024
* @param macLen 1=4Byte 2=8Byte 3=16Byte(仅在SM4/AES 下有效)
* @return mac 值 hex 格式
*/
public String MACCalc(int alg, int keyType, String AK, int fullMode, byte[] infoData, int macLen);
public void MACCheck(int alg, int keyType, String AK, int fullMode, byte[] infoData, String mac);
public String calcPBOCMAC(int mode, int keyType, String key, byte[] data, int block, byte[] iv);
}
/**
* 非对称加解密接口
*/
interface SydASYMApi {
/**
* 用指定的 SM2 公钥对指定的密文数据进行加密。
*
* @param publicKey 公钥钥串,DER 编码,HEX 格式。
* @param pOrgData 加密的数据。
* @return 加密的数据 base64 编码。
*/
String SM2Encrypt(
byte[] publicKey,
byte[] pOrgData
);
/**
* 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。
*
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param pEnData 加密的数据,base64 编码。
* @return 明文数据。
*/
byte[] SM2DecryptC(
String userId,
String pEnData
);
}
/**
* 对称加解密接口
*/
interface SydSYMApi {
public byte[] SYMEnDeData(Boolean isEn, int nAlg, String seesionKey, int roundmod, int fullMode, byte[] pInData, byte[] iv, int block);
/**
* 用输入的会话密钥,对指定报文数据进行加密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey  本地LMK 加密的会话密钥,HEX 格式
* @param pINdata  要加密的报文明文。必须是 8 或16 的倍数。
* @return 输出的报文密文, 长度为报文明文 + 16
*/
byte[] SYMEncryptData(int nAlg, String seesionKey, byte[] pINdata);
byte[] SYMEncryptData(int nAlg, String seesionKey, int fullmode, byte[] pINdata);
byte[] SYMEncryptData_nofill(int nAlg, String seesionKey, byte[] pInData);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param pINdata 要解密的报文密文。长度必须是8 或16 的倍数。
* @return 输出的报文明文。
*/
byte[] SYMDecryptData(int nAlg, String seesionKey, byte[] pINdata);
byte[] SYMDecryptData(int nAlg, String seesionKey, int fullmode, byte[] pINdata);
byte[] SYMDecryptData_nofill(int nAlg, String seesionKey, byte[] pInData);
boolean SYMDecryptDataWithFile(int nAlg, String seesionKey, String inputPath, String outputPath) throws Exception;
/**
* 用输入的会话密钥,对指定报文数据进行加密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey  本地LMK 加密的会话密钥,HEX 格式
* @param pINdata  要加密的报文明文。必须是 8 或16 的倍数。
* @return 输出的报文密文, 长度为报文明文 + 16
*/
byte[] SYMEncryptDataCBC(int nAlg, String seesionKey, byte[] pINdata);
public byte[] SYMEncryptDataCBC(int nAlg, String seesionKey, int fullmode, byte[] pInData);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param pINdata 要解密的报文密文。长度必须是8 或16 的倍数。
* @return 输出的报文明文。
*/
byte[] SYMDecryptDataCBC(int nAlg, String seesionKey, byte[] pINdata);
public byte[] SYMDecryptDataCBC(int nAlg, String seesionKey, int fullmode, byte[] pInData);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。
*
* @param srcKey  源秘钥.十六进制字符串。
* @param desKey  目的秘钥.十六进制字符串。
* @param sca  源算法SCA.Int类型。
* @param sPin  源PIN块.十六进制字符串。
* @param primaryAccount  主账号.十六进制字符串。
* @return 目的Pin块。
*/
byte[] transPinFrOneKeyToAno(String srcKey, String desKey, int sca, String sPin, String primaryAccount);
/**
* 用一把DEK密钥加密数据, 报文总长度不大于8192
*
* @param alg 加密算法
* @param DEK DEK密钥
* @param infoData 数据
* @param vector 初始向量数据 可选项,当加密模式为CBC,CFB或OFB时才显示此项
* @param disperseAlg 分散算法
* @return 密文数据
*/
byte[] SYD_Encrypt_Data(int alg, String DEK, byte[] infoData, byte[] vector, int disperseAlg, byte[] factor);
/**
* 用DEK密钥解密数据, 报文总长度不大于8192
*
* @param alg 解密算法
* @param DEK DEK密钥
* @param infoData 数据密文
* @param vector 初始向量数据 可选项,当加密模式为CBC,CFB或OFB时才显示此项
* @param disperseAlg 分散算法
* @return 解密后的明文数据
*/
byte[] SYD_Decrypt_Data(int alg, String DEK, byte[] infoData, byte[] vector, int disperseAlg, byte[] factor);
/**
* 对于给定的数据生成一个MAC
*
* @param key LMK对(16-17)下加密的TAK
* @param infoData 生成MAC的数据
* @param IV
* @param disperseNum 指定对根密钥分散的次数(1-3次)
* @param disperseAlg 分散算法
* @return 所计算出的MAC
*/
byte[] SYD_MAC_Data(String key, String infoData, byte[] factor, String IV, int disperseNum, int disperseAlg);
}
@@ -0,0 +1,144 @@
package com.sunyard.inf;
import com.sunyard.RetWrap;
/**
* 密钥生成相关接口
*/
public interface SydGenApi {
/**
* RSA、SM2 非对称密钥产生
*
* @return RetWrap 包含 privateKey 和 publicKey
* privateKey LMK 加密下的私钥
* publicKey 公钥的 DER 编码
*/
RetWrap SM2GenKeyPair();
/**
* RSA、SM2 非对称密钥产生
* @param keyType 算法标识 0:RSA 1:SM2
* @param index 27位数字,以此索引存储生成的密钥
* @param length 长度
* @return RetWrap 包含 privateKey 和 publicKey
* privateKey LMK 加密下的私钥
* publicKey 公钥的 DER 编码
* 再之前的接口上添加了索引参数
*/
RetWrap SM2OrRSAGenKeyPair(int keyType,String index,int length);
/**
* 对称密钥产生
* @param keyType 密钥类型
* @param solution 密钥方案(LMK) 密钥长度/LMK下加密密钥的方案。
* @return RetWrap 包含
* lmkKey LMK LMK加密密钥
* keyCheck 密钥校验值
*
*/
RetWrap genSymmetricKey(String keyType,char solution);
RetWrap genAndPrintSplit(String keyType,char solution);
public RetWrap outputKey(String keyType, char solution, String zmk, String key);
public RetWrap inputKey(String keyType, char solution, String zmk, String key);
/**
* 密钥合成
* @param keyType 密钥类型
* @param keySolution 密钥方案(LMK) 密钥长度/LMK下加密密钥的方案。
* @param keyClearPattern 两个明文分量异或合成
* @return RetWrap 包含
* lmkKey LMK LMK加密密钥
* keyCheck 密钥校验值
*
*/
RetWrap genComposeKey(String keyType,char keySolution,String keyClearPattern);
RetWrap genComposeKey(String[] keys);
/**
* SM2 非对称密钥产生和存储
*
* @return RetWrap 包含 privateKey 和 publicKey
* privateKey LMK 加密下的私钥
* publicKey 公钥的 DER 编码
*/
RetWrap SYD_SM2GenKeyPair();
/**
* 此函数用于会话密钥的产生,用发起端。
* 加密机产生随机会话密钥,输出两类密文:
* 1、 公钥加密的密文,用于密钥的传递。
* 2、 本地 LMK 加密,用于本地应用数据的加解密。
*
* @param publicKey 公钥串,DER 编码,HEX 格式。
* @return CipherKey 公钥加密的会话密钥,DER 编码,HEX 格式, SessionKey 本地LMK 加密的会话密钥,HEX 格式 , KCV 会话密钥的检验值,HEX 格式,长度为 16H
*/
RetWrap SM2GenSessionKey(String publicKey);
/**
* 此函数用于会话密钥的接收,用于接收端。
* 加密机通过使用者 ID 所对应的私钥解密对方公钥加密的密文,输出本地 LMK 加密的会话密钥,用于本地应用数据的加解密。
*
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param cipherKey 公钥加密的会话密钥,DER 编码,HEX 格式
* @return SessionKey : 本地LMK 加密的会话密钥,HEX 格式 ; KCV 会话密钥的检验值,HEX 格式,长度为 16H。
*/
RetWrap SM2ConfirmSessionKeyC(String userId, String cipherKey);
/**
* 此函数用于会话密钥的接收,用于接收端。
* 加密机通过使用者 ID 所对应的私钥解密对方公钥加密的密文,输出本地 LMK 加密的会话密钥,用于本地应用数据的加解密。
*
* @param sk 私钥
* @param cipherKey 公钥加密的会话密钥,DER 编码,HEX 格式
* @return SessionKey : 本地LMK 加密的会话密钥,HEX 格式 ; KCV 会话密钥的检验值,HEX 格式,长度为 16H。
*/
RetWrap SM2ConfirmSessionKey(String sk, String cipherKey);
/**
* 产生对称密钥,通过公钥加密生成网联格式的数字信封。
* @param certSerial 对*方 X509 证书的序列号。
* @param nAlg 算法标识,0:AES,1:SM4
* @return RetWrap 包含 CipherKey SessionKey KCV
* CipherKey 公钥加密的会话密钥 ,BASE64 编码
* SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。
* KCV 会话密钥的检验值,HEX 格式,长度为 32H。
*/
RetWrap generateDE(
String certSerial,
byte nAlg
);
/**
* 接收用私钥解密数字信封,还原对称密钥。
*
* @param pCertSerial 输入。 对方 X509 证书的序列号。
* @param pCipherKey 输入。 公钥加密的会话密钥,BASE64 编码
* @return RetWrap 包含 SessionKey KCV
* SessionKey 输出。 本地LMK 加密的会话密钥,格式为:密钥类型|密钥密文,比如:02|密钥密文
* KCV 会话密钥的检验值,HEX 格式,长度为 36H。
*/
RetWrap decryptDE(
String pCertSerial,
String pCipherKey
);
/**
* 产生要求长度的随即数据串,可用于身份认证
*
* @param nRandomSize 需要输出的随机串的长度
* @return 未抛出异常表示成功, 返回 HEX 格式的密钥
*
*/
String GenerateRandom(
int nRandomSize
);
}
@@ -0,0 +1,65 @@
package com.sunyard.inf;
/**
* 密钥工具类接口
* 不影响数据库中的密钥
*/
public interface SydPINOpt {
String transPINFromZPKToZPK(String zpk1, String zpk2, int sca, int dca, int spt, int dpt, String pin, String account);
String transPINFromTPKToZPK(String tpk, String zpk, int sca, int dca, int spt, int dpt, String pin, String account);
//
// /**
// * 将 PIN 从一个 ZPK 加密转为另一个 ZPK 加密
// * @param zpk1 源 PIN保护密钥
// * @param zpk2 目标 PIN保护密钥
// * @param account1 源账号
// * @param account2 目标账号
// * @param pin 源 PIN 密文
// * @return PIN 密文
// */
// String transPinFromZPKToZPK(String zpk1, String zpk2, String account1, String account2, String pin);
//
//
// /**
// * 将 PIN 从一个 ZPK 加密转为另一个 ZPK 加密
// * @param zpk1 源 PIN保护密钥
// * @param zpk2 目标 PIN保护密钥
// * @param account 账号
// * @param pin 源 PIN 密文
// * @return PIN 密文
// */
// String transPinFromTPKToZPK(String zpk1, String zpk2, String account, String pin);
//
//
// /**
// *
// * ZPK转PVK加密的IBM PIN OFFSET
// *
// * @param zpk 区域 PIN保护密钥
// * @param pvk 验 PIN 专用密钥
// * @param account1 源账号
// * @param account2 目标账号
// * @param pin ZPK 加密的 PIN 密文
// * @return IBM PIN OFFSE
// */
// String calculateIBMPinOffsetFromZPKToPVK(String zpk, String pvk, String account1, String account2, String pin);
//
//
// /**
// * ZPK转PVK加密的IBM PIN OFFSET并校验
// *
// * @param zpk 区域 PIN保护密钥
// * @param pvk 验 PIN 专用密钥
// * @param account1 源账号
// * @param account2 目标账号
// * @param pin ZPK 加密的 PIN 密文
// * @param pinOffset IBM PIN OFFSE
// * @return true 校验通过 / false 校验不通过
// */
// Boolean verifyIBMPinOffsetFromZPKToPVK(String zpk, String pvk, String account1, String account2, String pin, String pinOffset);
}
@@ -0,0 +1,26 @@
package com.sunyard.inf;
public interface SydPledge {
/**
* 编押
* @param AreaCode 地区代码 6 位
* @param Alg SydApi.NALG_3DES/SydApi.NALG_SM4
* @param Version 版本号
* @param Data 原始数据
* @return MAC 长度为 8 的 HEX字符串
*/
public String GenerateMIYA(String AreaCode, int Version, int Alg, byte[] Data);
/**
*
* @param AreaCode 地区代码 6 位
* @param Alg SydApi.NALG_3DES/SydApi.NALG_SM4
* @param Version 版本号
* @param MAC 长度为 8 的 HEX字符串
* @param Data 原始数据
* @return true=核押通过 false=核押不通过
*/
public boolean VerifyMIYA(String AreaCode, int Version, int Alg, String MAC, byte[] Data);
}
@@ -0,0 +1,21 @@
package com.sunyard.inf;
public interface SydRawApi {
/**
* 加密机直接通信
* @param pack 组好的 Hex 格式包
* @return 返回加密机返回 Hex 格式包
*/
public String send(String pack);
/**
* 加密机直接通信
* @param pack 组好的包
* @return 返回加密机返回包
*/
public byte[] send(byte[] pack);
}
+261
View File
@@ -0,0 +1,261 @@
package com.sunyard.inf;
import com.sunyard.RetWrap;
/**
* 签名验签相关接口
*/
public interface SydSVApi extends SydNakedSVApi, SydAttachedSVApi, SydDetachedSVApi{
}
/**
* 不经过 CA 授信
* 直接使用公私钥对签名验签
*/
interface SydNakedSVApi {
/**
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制裸签名(遵循 PKCS#1)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public byte[] SYD_NakedSign(
byte[] orgData,
String sCertDN
);
/**
* 使用指定的证书 DN,对指定的原始数据编制裸验签(遵循PKCS#1)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @param sCertDN 签名者证书 DN
* @return 验签是否通过
*/
public boolean SYD_NakedVerify(
byte[] orgData,
byte[] sign,
String sCertDN
);
}
/**
* 带原文的签名验签
*/
interface SydAttachedSVApi {
/**
* SM2 私钥签名
* @param pUserID 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param certNo 证书号
* @param nOrgDataType 原始数据类型 0 : hash 1 : 原数据
* @param publicKey 公钥的 DER 编码
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
String SM2SignC(
String pUserID,
String certNo,
int nOrgDataType,
byte[] publicKey,
byte[] orgData
);
/**
* RSA 私钥签名
* @param HashMark 哈希标识 指示用于哈希证书数据的哈希算法的标识。0: SHA1 1: SHA256 2: MD5。
* @param privateKeyTag 私钥标记 指示私钥位置的标记。数字为存储私钥的索引,除了全9表示使用由命令中提供的密钥。
* 27位的索引号:16位机构号+3位密钥类型+8位密钥索引号
* @param nOrgDataType 原始数据类型 0 : hash 1 : 原数据
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
byte[] RSASignC(
String privateKeyTag,
int HashMark,
int nOrgDataType,
byte[] orgData);
byte[] RSASign(
String privateKey,
int HashMark,
int nOrgDataType,
byte[] orgData);
/**
* 采用 RSA 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param HashMark 证书号
* @param nOrgDataType 签名方式
* @param publicKey 公钥
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean RSAVerify(
int HashMark,
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
byte[] sign);
/**
* 采用 SM2 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param certNo 哈希标识 指示用于哈希证书数据的哈希算法的标识。0: SHA1 1: SHA256 2: MD5
* @param nOrgDataType 签名方式
* @param publicKey 公钥
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean SM2Verify(
String certNo,
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
String sign
);
/**
* SM2 私钥签名
* @param certNo 证书号
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
String SM2SignCustomized(
String certNo,
byte[] orgData
);
/**
* 采用 SM2 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param certNo 证书号
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean SM2VerifyCustomized(
String certNo,
byte[] orgData,
String sign
);
}
/**
* 不带原文的签名验签
*/
interface SydDetachedSVApi {
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean SYD_DetachedVerify(
byte[] orgData,
String sign);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String SYD_DetachedSign(
byte[] orgData,
String sCertDN
);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 待签名的原始数据将在接口内部进行 sm3 ,然后做 Detach 签名
* @param orgData 待签名的原始数据
* @param publicKey sm3 hash 所用的公钥
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String sm3AndDetachedSign(
byte[] orgData,
String publicKey,
String sCertDN
);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 原始数据将在接口内部进行 sm3 ,然后做 Detach 验签
* @param orgData 待签名的原始数据
* @param publicKey sm3 hash 所用的公钥
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean sm3AndDetachedVerify(
byte[] orgData,
String publicKey,
String sign);
/**
*
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 输入的数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String detachedSign(
int dataType,
byte[] orgData,
String sCertDN
);
//8024
public byte[] detachedSign(
int dataType,
byte[] orgData,
int sCertDN
);
public String detachedSignbysn(
int dataType,
byte[] orgData,
String certificateNo);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
boolean detachedVerify(
int dataType,
byte[] orgData,
String sign);
//8025
boolean detachedVerify(
int dataType,
byte[] orgData,
byte[] sign);
RetWrap SM3Hash(int packSn, String userId, byte[] publicKey, byte[] msg, byte[] filterData);
}
@@ -0,0 +1,117 @@
package com.sunyard.inf.customize;
import com.sunyard.cert.X509;
public interface SydHAApi {
/**
* 通过机构实体ID获得使用者的SM2公钥(DER编码)
* @param pUserID 本机构实体ID,最大长度为16位数字,即设备安装生成实体时的实体机构输入栏的内容
* @param nKeyType 密钥类型,0:签名公钥,1:加密公钥,如无加解密业务,传入0即可
* @return 输出的公钥串,DER编码,HEX格式,此公钥是机构自己公钥证书的公钥
*/
public String SYD_SM2_Get_Id_PublicKey_HA (
String pUserID,
int nKeyType
);
/**
* 通过证书DN获得机构的公钥(DER编码),联调前需要导入公钥证书
* @param Dn 证书的DN,每个证书有唯一的DN
* @param nKeyType 密钥类型,0:签名公钥,1:加密公钥,如无加解密业务,传入0即可
* @return 输出的公钥串,DER编码,HEX格式,此公钥为他方机构的公钥
*/
public String SYD_SM2_Get_Dn_PublicKey_HA (
byte[] Dn,
int nKeyType
);
/**
* 通过本机构实体ID所对应的私钥对指定的原始数据进行数字签名(PKCS#1)
* @param pUserID 本机构实体ID,最大长度为16位数字,即设备安装生成实体时的实体机构输入栏的内容
* @param nOrgDataType 输入的数据类型,0:HASH值,1:原始数据,原始数据由加密设备内部完成HASH并签名
* @param publicKey 公钥串,DER编码,HEX格式。仅 OrgDataType=1有效, 2.1章节接口,输出公钥原串传入
* @param orgData 待签名的原始数据
* @return 签名数据( DER 编码 + Base64 编码)
*/
public String SYD_SM2_Sign_HA(
String pUserID,
int nOrgDataType,
byte[] publicKey,
byte[] orgData
);
/**
* 通过本机构实体ID所对应的私钥对指定的原始数据进行数字签名(PKCS#1)
* @param nOrgDataType 输入的数据类型,0:HASH值,1:原始数据,原始数据由加密设备内部完成HASH并签名
* @param privateKey 私钥串,LMK34-35 下加密的私钥
* @param publicKey 公钥串,DER编码,HEX格式。仅 OrgDataType=1有效, 2.1章节接口,输出公钥原串传入
* @param orgData 待签名的原始数据
* @return 签名数据( DER 编码 + Base64 编码)
*/
public String SYD_SM2_Sign_HA(
int nOrgDataType,
byte[] privateKey,
byte[] publicKey,
byte[] orgData
);
/**
* 用指定的公钥对指定的原始数据进行数字签名验证(PKCS#1)
* @param nOrgDataType 数据类型,SydApi.DATA_ORIGIN 原始数据 SydApi.DATA_HASH : hash 后的类型
* @param publicKey 公钥串,DER编码,HEX格式,2.1章节接口,输出公钥原串传入
* @param orgData 待签名的原始数据
* @param sign 签名数据 (DER 编码 + Base64 编码)
* @return 验签是否通过
*/
public boolean SYD_SM2_Verify_HA(
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
String sign
);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean SYD_SM2_DetachedVerify_HA(
byte[] orgData,
String sign );
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String SYD_SM2_DetachedSign_HA(
byte[] orgData,
String sCertDN
);
// 外部私钥
public String SM2Sign(
int nOrgDataType,
byte[] privateKey,
byte[] orgData
);
// SYD_SM2_Verify_HA
public boolean SM2Verify(
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
String base64Sign
);
}
@@ -0,0 +1,33 @@
package com.sunyard.inf.customize;
/**
* 网联全称 "网联清算有限公司"(China Nets Union Clearing Corporation)
* 是一个线上支付统一清算平台(unified clearing platform for online payment),在央行指导下,由中国支付清算协会(Payment & Clearing Association of China)组织支付机构成立,用以处理由非银行支付机构发起的、与银行交互的支付业务。
*/
public interface SydQNUCApi {
/**
* 用指定的证书私钥对指定的数据进行数字签名。
* @param pCertSerial 输入。签名 X509 证书的序列号。
* @param pOrgData 输入。 待签名的原始数据。
* @return 签名数据(BASE64 编码)。
*/
public String netSign(String pCertSerial, byte[] pOrgData);
/**
* 用指定证书对指定的原始数据进行数字签名验证。
* @param pCertSerial 输入。 签名 X509 证书的序列号。
* @param pOrgData 输入。 待签名的原始数据。
* @param pSignData 输入。 签名数据(BASE64 编码)。
* @return true 表示验证正确;false 表示失败;
*/
boolean netVerify(
String pCertSerial,
byte[] pOrgData,
String pSignData
);
}
@@ -0,0 +1,62 @@
package com.sunyard.inf.customize;
import com.sunyard.cert.X509;
/**
* 山东农信定制开发接口
*/
public interface SydSDNXApi {
/**
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制裸签名(遵循 PKCS#1)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String nakedSign(
byte[] orgData,
String sCertDN
);
/**
* 使用指定的证书机构号,对指定的原始数据编制裸验签(遵循PKCS#1)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @param organizationNum 机构号
* @return 验签结果,true:表示验证正确;验签不通过返回错误码和错误信息
*/
public boolean SYD_NakedVerify(
byte[] orgData,
String sign,
String organizationNum
);
/**
* 验签,通过传入行号字符串,获取证书去验签
* @param bNumber 行号,通过行号获取证书
* @param orgData 带签名的原始数据
* @param signData 签名数据( BASE64 编码)
* @return 验签结果,true:表示验证正确;验签不通过返回错误码和错误信息
*/
/* boolean netVerify(
String bNumber,
byte[] orgData,
String signData
);
*/
/**
*验签 ,上传并返回证书内容,并更新机构号
* @param bNumber 行号,通过行号获取证书
* @param orgData 待签名的原始数据
* @param sign 签名数据( BASE64 编码)
* @return 证书信息(包含公钥字段)
*/
public X509 SYD_Get_X509_CertInfo_HA(
String bNumber,
byte[] orgData,
String sign
);
}
@@ -0,0 +1,185 @@
package com.sunyard.inf.customize;
import com.sunyard.SydApiException;
import com.sunyard.cert.X509;
import com.sunyard.proto.Packet;
import com.sunyard.proto.PacketSection;
import com.sunyard.proto.Util;
import com.sunyard.trans.PacketSN;
import racal.sunyard.main.SydApi4j;
import racal.sunyard.main.proto.Proto8003;
import racal.sunyard.main.proto.Proto8004;
import racal.sunyard.main.proto.Proto8012;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class SydSDNXApiImpl extends SydApi4j implements SydSDNXApi {
public String nakedSign(byte[] orgData, String sCertDN) {
Proto8003 proto = new Proto8003(); //pset.getProtocolReqRender("75");
byte[] dn = new byte[256];
byte[] s = null;
try {
s = sCertDN.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.arraycopy(s, 0, dn, 0, s.length);
// 填充数据
HashMap<String, Object> packet = new HashMap<String, Object>();
HashMap<String, Object> data = new HashMap<String, Object>();
packet.put("data", data);
PacketSN sn = PacketSN.gen();
packet.put("header", sn.getSn().array());
data.put("signatureDataType$option", 1);
data.put("DN", dn);
data.put("data", orgData);
// 渲染发送
ByteBuffer bb = proto.rend(packet);
synchronized (this) {
// 响应解析
bb = syncRead(syncSend(bb));
}
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");
byte[] be = error.getBytes();
if (
(0 != (be[0] ^ be[1]))) {
throw new SydApiException(error.getInfo(), error.autoInt());
}
return Util.encodeBase64(((PacketSection) ret.get("signature")).getBytes());
//return ((PacketSection) ret.get("signature")).getBytes();
}
@Override
public boolean SYD_NakedVerify(byte[] orgData, String sign, String organizationNum) {
Proto8004 proto = new Proto8004(); //pset.getProtocolReqRender("75");
byte[] dn = new byte[256];
byte[] s = null;
// 填充数据
HashMap<String, Object> packet = new HashMap<String, Object>();
HashMap<String, Object> data = new HashMap<String, Object>();
packet.put("data", data);
PacketSN sn = PacketSN.gen();
packet.put("header", sn.getSn().array());
data.put("signatureDataType$option", 2);
data.put("organizationNum", organizationNum);
data.put("data", orgData);
data.put("signature", Util.decodeBase64(sign));
data.put("returnSign$option", 0);
// 渲染发送
ByteBuffer bb = proto.rend(packet);
synchronized (this) {
// 响应解析
bb = syncRead(syncSend(bb));
}
Packet p = proto.parse(bb, packet);
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");
byte[] be = error.getBytes();
if ((0 != (be[0] ^ be[1]))) {
throw new SydApiException(error.getInfo(), error.autoInt());
}
return true;
}
@Override
public X509 SYD_Get_X509_CertInfo_HA(String bNumber, byte[] orgData, String sign) {
Proto8012 proto = new Proto8012(); //pset.getProtocolReqRender("75");
// 填充数据
HashMap<String, Object> packet = new HashMap<String, Object>();
HashMap<String, Object> data = new HashMap<String, Object>();
packet.put("data", data);
PacketSN sn = PacketSN.gen();
packet.put("header", sn.getSn().array());
data.put("originData", orgData);
data.put("signData", sign.getBytes());
data.put("flag$option", 2);
data.put("organizationNum", bNumber);
// 渲染发送
ByteBuffer bb = proto.rend(packet);
synchronized (this) {
// 响应解析
bb = syncRead(syncSend(bb));
}
Packet p = proto.parse(bb, packet);
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");
byte[] be = error.getBytes();
if ((0 != (be[0] ^ be[1]))) {
throw new SydApiException(error.getInfo(), error.autoInt());
}
PacketSection info = (PacketSection) ret.get("info");
byte[] pCertInfo = info.getBytes();
// X509 cinfo = new X509();
// cinfo.setIssuer(Util.toCleanString(pCertInfo, 0, 257));
// cinfo.setSerialNumber(Util.toCleanString(pCertInfo, 257, 65));
// cinfo.setSubject(Util.toCleanString(pCertInfo, 257 + 65, 257));
// cinfo.setNotBefore(Util.toCleanString(pCertInfo, 257 + 65 + 257, 15));
// cinfo.setNotAfter(Util.toCleanString(pCertInfo, 257 + 65 + 257 + 15, 15));
// byte[] blen = new byte[]{pCertInfo[257 + 65 + 257 + 15 + 15], pCertInfo[257 + 65 + 257 + 15 + 16]};
// int len = Util.b2i(blen);
// byte[] pem = new byte[len];
// System.arraycopy(pCertInfo, 257 + 65 + 257 + 15 + 17, pem, 0, len);
// String pp = new String(pem);
// 解析证书
return GetX509CertInfo(new String(pCertInfo));
}
}
@@ -0,0 +1,34 @@
package com.sunyard.trans;
public enum AlgorithmType {
// DES 加密
ENCRYPT_DES,
// DES 解密
DECRYPT_DES,
// AES 加密
ENCRYPT_AES,
// AES 解密
DECRYPT_AES,
// SSF33 加密
ENCRYPT_SSF33,
// SSF33 解密
DECRYPT_SSF33,
// SM1 加密
ENCRYPT_SM1,
// SM1 解密
DECRYPT_SM1,
// SM4 加密
ENCRYPT_SM4,
// SM4 解密
DECRYPT_SM4,
// IDEA 加密
ENCRYPT_IDEA,
// IDEA 解密
DECRYPT_IDEA,
// AES256 加密
ENCRYPT_AES256,
// AES256 解密
DECRYPT_AES256,
}
+19
View File
@@ -0,0 +1,19 @@
package com.sunyard.trans;
import java.nio.ByteBuffer;
public enum CMD {
// 加解密
ENCRYPTION_DECRYPTION("E0");
private String value;
public ByteBuffer getValue() {
return ByteBuffer.wrap(value.getBytes());
}
CMD(String value) {
this.value = value;
}
}
@@ -0,0 +1,11 @@
package com.sunyard.trans;
public enum DataType {
// 二进制
BIN,
// 十六进制编码的二进制
HEX,
// 文本格式
TXT
}
@@ -0,0 +1,22 @@
package com.sunyard.trans;
public enum FullEndType {
/**
* 填充数据的最后一个字节不填充计数位。解
密后的数据包含填充数据,由应用摘取实际数据。
*/
WITH_END,
/**
* 填充数据的最后一个字节填充计数位。计数
位取值在 0x01 to 0x08/ 0x10 之间。解密后
的数据由加密机根据 Pad count flag 值在内部自
动去掉填充数据
*/
AUTO_END,
/**
* pkcs5和 pkcs7 填充
*/
PKCS5_PKCS7
}
@@ -0,0 +1,23 @@
package com.sunyard.trans;
/**
*/
public enum FullMode {
/**
* 如果数据块长度为 8/16 的整数倍,不需要填
充;如果长度不为 8/16 的整数倍,填充至长度满
8/16 的整数倍(填充方式按 Pad character 域中
描述的规则进行,由加密机内部自动完成)
*/
FULL_8_16,
/**
* 如果数据块长度为 8/16 的整数倍,填充一个
整 8/16 字节的数据(填充方式按 Pad character
域中描述的规则进行,由加密机内部自动完成);
如果长度不为8/16的整数倍,填充至长度满8/16
的整数倍(填充方式按 Pad character 域中描述
的规则进行,由加密机内部自动完成)
*/
FULL_MORE_8_16
}
@@ -0,0 +1,10 @@
package com.sunyard.trans;
public enum KeyType {
// LMK 加密的 ZEK (区域加密密钥)
ZEK,
// LMK 加密的 TEK ()
TEK,
}
@@ -0,0 +1,13 @@
package com.sunyard.trans;
public enum PackType {
// 唯一块
ONLY,
// 起始块
HEAD,
// 中间块
MIDDLE,
// 结束块
TAIL
}
@@ -0,0 +1,80 @@
package com.sunyard.trans;
import com.sunyard.proto.Util;
import java.nio.ByteBuffer;
import java.util.HashMap;
/**
* 生成包序号,不负责销毁。
* 相同设备 sn 轮转
* 不同设备 sn 无关
*/
public class PacketSN {
private static HashMap<String, SN> keeper = new HashMap<String, SN>();
private ByteBuffer sn;
private String devid;
public static PacketSN gen(String devid){
// 申请小锁
SN sn = keeper.get(devid);
if ( null == sn){
// 申请全局锁
synchronized (PacketSN.class){
SN snCheck = keeper.get(devid);
if( null == snCheck){
keeper.put(devid, new SN());
sn = keeper.get(devid);
}else{
sn = snCheck;
}
}
}
return new PacketSN(sn.next(), devid);
}
public static PacketSN gen(){
return gen("default");
}
public PacketSN(ByteBuffer sn, String devid) {
this.sn = sn;
this.devid = devid;
}
public ByteBuffer getSn() {
return sn;
}
public String getDevid() {
return devid;
}
public String getGlobalId(){
return devid + "-" + Util.bytes2HexString(sn.array());
}
}
class SN {
private long sn = 0;
synchronized ByteBuffer next(){
ByteBuffer bb = ByteBuffer.allocate(8);
bb.put((byte) ((sn >>> 56) & 0xFF));
bb.put((byte) ((sn >>> 48) & 0xFF));
bb.put((byte) ((sn >>> 40) & 0xFF));
bb.put((byte) ((sn >>> 32) & 0xFF));
bb.put((byte) ((sn >>> 24) & 0xFF));
bb.put((byte) ((sn >>> 16) & 0xFF));
bb.put((byte) ((sn >>> 8) & 0xFF));
bb.put((byte) (sn & 0xFF));
sn += 1;
return bb;
}
}
@@ -0,0 +1,16 @@
package com.sunyard.trans;
public enum RoundType {
// 占位
DO_NOT_USE,
// 电子密码本
ECB,
// 密码块连接
CBC,
// 分组长度密码反馈
CFB,
// 分组长度输出反馈
OFB
}
@@ -0,0 +1,267 @@
package com.sunyard.trans.pkg;
import com.sunyard.trans.FullMode;
import com.sunyard.SydApiException;
import com.sunyard.proto.Util;
import com.sunyard.trans.*;
import java.nio.ByteBuffer;
public class DataEncryptDecryptPacket extends Packet {
// 包类型
private int packType;
// 算法标记
private int alg;
// 轮类型
private int round;
// 密钥类型
private int keyType;
// 密钥
private byte[] key;
// 输入数据类型
private int inDataType;
// 输出数据类型
private int outDataType;
// 填充模式
private int fullMode;
// 填充字符
private String fullCharacter;
// 填充类型
private int fullEndType;
/**
* 消息类型影响消息长度(若消息类型为二进制,则为
* 随后域长度;若消息类型为扩展十六进制,则为随后
* 域长度的一半)。默认是 BIN
*/
private int messageType;
// 消息数据
private byte[] message;
public DataEncryptDecryptPacket() {
this.setCommand(CMD.ENCRYPTION_DECRYPTION);
}
@Override
protected DataEncryptDecryptPacket clone(){
DataEncryptDecryptPacket subPack = new DataEncryptDecryptPacket();
subPack.setCommand(getCommand());
subPack.setHeader(getHeader());
subPack.setPackType(packType);
subPack.setAlg(alg);
subPack.setRound(round);
subPack.setKeyType(keyType);
subPack.setKey(key);
subPack.setInDataType(inDataType);
subPack.setOutDataType(outDataType);
subPack.setFullMode(fullMode);
subPack.setFullCharacter(fullCharacter);
subPack.setFullEndType(fullEndType);
return subPack;
}
/**
* 初始向量
* 仅当密钥加密轮函数类型为 CBC ,CFB ,OFB 时有此域。
* 当密钥模式为 DES加解密 该域为 16H
* 当密钥模式为 AES SSF33 SM1 加解密时,该域为 32H
*/
private byte[] iv = new byte[0];
public void setKeyType(KeyType keyType) {
this.keyType = keyType.ordinal();
}
public void setRoundType(RoundType roundType) {
this.round = roundType.ordinal();
}
public void setPackType(PackType type) {
this.packType = type.ordinal();
}
public void setAlgType(AlgorithmType type){
this.alg = type.ordinal();
}
public void setKey(byte[] key){
this.key = key;
}
public void setIv(byte[] iv) {
if ( RoundType.CBC.ordinal() == round
|| RoundType.CFB.ordinal() == round
|| RoundType.OFB.ordinal() == round
){
if( AlgorithmType.ENCRYPT_DES.ordinal() == keyType
|| AlgorithmType.DECRYPT_DES.ordinal() == keyType
){
if( 16 != iv.length ){
throw new SydApiException(65535);
}
}else{
if( 32 != iv.length ){
throw new SydApiException(65535);
}
}
this.iv = iv;
}
throw new SydApiException(65535);
}
public void setInDataType(DataType dataType) {
this.inDataType = dataType.ordinal();
}
public void setOutDataType(DataType dataType) {
this.outDataType = dataType.ordinal();
}
public void setFullMode(FullMode mode,FullEndType endType, String firstChar, String otherChar){
this.fullMode = mode.ordinal();
this.fullCharacter = firstChar + otherChar;
this.fullEndType = endType.ordinal();
}
public void setMessage(DataType type , byte[] message) {
this.message = message;
this.messageType = type.ordinal();
}
public void setMessage(byte[] message) {
setMessage(DataType.BIN, message);
}
private ByteBuffer toSubPack(){
ByteBuffer bb = ByteBuffer.allocate(MAX_PACKAGE_DATA_LEN);
bb.put( Util.int2charbyte16(packType) );
bb.put( Util.int2charbyte16(alg) );
bb.put( Util.int2charbyte16(round) );
bb.put( Util.int2charbyte16(keyType));
bb.put( key );
bb.put( Util.int2charbyte16(inDataType) );
bb.put( Util.int2charbyte16(outDataType) );
if ( 0 == packType || 3 == packType ){
bb.put( Util.int2charbyte16(fullMode) );
bb.put( fullCharacter.getBytes() );
bb.put( Util.int2charbyte16(fullEndType));
}
bb.put(iv);
int msgLen = message.length;
if ( DataType.HEX.ordinal() == messageType ){
msgLen = msgLen/2;
}
bb.put(String.format("%03X", msgLen).getBytes());
bb.put(message);
this.setData(bb);
return this.pack();
}
@Override
public ByteBuffer toSendPack(PacketSN sn) {
setHeader(sn.getSn());
// 依据数据长度的不同可能需要分包
int packLen = 2048;
int inDataLen = this.message.length;
// 拆包数量
int loop = inDataLen / packLen;
if ( 0 != inDataLen % packLen ){
loop += 1;
}
ByteBuffer bb = ByteBuffer.allocate( packLen * loop );
int i = 0;
while ( i < loop){
DataEncryptDecryptPacket subPack = this.clone();
if ( 0 == i){
if ( 1 == loop){
subPack.setPackType(PackType.ONLY);
}else{
subPack.setPackType(PackType.HEAD);
}
}else{
if ( (loop - 1) == i){
subPack.setPackType(PackType.TAIL);
}else{
subPack.setPackType(PackType.MIDDLE);
}
}
// 唯一包
if ( 1 == loop){
subPack.setMessage(this.message);
}else{
byte[] tMsg = new byte[packLen];
// 最后一个包
if ( (loop - 1) == i){
System.arraycopy(this.message, i * packLen , tMsg, 0, this.message.length % packLen);
}else{ // 其他包
System.arraycopy(this.message, i * packLen , tMsg, 0, packLen);
}
subPack.setMessage(tMsg);
}
bb.put( subPack.toSubPack() );
i++;
}
return bb;
}
// POJO set
public void setPackType(int packType) {
this.packType = packType;
}
public void setAlg(int alg) {
this.alg = alg;
}
public void setRound(int round) {
this.round = round;
}
public void setKeyType(int keyType) {
this.keyType = keyType;
}
public void setInDataType(int inDataType) {
this.inDataType = inDataType;
}
public void setOutDataType(int outDataType) {
this.outDataType = outDataType;
}
public void setFullMode(int fullMode) {
this.fullMode = fullMode;
}
public void setFullCharacter(String fullCharacter) {
this.fullCharacter = fullCharacter;
}
public void setFullEndType(int fullEndType) {
this.fullEndType = fullEndType;
}
public void setMessageType(int messageType) {
this.messageType = messageType;
}
}
@@ -0,0 +1,70 @@
package com.sunyard.trans.pkg;
import com.sunyard.trans.CMD;
import com.sunyard.trans.PacketSN;
import java.nio.ByteBuffer;
/**
* SJJ1316 加密机通用格式
*/
public abstract class Packet {
public static final int MAX_PACKAGE_DATA_LEN = 8192;
public static final int MAX_PACKAGE_LEN = MAX_PACKAGE_DATA_LEN + 10;
private ByteBuffer header;
private ByteBuffer command;
private ByteBuffer data;
private ByteBuffer length;
public abstract ByteBuffer toSendPack(PacketSN sn);
public ByteBuffer getHeader() {
return header;
}
public ByteBuffer getCommand() {
return command;
}
public void setCommand(CMD cmd) {
this.command = cmd.getValue();
}
public void setCommand(ByteBuffer command) {
this.command = command;
}
public void setHeader(ByteBuffer header){
this.header = header;
}
public void setData(ByteBuffer data){
this.data = data;
int len = data.array().length + 8 + 2;
header.put(0, (byte) (len / 256));
header.put(1, (byte) (len % 256));
}
public ByteBuffer pack(){
ByteBuffer bb = ByteBuffer.allocate(MAX_PACKAGE_LEN);
// 长度占位
bb.put(length);
// head 占位
bb.put(header);
// command 占位
bb.put(command);
// data
bb.put(data);
return bb;
}
}
@@ -0,0 +1,174 @@
package com.sunyard.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class CoderUtil {
public static byte[] EToA = hexToBytes(getEDBToAsc());
public static byte[] AToE = hexToBytes(getAscToEDB());
public static String getAscToEDB() {
StringBuffer sb = new StringBuffer();
sb.append("00010203372D2E2F1605250B0C0D0E0F");
sb.append("101112133C3D322618193F271C1D1E1F");
sb.append("405A7F7B5B6C507D4D5D5C4E6B604B61");
sb.append("F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F");
sb.append("7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6");
sb.append("D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D");
sb.append("79818283848586878889919293949596");
sb.append("979899A2A3A4A5A6A7A8A9C04FD0A107");
sb.append("202122232415061728292A2B2C090A1B");
sb.append("30311A333435360838393A3B04143EE1");
sb.append("41424344454647484951525354555657");
sb.append("58596263646566676869707172737475");
sb.append("767778808A8B8C8D8E8F909A9B9C9D9E");
sb.append("9FA0AAABAC4AAEAFB0B1B2B3B4B5B6B7");
sb.append("B8B9BABBBC6ABEBFCACBCCCDCECFDAdB");
sb.append("DCDDDEDFEAEBECEDEEEFFAFBFCFDFEFF");
return sb.toString(); }
public static String getEDBToAsc() {
StringBuffer sb = new StringBuffer();
sb.append("000102039C09867F978D8E0B0C0D0E0F");
sb.append("101112139D8508871819928F1C1D1E1F");
sb.append("80818283840A171B88898A8B8C050607");
sb.append("909116939495960498999A9B14159E1A");
sb.append("20A0A1A2A3A4A5A6A7A8D52E3C282B7C");
sb.append("26A9AAABACADAEAFB0B121242A293B5E");
sb.append("2D2FB2B3B4B5B6B7B8B9E52C255F3E3F");
sb.append("BABBBCBDBEBFC0C1C2603A2340273D22");
sb.append("C3616263646566676869C4C5C6C7C8C9");
sb.append("CA6A6B6C6D6E6F707172CBCCCDCECFD0");
sb.append("D17E737475767778797AD2D3D45BD6D7");
sb.append("D8D9DADBDCDDDEDFE0E1E2E3E45DE6E7");
sb.append("7B414243444546474849E8E9EAEBECED");
sb.append("7D4A4B4C4D4E4F505152EEEFF0F1F2F3");
sb.append("5C9F535455565758595AF4F5F6F7F8F9");
sb.append("30313233343536373839FAFBFCFDFEFF");
return sb.toString(); }
public static byte[] hexToBytes(char[] hex) {
int length = hex.length / 2;
byte[] raw = new byte[length];
for (int i = 0; i < length; i++) {
int high = Character.digit(hex[i * 2], 16);
int low = Character.digit(hex[i * 2 + 1], 16);
int value = (high << 4) | low;
if (value > 127) value -= 256; raw[i] = (byte) value; }
return raw; }
public static byte[] hexToBytes(String hex) { return hexToBytes(hex.toCharArray()); }
/**
* byte :: ASCII->EBCDIC
*/
public static int ASCIIToEBCDIC(int ascii) {
return AToE[ascii & 0xff] & 0xff;
}
/**
* byte :: EBCDIC->ASCII
*/
public static int EBCDICToASCII(int ebcdic) {
return EToA[ebcdic & 0xff] & 0xff;
}
/**
* byte[] :: ASCII->EBCDIC
*/
public static byte[] ASCIIToEBCDIC(byte[] ascii) {
byte[] tobytes = new byte[ascii.length];
for (int i = 0; i < ascii.length; i++)
tobytes[i] = (byte) ASCIIToEBCDIC(ascii[i]);
return tobytes;
}
/**
* 直接在原数据上修改
* byte[] :: ASCII->EBCDIC
*/
public static byte[] ASCIIToEBCDICFIX(byte[] ascii, int from) {
for (int i = from; i < ascii.length; i++)
ascii[i] = (byte) ASCIIToEBCDIC(ascii[i]);
return ascii;
}
/**
* byte[] :: EBCDIC->ASCII
*/
public static byte[] EBCDICToASCII(byte[] ebcdic) {
byte[] tobytes = new byte[ebcdic.length];
for (int i = 0; i < ebcdic.length; i++)
tobytes[i] = (byte) EBCDICToASCII(ebcdic[i]);
return tobytes;
}
/**
* byte[] :: EBCDIC->ASCII
* 直接修改原数据
*/
public static byte[] EBCDICToASCIIFIX(byte[] ebcdic, int from) {
for (int i = from; i < ebcdic.length; i++)
ebcdic[i] = (byte) EBCDICToASCII(ebcdic[i]);
return ebcdic;
}
/**
* String :: ASCII->EBCDIC
*/
public static String ASCIIToEBCDIC(String ascii)
throws Exception
{
return new String(ASCIIToEBCDIC(ascii.getBytes("iso-8859-1")), "iso-8859-1");
}
/**
* String :: EBCDIC->ASCII
*/
public static String EBCDICToASCII(String ebcdic)
throws Exception
{
return new String(EBCDICToASCII(ebcdic.getBytes("iso-8859-1")),"iso-8859-1");
}
/**
* File :: ASCII->EBCDIC
*/
public static void ASCIIToEBCDIC(String fromfile, String tofile) {
try {
FileInputStream in = new FileInputStream(new File(fromfile));
FileOutputStream out = new FileOutputStream(new File(tofile));
int tempint, i = 0;
byte[] tempbytes = new byte[in.available()];
while ((tempint = in.read()) != -1)
tempbytes[i++] = (byte) tempint;
out.write(ASCIIToEBCDIC(tempbytes));
in.close();
out.close();
} catch (Exception e) {
System.out.println(e);
}
}
/**
* File :: EBCDIC->ASCII
*/
public static void EBCDICToASCII(String fromfile, String tofile) {
try {
FileInputStream in = new FileInputStream(new File(fromfile));
FileOutputStream out = new FileOutputStream(new File(tofile));
int tempint, i = 0;
byte[] tempbytes = new byte[in.available()];
while ((tempint = in.read()) != -1)
tempbytes[i++] = (byte) tempint;
out.write(EBCDICToASCII(tempbytes));
in.close();
out.close();
} catch (Exception e) {
System.out.println(e);
}
}
}