java利用jna对国密SDF接口的封装类

该文章介绍了如何使用JNA而非JNI来封装国密(国家密码算法)接口,提供了大约20个加密、解密、签名等接口的封装,包括SM2、SM3、SM4等。此外,还展示了如何通过示例功能类进行设备打开、会话创建和生成随机数的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

前几天发了一个利用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 类导入到文件, 直接调用功能就可以了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

化妖成魔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值