简介
前几天发了一个利用JNI封装国密接口的类,封装的接口不全,只提供了5个接口的封装(而且JNI使用起来太麻烦)。这里提供一个jna封装国密接口的类,封装了大约20多个接口,现在也发出来,希望对大家有用。
类封装
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
public class JnaSDF {
public static int ECCref_MAX_BITS = 512;
public static int ECCref_MAX_LEN = ((ECCref_MAX_BITS+7) / 8);
public static int RSAref_MAX_BITS = 2048;
public static int RSAref_MAX_LEN = ((RSAref_MAX_BITS + 7) / 8);
public static int RSAref_MAX_PBITS = ((RSAref_MAX_BITS + 1) / 2);
public static int RSAref_MAX_PLEN = ((RSAref_MAX_PBITS + 7)/ 8);
public static int SGD_SM1_ECB = 0x00000101; /* SCB2 ECB加密机制 */
public static int SGD_SM1_CBC = 0x00000102; /* SCB2 CBC加密机制 */
public static int SGD_SM4_ECB = 0x00000401; /* SM4 ECB加密机制 */
public static int SGD_SM4_CBC = 0x00000402; /* SM4 CBC加密机制 */
public static int SGD_DES_ECB = 0x00000501; /* DES ECB加密机制 */
public static int SGD_DES_CBC = 0x00000502; /* DES CBC加密机制 */
public static int SGD_3DES_ECB = 0x00000504; /* 3DES ECB加密机制 */
public static int SGD_3DES_CBC = 0x00000508; /* 3DES CBC加密机制 */
public static int SGD_SM3 = 0x00000001; /*SM3算法机制 */
public static int SGD_SHA1 = 0x00000002; /* SHA-1算法机制 */
public static int SGD_SHA256 = 0x00000004; /*SHA256杂凑算法 */
public static int SGD_SM2 = 0x00020100; //SM2算法机制
public static int SGD_SM2_1 = 0x00020200; //椭圆曲线签名算法
public static int SGD_SM2_2 = 0x00020400; //椭圆曲线密钥交换协议
public static int SGD_SM2_3 = 0x00020800; //椭圆曲线加密算法
public static int SGD_RSA = 0x00010000; /* RSA算法机制 */
public static int SGD_RSA_SIGN_EX = 0x00010001; //导入或导出RSA签名或验证密钥时使用
public static int SGD_RSA_ENC_EX = 0x00010002; //导入或导出RSA加密或解密密钥时使用
public static class RSArefPublicKey extends Structure
{
public int bits;
public byte[] m = new byte[ECCref_MAX_LEN];
public byte[] e = new byte[ECCref_MAX_LEN];
@SuppressWarnings("rawtypes")
protected List getFieldOrder() {
return Arrays.asList("bits", "m", "e");
}
public static class ByReference extends ECCrefPublicKey implements Structure.ByReference {};
};
public static class RSArefPrivateKey extends Structure
{
public int bits;
public byte[] m = new byte[RSAref_MAX_LEN];
public byte[] e = new byte[RSAref_MAX_LEN];
public byte[] d = new byte[RSAref_MAX_LEN];
public byte[][] prime = new byte[2][RSAref_MAX_PLEN];
public byte[][] pexp = new byte[2][RSAref_MAX_PLEN];
public byte[] coef = new byte[RSAref_MAX_PLEN];
@SuppressWarnings("rawtypes")
protected List getFieldOrder() {
return Arrays.asList("bits", "m", "e", "d", "prime", "pexp", "coef");
}
public static class ByReference extends ECCrefPublicKey implements Structure.ByReference {};
};
public static class ECCrefPublicKey extends Structure
{
public int bits;
public byte[] x = new byte[ECCref_MAX_LEN];
public byte[] y = new byte[ECCref_MAX_LEN];
@SuppressWarnings("rawtypes")
protected List getFieldOrder() {
return Arrays.asList("bits", "x", "y");
}
public static class ByReference extends ECCrefPublicKey implements Structure.ByReference {};
};
public static class ECCrefPrivateKey extends Structure {
public int bits;
public byte[] d = new byte[ECCref_MAX_LEN];
@SuppressWarnings("rawtypes")
protected List getFieldOrder() {
return Arrays.asList(new String[] {"bits", "d"});
}
public static class ByReference extends ECCrefPrivateKey implements Structure.ByReference {}
};
public static class SM2Key {
public JnaSDF.ECCrefPublicKey refPubKey = new JnaSDF.ECCrefPublicKey.ByReference();
public JnaSDF.ECCrefPrivateKey refPriKey = new JnaSDF.ECCrefPrivateKey.ByReference();
};
public static class ECCCipher extends Structure {
public byte[] x = new byte[ECCref_MAX_LEN];
public byte[] y = new byte[ECCref_MAX_LEN];
public byte[] M = new byte[32];
public int L;
public byte[] C = new byte[136];
@SuppressWarnings("rawtypes")
protected List getFieldOrder() {
return Arrays.asList(new String[] {"x", "y", "M", "L", "C"});
}
public static class ByReference extends ECCCipher implements Structure.ByReference {}
};
public static class ECCSignature extends Structure{
public byte[] r = new byte[ECCref_MAX_LEN];
public byte[] s = new byte[ECCref_MAX_LEN];
@SuppressWarnings("rawtypes")
protected List getFieldOrder() {
return Arrays.asList(new String[] {"r", "s"});
}
public static class ByReference extends ECCSignature implements Structure.ByReference {}
};
public interface CLibrary extends Library
{
CLibrary Instance=(CLibrary)Native.loadLibrary((Platform.isWindows()?"SdfFileforWindows":"SDFFileforLinux"),CLibrary.class);
int SDF_OpenDevice(PointerByReference hDev);
int SDF_CloseDevice(Pointer hDev);
int SDF_OpenSession(Pointer hDev, PointerByReference hSess);
int SDF_CloseSession(Pointer hSess);
int SDF_GetPrivateKeyAccessRight(Pointer hSess, int uiKeyIndex, byte[] pucPassword, int uiPwdLength);
int SDF_ReleasePrivateKeyAccessRight(Pointer hSess, int uiKeyIndex);
int SDF_GenerateRandom(Pointer hSess, int uiLength, byte[] pucRandom);
int SDF_GenerateKeyPair_ECC(Pointer hSess, int uiAlgID, int uiKeyBits, ECCrefPublicKey pucPublicKey, ECCrefPrivateKey pucPrivateKey);
int SDF_ExportSignPublicKey_ECC(Pointer hSess, int uiKeyId, ECCrefPublicKey pucPublicKey);
int SDF_ExportEncPublicKey_ECC(Pointer hSess, int uiKeyId, ECCrefPublicKey pucPublicKey);
int SDF_ExternalSign_ECC(Pointer hSess, int uiAlgID, ECCrefPrivateKey pucPrivateKey, byte[] pucData, int uisublength, ECCSignature pucSignature);
int SDF_ExternalVerify_ECC(Pointer hSess, int uiAlgID, ECCrefPublicKey pucPublicKey, byte[] pucDataInput, int uiInputLength, ECCSignature pucSignature);
int SDF_ExternalEncrypt_ECC(Pointer hSess, int uiAlgID, ECCrefPublicKey pucPublicKey, byte[] pucData, int uisublength, ECCCipher pucEncData);
int SDF_ExternalDecrypt_ECC(Pointer hSess, int uiAlgID, ECCrefPrivateKey pucPrivateKey, ECCCipher pucEncData, byte[] pucData, IntByReference puisublength);
int SDF_InternalSign_ECC(Pointer hSess, int uiISKIndex, byte[] pucData, int uisublength, ECCSignature pucSignature);
int SDF_InternalVerify_ECC(Pointer hSess, int uiISKIndex, byte[] pucData, int uisublength, ECCSignature pucSignature);
int SDF_ImportKey(Pointer hSess, byte[] pucKey, int uiKeyLength, PointerByReference phKeyHandle);
int SDF_DestoryKey(Pointer hSess, Pointer hKeyHandle);
int SDF_ImportKeyWithISK_ECC (Pointer hSess, int uiISKIndex, ECCCipher pucKey, PointerByReference phKeyHandle);
int SDF_Encrypt(Pointer hSess, Pointer hKey, int algID, byte[] iv, byte[] plain, int plainlen, byte[] enc, IntByReference enclen);
int SDF_Decrypt(Pointer hSess, Pointer hKey, int algID, byte[] iv, byte[] enc, int enclen, byte[] plain, IntByReference plainlen);
int SDF_HashInit(Pointer hSess, int uiAlgID, ECCrefPublicKey pucPublicKey, byte[] pucID, int uiIDLength);
int SDF_HashUpdate(Pointer hSess, byte[] pucData, int uisublength);
int SDF_HashFinal(Pointer hSess, byte[] pucHash, IntByReference puiHashLength);
int SDF_InternalDecryptEx_ECC(Pointer hSess, int uiISKIndex, int KeyType, ECCCipher pucEncData, byte[] pucData, IntByReference uisublength);
int SDF_ImportKey_Ex(Pointer hSess, int KeyId, int KeyType, byte[] pKey, int KeyLen, byte[] pTag);
int SDF_ImportKeyPair_Ex(Pointer hSess, int Mechanism, int KeyID, int KeyType, RSArefPrivateKey refRsaKey, ECCrefPublicKey refEccPubKey, ECCrefPrivateKey refEccPriKey);
int SDF_ExportSymmKey_Ex(Pointer hSess, int uiKeyIndex, byte[] pucInternalKey, IntByReference uiKeyLen);
};
}
扩展功能类
在这里,以打开设备、打开回话,产生随机数为例,写一个基于JnaSDF为父类的功能类,希望能
抛转引玉。其他的功能小伙伴们自行实现吧。
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
//单独放一个java文件中,封装sdf函数返回码,抛出异常
public class SDFException extends Exception {
private static final long serialVersionUID = 1L;
public int errno;
public SDFException(String funcname, int errno)
{
super(funcname + Integer.toHexString(errno));
this.errno = errno;
}
}
//单独放一个java文件中,封装功能函数,失败抛出异常
public class JnaSDFFunction extends JnaSDF {
public static Pointer open_Device() throws SDFException
{
int rv;
PointerByReference phDev = new PointerByReference();
rv = CLibrary.Instance.SDF_OpenDevice(phDev);
if(0 != rv)
throw new SDFException("CLibrary.Instance.SDF_OpenDevice return error: ", rv);
return phDev.getValue();
}
public static Pointer open_Session(Pointer hDev) throws SDFException
{
int rv;
PointerByReference phSess = new PointerByReference();
rv = CLibrary.Instance.SDF_OpenSession(hDev, phSess);
if(0 != rv)
throw new SDFException("CLibrary.Instance.SDF_OpenSession return error: ", rv);
return phSess.getValue();
}
public static int close_Device(Pointer hDev) throws SDFException
{
int rv;
rv = CLibrary.Instance.SDF_CloseDevice(hDev);
if(0 != rv)
throw new SDFException("CLibrary.Instance.SDF_CloseDevice return error: ", rv);
return 0;
}
public static int close_Session(Pointer hSess) throws SDFException
{
int rv;
rv = CLibrary.Instance.SDF_CloseSession(hSess);
if(0 != rv)
throw new SDFException("CLibrary.Instance.SDF_CloseSession return error: ", rv);
return 0;
}
//功能函数:产生随机数
public static byte[] generate_Random(Pointer hSess, int len) throws SDFException
{
int rv, i, _len, offset = 0;
byte[] rand = new byte[len];
byte[] tmp = new byte[1536];
for(i=0; ; i+= 1536) {
if(i + 1536 <= len)
_len = 1536;
else
_len = len - i;
rv = CLibrary.Instance.SDF_GenerateRandom(hSess, _len, tmp);
if(0 != rv)
throw new SDFException("CLibrary.Instance.SDF_GenerateRandom error: ", rv);
System.arraycopy(tmp, 0, rand, offset, _len);
offset += _len;
if(offset >= len)
break;
}
return rand;
}
}
将上面的JnaSDFFunction 类导入到文件, 直接调用功能就可以了。