CN103093136B - 一种java应用访问智能密钥装置的方法 - Google Patents

一种java应用访问智能密钥装置的方法 Download PDF

Info

Publication number
CN103093136B
CN103093136B CN201210580998.8A CN201210580998A CN103093136B CN 103093136 B CN103093136 B CN 103093136B CN 201210580998 A CN201210580998 A CN 201210580998A CN 103093136 B CN103093136 B CN 103093136B
Authority
CN
China
Prior art keywords
type
interface
env
jni
parameter
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Active
Application number
CN201210580998.8A
Other languages
English (en)
Other versions
CN103093136A (zh
Inventor
陆舟
于华章
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Feitian Technologies Co Ltd
Original Assignee
Feitian Technologies Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Feitian Technologies Co Ltd filed Critical Feitian Technologies Co Ltd
Priority to CN201210580998.8A priority Critical patent/CN103093136B/zh
Publication of CN103093136A publication Critical patent/CN103093136A/zh
Priority to PCT/CN2013/087916 priority patent/WO2014101610A1/zh
Priority to US14/394,593 priority patent/US9824201B2/en
Application granted granted Critical
Publication of CN103093136B publication Critical patent/CN103093136B/zh
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F21/00Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
    • G06F21/30Authentication, i.e. establishing the identity or authorisation of security principals
    • G06F21/31User authentication
    • G06F21/34User authentication involving the use of external additional devices, e.g. dongles or smart cards
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F21/00Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
    • G06F21/10Protecting distributed programs or content, e.g. vending or licensing of copyrighted material ; Digital rights management [DRM]
    • G06F21/12Protecting executable software
    • G06F21/14Protecting executable software against software analysis or reverse engineering, e.g. by obfuscation
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/44Arrangements for executing specific programs
    • G06F9/448Execution paradigms, e.g. implementations of programming paradigms
    • G06F9/4482Procedural
    • G06F9/4484Executing subprograms
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/44Arrangements for executing specific programs
    • G06F9/455Emulation; Interpretation; Software simulation, e.g. virtualisation or emulation of application or operating system execution engines
    • G06F9/45504Abstract machines for programme code execution, e.g. Java virtual machine [JVM], interpreters, emulators

Landscapes

  • Engineering & Computer Science (AREA)
  • Software Systems (AREA)
  • Theoretical Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Computer Security & Cryptography (AREA)
  • Computer Hardware Design (AREA)
  • Technology Law (AREA)
  • Multimedia (AREA)
  • Stored Programmes (AREA)
  • Telephone Function (AREA)
  • Devices For Executing Special Programs (AREA)

Abstract

本发明公开了一种java应用访问智能密钥装置的方法,属于信息安全领域。所述方法包括:java应用调用JNI接口,根据JNI接口函数与下层接口函数的对应表,获取对应的下层接口函数,根据下层接口函数的目标参数列表,将JNI接口函数的源参数列表转换为对应的下层接口函数的目标参数列表,调用下层接口,访问智能密钥装置,得到返回结果,再将返回结果的值返回给java应用。采用本发明的技术方案能够使java应用不容易被反编译获取源码,提高了java应用访问智能密钥装置的安全性。

Description

一种java应用访问智能密钥装置的方法
技术领域
本发明涉及信息安全领域,尤其涉及一种java应用访问智能密钥装置的方法。
背景技术
智能密钥装置是一种USB接口设备,它采用双因子认证模式,使用方便、成本较低。它内置单片机或智能密钥装置芯片,可以存储用户密钥或数字证书,利用智能密钥装置内的密文算法可以实现对用户身份的认证,智能密钥装置具有电子邮件加密、数字签名、安全证书、安全网络登录和访问SSL安全网络等功能,具有保证用户的私钥永远不离开硬件的特征,并且还具有物理上防攻击的特征,安全性极高。
Java应用程序虽然能够直接访问智能密钥装置,但是由于java语言的特性,很容易通过反编译来获取源代码,访问安全性低,存在安全隐患。
发明内容
本发明的目的是为了克服现有技术的不足,提供了一种java应用访问智能密钥装置的方法。
本发明采用的技术方案是:一种java应用访问智能密钥装置的方法,包括:
步骤101:JNI接口获取JNI接口函数被调用时的源参数列表;
步骤102:根据预设JNI接口函数与下层接口函数的对应表,确定与JNI接口函数对应的下层接口函数;
步骤103:根据所述下层接口函数确定目标参数列表;
步骤104:根据下层接口的目标参数列表,将所述源参数列表的值传递给相应的下层接口参数;
步骤105:调用所述下层接口,访问智能密钥装置,得到返回结果;
步骤106:将所述得到的返回结果返回给调用方或抛出异常,结束。
所述步骤102中,所述预设JNI接口函数与下层接口函数的对应表中包括多个一一对应的接口函数对,其中每个接口函数对中包含一个JNI接口函数与一个与所述JNI接口函数对应的下层接口函数,当JNI接口函数被调用时,根据所述预设JNI接口函数与下层接口函数的对应表查找到对应的下层接口函数。
所述步骤104中:
如果下层接口需要的类型是预定义简单类型,则:
根据下层接口需要的预定义简单类型,根据源参数列表中的预定义本地类型的参数,查询第一预设映射表,获取所述第一预设映射表中包含所述预定义本地类型的参数的类型对,得到与所述预定义本地类型对应的下层接口函数需要的预定义简单类型,通过强制类型转换,得到下层接口需要的参数。
所述步骤104中:
如果下层接口函数需要的类型是预定义复合类型,则:
根据下层接口需要的预定义复合类型,根据源参数列表中的预定义引用类型的参数,查询第二预设映射表,获取所述第二预设映射表中包含所述预定义引用类型的参数类的型对,得到与所述预定义引用类型对应的下层接口函数需要的预定义复合类型。
所述步骤104具体包括:
步骤104-1:获取所述源参数列表中所述预定义引用类型的参数的长度,并根据参数长度分配第一缓冲区;
步骤104-2:将所述源参数列表中所述预定义引用类型的参数转存至所述第一缓冲区中;
步骤104-3:在所述下层接口中为转存后的数据分配第二缓冲区;
步骤104-4:将所述转存后的数据存入所述第二缓冲区中。
所述步骤106具体包括:
步骤106-1:判断所述返回结果是否正确,如果是,则执行步骤106-2,否则抛出异常,结束;
步骤106-2:将所述返回结果的值返回给调用方。
所述步骤106-1具体为:
判断下层结果的返回结果是否是预定义的“成功”,如果是,则表示返回结果正确,执行步骤106-2,否则表示返回结果错误,抛出异常,结束。
所述抛出异常具体包括:
A:根据源参数列表中的参数,获取调用方异常类;
B:根据源参数列表中的参数,实例化调用方异常;
C:根据源参数列表中的参数,为调用方抛出异常。
所述步骤106中将所述得到的返回结果返回给调用方,具体包括:
S1:获取调用方的类;
S2:创建所述类的实例;
S3:将所述下层接口返回的内容传给所述类的实例;
S4:将所述创建的类的实例返回给调用方。
所述步骤S3包括:
步骤S3-1:获取预定的成员变量在存储所述类的实例的缓冲区的首地址;
步骤S3-2:根据所述下层接口返回内容的预定的成员变量的类型与调用方的结构的成员变量类型,将下层接口返回内容的类型转换成为JNI接口类型;
步骤S3-3:将转换后的内容传递给所述类的实例。
所述步骤106中将所述的得到的返回结果返回给调用方,具体包括:
如果所述下层接口返回内容的类型是预定义简单类型,则根据所述第一预设映射表,将所述预定义简单类型的参数,通过强制类型转换得到JNI接口类型,然后将得到的JNI接口类型的值返回给调用方;
如果所述下层接口返回内容的类型是预定义复合类型,则根据所述第二预设映射表,将所述预定义引用类型的参数转换为JNI接口类型,然后将得到的JNI接口类型的值返回给调用方。
如果下层接口的返回内容的类型是预定义复合类型,根据所述第二预设映射表,将所述预定义引用类型的参数转换为JNI接口类型,然后将得到的JNI接口类型的值返回给调用方,具体包括:
步骤B1:获取所述下层接口的返回内容的长度,并根据所述长度分配第三缓冲区;
步骤B2:将所述下层接口的返回内容转存至所述第三缓冲区中;
步骤B3:在JNI接口中为转存后的数据分配第四缓冲区;
步骤B4:将所述转存后的数据存入所述第四缓冲区中。
附图说明
图1为本发明实施例1提供了一种java应用访问智能密钥装置的方法流程图;
图2为本发明实施例2提供了一种java应用访问智能密钥装置的方法流程图;
图3为本发明实施例3提供了一种java应用访问智能密钥装置的方法流程图;
图4为本发明实施例4提供了一种java应用访问智能密钥装置的方法流程图;
图5为本发明实施例5提供了一种java应用访问智能密钥装置的方法流程图;
图6为本发明实施例6提供了一种java应用访问智能密钥装置的方法流程图。
具体实施方式
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
实施例1
本发明的实施例1提供了一种java应用访问智能密钥装置的方法,如图1所示,包括:
步骤101:JNI接口获取JNI接口函数被调用时的源参数列表;
步骤102:根据预设JNI接口函数与下层接口函数的对应表,确定与JNI接口函数对应的下层接口函数;
在本实施例中,所述下层接口是预定义的PKCS#11接口;
步骤103:根据所述下层接口函数确定目标参数列表;
步骤104:判断JNI接口函数的源参数列表中的参数是否是预定义本地类型,如果是,则执行步骤105,否则执行步骤106;
在本实施例中,所述预定义本地类型包括:jbyte、jchar、jboolean、jint、jlong等;
步骤105:根据下层接口需要的参数类型,查询第一预设映射表,将JNI接口函数的源参数列表中预定义本地类型的参数,,通过强制类型转换,得到下层接口函数的目标参数列表需要的预定义简单类型的参数,执行步骤107;
所述第一预设映射表为:
步骤106:根据下层接口需要的参数类型,查询第二预设映射表,将JNI接口函数的源参数列表中预定义引用类型的参数,得到下层接口函数的目标参数列表中需要的预定义复合类型的参数,执行步骤107;
所述第二预设映射表为:
具体包括:
106-1:获取源参数列表中预定义引用类型的参数长度,根据所述参数长度分配缓冲区空间,供下层接口使用;
在本实施例中,所述源参数列表的参数是预定义引用类型,而下层接口需要的是预定义复合类型或是指向预定义复合类型的指针类型,类型不同,需要的空间也不相同,需要重新为下层接口函数的参数分配空间;
106-2:对预定义引用类型的数据进行拆分,并判断拆分后得到的数据的类型是否为下层接口需要的类型,是则执行步骤106-3,否则抛出异常;
106-3:检测所述拆分得到的数据的类型,如果是预定义本地类型,则执行步骤106-4,如果是预定义引用类型,则执行步骤106-2;
106-4:将所述拆分得到的预定义本地类型的数据进行强制类型转换;
步骤107:根据预先约定的大小分配缓冲区;
步骤108:调用下层接口,访问智能密钥装置,得到返回结果;
步骤109:判断所述返回结果是否正确,如果是,则执行步骤110,否则抛出异常,结束;
具体的,判断所述返回值是否等于CKR_OK(下层接口宏定义),如果是,则表示返回值正确,否则表示返回值错误;
抛出异常具体包括,
a:获取异常类对象;
b:实例化异常类对象;
c:将实例化后的异常类对象抛出;
步骤110:将下层接口的返回结果的值传给调用方;
具体的,
1、当不由源参数列表中的参数进行类型转换得到的目标参数的数据类型是预定义简单类型时,根据所述第一预设映射表,对所述目标参数进行强制数据类型转换,然后上传;
2、当不由源参数列表中的参数进行类型转换得到的目标参数的数据类型是预定义复合类型时,根据所述第二预设映射表,对所述目标参数进行数据类型转换,然后上传;
具体包括:
S1:对所述预定义复合类型的参数进行拆分,并检测拆分后的参数的数据类型,如果是预定义简单类型,则执行步骤S2,如果仍是预定义复合类型,则继续执行S1;
S2:将所述拆分后的预定义本地类型的数据进行强制类型转换,然后上传;
S3:将转换后得到的结果返回给调用方。
实施例2
本发明实施例2提供了一种java访问智能密钥装置的方法,如图2所示,包括:
本实施例以获取智能密钥装置信息的方法为例来说明;
当预定的接口public native CK_TOKEN_INFO C_GetTokenInfo (long slotID) throws PKCS11Exception被调用时:
步骤201:JNI接口获取源参数列表;
具体的,当预定的接口public native CK_TOKEN_INFO C_GetTokenInfo (long slotID) throws PKCS11Exception被调用时,java通过JNI技术调用JNI接口函数:JNIEXPORT jobject JNICALL Java_pkcs11_wrapper_PKCS11Imple mentation_C_1GetTokenInfo(JNIEnv *env, jobject obj, jlong jSlotID),其中接口名中的pkcs11_wrapper_PKCS11Implementation为预定的接口在调用方工程中的路径,即预定的接口在调用方在包名为pkcs11.wrapper的PKCS11Implementation类中;
获取到的参数列表为JNIEnv *env, jobject obj, jlong jSlotID,其中,JNIEnv *env, jobject obj是JNI接口添加的参数,用于在JNI层操作java数据,或者用于创建java数据对象以及对java数据对象赋值,真正的源参数列表是jlong jSlotID;
步骤202:根据预设JNI接口函数与下层接口函数的对应表,确定与JNI接口函数对应的下层接口函数;
具体的,在本实施例中,调用的下层接口为预先约定的PKCS#11接口;
在本实施例中,与所述JNI接口函数对应的下层接口函数是:
C_GetTokenInfo(
CK_SLOT_ID slotID,
CK_TOKEN_INFO_PTR pTokenInfo);
步骤203:根据下层接口函数确定目标参数列表;
在本实施例中,所述目标参数列表是:CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pTokenInfo;
步骤204:将源参数列表中的参数类型转换为下层接口可识别的类型;
具体的,根据所述第一预设映射表,将jlong类型的jSlotID强制类型转换为CK_SLOT_ID类型的slotID;
步骤205:根据预先约定的大小分配缓冲区;
具体的,在本实施例中,根据预先约定的PKCS#11数据结构CK_TOKEN_INFO的大小分配缓冲区;
CK_TOKEN_INFO tokenInfo = {0};
其中,所述目标参数pTokenInfo,即为所述缓冲区的首地址,即有:pTokenInfo = &tokenInfo;
所述缓冲区的结构为:
其中,调用方的结构如下:
步骤206:调用下层接口,访问智能密钥装置,得到返回结果;
在本实施例中,通过调用CK_RV rv = C_GetTokenInfo(slotID,pTokenInfo)将步骤204中CK_SLOT_ID类型的slotID和步骤205中所述缓冲区的首地址传给下层接口;
步骤207:判断返回结果是否正确,如果是,则执行步骤208,否则抛出异常,结束;
在本实施例中,如果下层接口的返回值不是预先预定的“成功”,则将下层接口的返回值通过抛出异常的方式返回给调用方,否则,将下层接口的返回值以及所述缓冲区中的内容返回给调用方;
具体的,抛出异常的方式为:
S1:通过源参数列表中的参数JNIEnv *env,获取调用方异常类;
具体地,以PKCS11Exception异常类为例:
通过调用jclass errClass = (*env)->FindClass(env, “pkcs11/ wrapper/ PKCS11Exception”)获取调用方异常类,其中" pkcs11/wrapper/ PKCS11Exception "为异常类PKCS11Exception在调用方工程中的路径;
S2:通过源参数列表中的参数JNIEnv *env,实例化调用方异常;
具体地,通过调用jmethodID jConstructor = (*env)-> GetMethodID(env, errClass, "<init>", "()V")来获取预定的异常类的构造函数,其中"<init>"表示是够着函数,"()V"表示参数与返回值类型,errClass为上述S1中获取;
通过调用jthrowable jOutOfError = (jthrowable) (*env)->NewObject (env,errClass, jConstructor)将调用方异常类实例化;
具体地,errClass由S1中获取,jConstructor即上述调用GetMethodID获取得到;
S3:通过源参数列表中的参数JNIEnv *env,为调用方抛出异常;
具体地,通过调用(*env)->Throw(env, jOutOfError)将异常抛出,由调用方接收;其中jOutOfError由S2中获取;
步骤208:将下层接口的返回结果转换为JNI接口类型,然后返回给调用方;
具体包括:
步骤 208-1:通过调用JNI参数列表中的JNIENV *env,获取调用方的CK_TOKEN_INFO类;
在本实施例中,通过调用jclass jTokenInfoClass = (*env)->FindClass (env,“pkcs11/wrapper/CK_TOKEN_INFO”);来获取调用方的CK_TOKEN_INFO类,其中,”pkcs11/wrapper/CK_TOKEN_INFO”为预定的CK_TOKEN_INFO类在调用方工程中的路径;
步骤208-2:通过JNI参数列表中的JNIENV *env,创建CK_TOKEN_INFO类的实例;
在本实施例中,通过调用jobject jTokenInfoObject = (*env)->Alloc Object (env, jTokenInfoClass);来创建CK_TOKEN_INFO类的实例;
步骤 208-3:通过JNI参数列表中的JNIENV *env,将下层接口返回的内容传给所述类的实例;
本实施例中,步骤208-3具体包括:
一、获取预定的成员变量在类的实例中的属性编号;
在本实施例中,通过调用
jfieldID jFieldID1 = (*env)->GetFieldID(env, jTokenInfoClass, "label", "[C");
jfieldID jFieldID2 = (*env)->GetFieldID(env, jTokenInfoClass, "flags", "J");
jfieldID jFieldID3 = (*env)->GetFieldID(env, jTokenInfoClass, "hardwareVersion","Lpkcs11/wrapper/CK_VER SION;")来获取成员变量的属性编码,其中,label为预定的成员变量名,[C 为预定成员变量的类型char[],J表明类型为long;pkcs11/wrapper/CK_VERSION为预定的CK_VERSION类在调用方工程的路径;
二、根据下层接口返回内容的预定结构中成员变量的类型与调用方的结构的成员变量类型,将下层接口返回内容转换成为对应的类型;
具体的,
1、根据所述第一预设映射表,将CK_ULONG、CK_FLAGS强制转换为jlong;
2、根据所述第二预设映射表,将CK_UTF8CHAR[]、CK_CHAR[]转换为jcharArray;
具体包括:
(1)将CK_UTF8CHAR[]、CK_CHAR[]转换为jchar*类型;
具体的,
通过调用jchar* jpTemp = (jchar*) malloc(sizeof(tokenInfo. label) * sizeof(jchar))和for (int i=0; i<sizeof (tokenInfo. label); i++) {jpTemp[i] = (jchar)tokenInfo.label[i];}将CK_UTF8CHAR[]、CK_CHAR[]进行循环转换为jchar*类型;
(2)通过源参数列表中的参数JNIEnv *env,将jchar*类型数据转变为jcharArray类型的数据;
具体的:
通过调用jcharArray jArray = (*env)->NewCharArray(env, jsize(sizeof (tokenInfo.label)*sizeof(jchar)));为jcharArray分配缓冲区,然后通过调用(*env)->SetCharArrayRegion(env, jArray, 0, jsize(sizeof(tokenInfo. label)), jpTemp);将jchar*的tokenInfo.label中的内容转存至jArray所在缓冲区中;
3、根据所述第二预设映射表,将下层接口的结构体CK_VERSION转换为调用方的CK_VERSION类;
具体包括:
CK_VERSION 在下层接口的返回内容的结构为:
{CK_BYTE       major;
CK_BYTE       minor;};
CK_VERSION类在调用方的结构为:
public class CK_VERSION {
public byte major;
public byte minor;};
具体转换过程如下:
(1)通过JNI参数列表中的JNIEnv *env,获取调用方的CK_VERSION类;
在本实施例中,通过调用jclass jVersionClass = (*env)->FindClass(env, pkcs11/wrapper/CK_VERSION);获取调用方的CK_VERSION类,其中pkcs11/wrapper/CK_VERSION为预定的CK_VERSION类在调用方工程中的路径;
(2)通过JNI参数列表中的JNIEnv *env,创建CK_TOKEN_INFO类对象;
在本实施例中,通过调用jobject jVersionObject= (*env)->AllocObject (env, jVersionClass );创建CK_TOKEN_INFO类对象;
(3)通过JNI参数列表中的JNIEnv *env,将下层接口返回的CK_VERSION对象的内容给CK_VERSION类的实例;
具体包括:
①.获取预定的成员变量在类的实例中的属性编号;
在本实施例中,通过调用jfieldID jFieldID = (*env)->GetFieldID(env, jVersionClass, "major", "B")获取属性编码;
②.根据下层接口返回内容的预定结构中成员变量的类型与调用方的结构的成员变量类型,对下层接口返回内容CK_BYTE转换成为对应的类型jbyte;
具体为:
根据所述第一预设映射表,将CK_BYTE类型强制转换为jbyte类型;
③.将转换后的内容传递给类对象jVersionObject;
在本实施例中,通过调用(*env)->SetByteField(env, jVersionObject,jFieldID,(jbyte)(tokenInfo.hardwareVersion. major))将转换后的内容传给jVersionObject;
三、将转换后的内容传递给类的实例jTokenInfoObject;
在本实施例中,通过调用(*env)->SetObjectField(env, jTokenInfoObject, jFieldID1, jArray)和(*env)->SetLongField (env,jTokenInfoObject, jFieldID2, (jlong)tokenInfo.flags)和(*env)->SetObjectField(env, jTokenInfoObject, jFieldID3, jVersionObject);将转换后的内容传给jTokenInfoObject;
步骤 208-4:通过调用return 方法,将创建的类的实例jTokenInfoObject返回。
实施例3
本发明实施例3提供了一种java访问智能密钥装置的方法,包括:
本实施例以获取访问标识的方法为例说明:
当预定的接口public native long C_OpenSession(long slotID, long flags, Object pApplication, CK_NOTIFY Notify)throws PKCS11Exception被调用时:
步骤301:JNI接口获取源参数列表;
具体地,
当预定的接口public native long C_OpenSession(long slotID, long flags, Object pApplication, CK_NOTIFY Notify)throws PKCS11Exception被调用时,java通过JNI技术调用JNI接口函数:JNIEXPORT jlong JNICALL Java_ pkcs11_wrapper_PKCS11Implement ation_C_1OpenSession (JNIEnv *env, jobject obj, jlong jSlotID, jlong jFlags, jobject jApplication,jobject jNotify);其中接口名中的pkcs11_wrapper_PKCS11Implementation为预定的接口在调用方工程中的路径,即预定的接口在调用方在包名为pkcs11.wrapper的PKCS11Implementation类中;
参数列表中的JNIEnv *env, jobject obj 是JNI添加的参数,以便在JNI层操作java数据,或者创建java的数据对象以及对java数据对象赋值,真正的参数列表为jlong jSlotID, jlong jFlags, jobject jApplication, jobject jNotify;
步骤302:根据预设JNI接口函数与下层接口函数的对应表,确定与JNI接口函数对应的下层接口函数;
在本实施例中,与所述JNI接口函数对应的下层接口函数是:
步骤303:根据所述下层接口函数确定目标参数列表;
在本实施例中,目标参数列表为:  CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession;
步骤304:将源参数列表中预定义本地类型的参数转换为下层接口可识别的类型;
具体包括:
根据所述第一预设映射表,将jlong类型的jSlotID强制转换为CK_SLOT_ID类型的slotID;将jlong类型的jFlags 强制转换为CK_FLAGS类型的flags;
步骤305:将源参数列表中预定义引用类型的参数转换为下层接口可识别的类型;
具体包括:
根据所述第二预设映射表,将jobject 类型的jApplication转换为CK_VOID_PTR类型的pApplication;将jobject 类型的jNotify 转换为CK_NOTIFY 类型的Notify;
具体地,根据下层接口的参数作用,由于CK_NOTIFY在下层接口中为函数指针,而其在调用方的结构为类,参数jApplication的作用是供CK_NOTIFY的函数指针使用;
具体地,根据下层接口无法直接使用调用方函数的原则,我们需要将jobject的俩个参数转换成为一个CK_VOID_PTR类型,并且在JNI层使用一个函数来转换为CK_NOTIFY的函数指针,并且此函数能够使用调用方函数,jobject转换后的结构为:
其中,成员jNotifyObject即为参数列表中的jNotify,成员jApplicationData即为参数列表中的jApplication;
根据预先约定的大小分配缓冲区;
具体的,在本实施例中,根据预先约定的所述数据结构NotifyEncapsulation的大小分配缓冲区;
NotifyEncapsulation application = {NULL, NULL};
其中,所述目标参数pApplication,即为所述缓冲区的首地址,即有:pApplication= &application;
将源参数列表中的jNotify 与jApplication存入所述缓冲区,具体地,通过调用
application.jNotifyObject = jNotify;
application.jApplicationData = jApplication;
构造目标参数CK_NOTIFY 类型的Notify的步骤如下:
jNotify在调用方的结构如下:
public interface CK_NOTIFY {
public void CK_NOTIFY(long hSession, long event, Object pApplication) throws PKCS11Exception;}
其中,真正需要调用的调用层函数为CK_NOTIFY类中的成员函数:public void CK_NOTIFY(long hSession, long event, ObjectpApplication)throwsPKCS11Exception
其中,JNI层函数参数列表均由所述下层接口提供,其中CK_VOID_PTRpApplication,即为所述下层接口的CK_VOID_PTR的参数pApplication,也就是上述变量application的首地址;
具体地,JNI函数notifyCallback使用调用方函数的步骤过程具体包括:
其中,函数接口notifyCallback的首地址即为目标参数Notify的值,即Notify = (CK_NOTIFY)&notifyCallback;
将参数列表中CK_SESSION_HANDLE类型的hSession强制类型转换为jlong类型的hSession,将CK_NOTIFICATION类型的event 强制类型转换为jlong 类型的event,将application中的成员jApplicationData转变为jobject类型。
其中JNI使用调用方函数的过程具体如下:
⑴获取JNIEnv指针类型的env;
具体地,
⑵.获取调用方CK_NOTIFY类
具体地,通过调用jclass ckNotifyClass = (*env)->FindClass(env, pkcs11/wrapper/PKCS11Implementation); 其中PKCS11Implementation为CK_NOTIFY类在调用方工程中的路径;
⑶.获取调用方CK_NOTIFY类中的成员函数public void CK_NOTIFY(long hSession, long event, Object pApplication)throwsPKCS11Exception的属性编号;
具体地,通过调用jmethodID jmethod = (*env)-> etMethodID(env, ckNotifyClass, "CK_NOTIFY", "(JJLjava/lang Object;)V");
⑷.调用方CK_NOTIFY类中的函数CK_NOTIFY函数;
具体地,通过调用(*env)->CallVoidMethod(env, notify ncapsulation->jNotifyObject, jmethod,jSessionHandle, jEvent, notifyEncapsulation->jApplicationData);
步骤306:根据预先约定的大小分配缓冲区;
具体地,在本实施例中,根据预先约定的PKCS#11数据类型CK_SESSION_HANDLE的大小分配缓冲区;
CK_SESSION_HANDLE hSession = 0;
phSession =&hSession,其中phSession为所述缓冲区的首地址;
步骤307:调用下层接口,访问智能密钥装置,得到返回结果;
具体地,
在本实施例中,通过调用CK_RV rv = C_OpenSession(CK_SLOT_ID slotID,CK_FLAGS flags,CK_VOID_PTR pApplication,CK_NOTIFY Notify,phSession);将步骤304和步骤305转换得到的参数和步骤306中所述缓冲区的首地址传给下层接口;
步骤308:判断所述返回结果是否正确,如果是,则执行步骤309,否则抛出异常,结束;
具体的,
如果下层接口的返回值不是预先预定的“成功”,则将下层接口的返回值通过抛出异常的方式返回给调用方,否则,在步骤309中将下层接口的返回值以及所述缓冲区中的内容返回给调用方;
具体的,抛出异常的方式为:
S1:通过JNI参数列表中的JNIEnv *env,获取调用方异常类;
具体地,以PKCS11Exception异常类为例:
通过调用jclass errClass = (*env)->FindClass(env, “pkcs11/wrapper/PKCS11Exception”)获取调用方异常类,其中" pkcs11/wrapper/PKCS11Exception "为异常类PKCS11Exception在调用方工程中的路径;
S2:通过JNI参数列表中的JNIEnv *env,实例化调用方异常;
具体地,通过调用jmethodID jConstructor = (*env)-> GetMethodID(env, errClass, "<init>", "()V")来获取预定的异常类的构造函数,其中"<init>"表示是构造函数,"()V"表示参数与返回值类型,errClass为上述S1中获取;
通过调用jthrowable jOutOfError = (jthrowable)(*env)->NewObject (env, errClass, jConstructor)将调用方异常类实例化;
具体地,errClass由S1中获取,jConstructor即上述调用GetMethodID获取得到;
S3:通过JNI参数列表中的JNIEnv *env,为调用方抛出异常;
具体地,通过调用(*env)->Throw(env, jOutOfError);将异常抛出,由调用方接收;其中jOutOfError由S2中获取;
步骤309:将所述返回结果转换为JNI接口类型,并将结果返回给调用方;
将所述缓冲区中的内容返回给调用方,具体包括:
所述缓冲区的结构为:
{
CK_ULONG;
}
调用方的结果如下:
{
long;
}
根据所述预设第一映射表,将CK_SESSION_HANDLE 类型的hSession强制转换为jlong类型的jsessionhandle,然后通过调用return 方法,将jlong类型的jsessionhandle返回。
实施例4
本发明实施例4提供一种java访问智能密钥装置的方法,包括:
本实施例以设置检索条件为例来说明;
当预定的接口public native void C_FindObjectsInit(long hSession,CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception被调用时:
步骤401:JNI接口获取源参数列表;
具体的,
当预定的接口public native void C_FindObjectsInit(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception被调用时,java通过JNI技术调用JNI接口:JNIEXPORT void JNICALL Java_pkcs11_wrapper_ PKCS11Implementation_C_1FindObjects Init(JNIEnv *env, jobject obj, jlong jSessionHandle,jobjectArray jTemplate),其中接口名中的pkcs11_wrapper_ PKCS11Implementation为预定的接口在调用方工程中的路径,即预定的接口在调用方在包名为pkcs11.wrapper的PKCS11Implementation类中;
参数列表为JNIEnv *env, jobject obj, jlong jSessionHandle, jobjectArray jTemplate,其中JNIEnv *env, jobject obj是JNI添加的参数,以便在JNI层操作java数据,或者创建java的数据对象以及对java数据对象赋值,真正的源参数列表为jlong jSessionHandle, jobjectArray jTemplate;
步骤402:根据预设JNI接口与下层接口函数的对应表,确定与所述JNI接口函数对应的下层接口函数;
在本实施例中,所述下层接口函数为:
步骤403:根据所述下层接口函数确定目标参数列表;
在本实施例中,所述目标参数列表为:CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR  pTemplate, CK_ULONG ulCount;
步骤404:将源参数列表中预定义本地类型的参数转换为下层接口可识别的类型;
具体的,
根据所述第一预设映射表,将jlong类型的jSessionHandle强制转换为CK_SESSION_HANDLE类型的 hSession;
步骤405:将源参数列表中预定义引用类型的参数转换为下层接口可识别的类型;
具体的,
根据所述第二预设映射表,将jobjectArray 类型的jTemplate转换为CK_ATTRIBUTE_PTR类型的pTemplate和参数jTemplate的长度CK_ULONGulCount;
具体包括:
A:根据参数jTemplate的长度为转换后的参数template分配缓冲区,供下层接口使用;
在本实施例中,通过调用CK_ULONG ulCount= (*env) ->GetArrayLength(env, jTemplate)获取参数长度;通过调用CK_ATTRIBUTE_PTR pTemplate = (CK_ATTRIBUTE_PTR) malloc(ulCount * sizeof(CK_ATTRIBUTE))为参数pTemplate分配缓冲区;
参数jTemplate的数据类型是不能被下层接口识别,因此需要重新为数据转换后的参数提供缓冲区,供下层接口使用;
B:获取CK_ATTRIBUTE数组jTemplate中的每一个结构体;
CK_ATTRIBUTE在下层接口的结构为:
CK_ATTRIBUTE在调用方的结构为:
public class CK_ATTRIBUTE {
public long type;
public Object pValue;}
在本实施例中,通过调用jobject jTemplate = (*env)-> GetObjectArray Element(env, jArray, n)来获取结构体对象,其中,n的值大于0、小于ulCount,用于表示数组下标;
jTemplate所对应的缓冲区为pTemplate[n];
C:将每一个获取的结构体的成员变量的数据类型转换为下层接口可识别的数据类型;
具体包括:
C-1:获取所述成员变量在调用方中的结构;
在本实施例中,通过调用jclass jAttributeClass = (*env)->GetObjectClass (env, jAttribute)来获取成员变量在调用方的结构;
C-2:获取所述成员变量在类的实例中的属性编号;
在本实施例中,通过调用
jfieldID jFieldID1 = (*env)->GetFieldID(env, jAttributeClass, "type", "J");
jfieldID jFieldID2 = (*env)->Get FieldID (env, jAttributeClass,“pValue”,“Ljava/lang/Object;”)来获取属性编号;
C-3:获取成员变量的值;在本实施例中,通过调用jobject jPValue =(*env)->Get ObjectField (env, jAttribute, jFieldID2)和jlong jType  = (*env)->GetLongField(env, jAttribute, jFieldID1);来获取变量值;
C-4:将获取的成员变量的值的JNI 接口的数据类型转换为下层接口可识别的类型;
本实施例中的C-4具体包括:
一、根据所述第一预设映射表,将成员变量进行强制转换,并获取type;
在本实施例中,通过调用pTemplate[n].type = (CK_ATTRIBUTE_TYPE)jType;获取type;
二、根据所述第二预设映射表,将jobject类型的jPValue  转换为CK_VOID_PTR类型的pValue 和 CK_ULONG类型的ulValueLen;
本实施例的该步骤中根据type的类型决定具体的转换过程:
A、当pTemplate[n].type是除CKA_WRAP_TEMPLATE 或者 CKA_UNWRAP_ TEMPLATE之外的类型时,转换过程为:
具体地,根据预先约定的映射表,可知此时jPValue 可能出现的类型为:pkcs11/wrapper/CK_DATE,java/lang/Boolean,java/lang/Byte,java/lang/ Character,java/lang/Class,java/lang/Integer,java/lang/Long,java/lang/String,java/lang/StringBuffer,[Z,[B,[C,[I,[J和java/lang/Object;
具体的,
A-1:获取可能出现类型在调用方的结构;
具体地,以java/lang/String为例,通过调用jclass jStringClass= (*env)->FindClass(env,"java/lang/String");来获取type结构;
A-2:将jPValue 的类型与A-1获取的结构进行比较:
具体地,以java/lang/String为例,通过调用(*env)-> IsInstanceOf(env, jPValue , jStringClass);可知,jPValue 的类型是否与jStringClass类型一致,一致时,返回成功,不一致返回失败;
A-3:将jPValue 转变为CK_VOID_PTR类型的pValue 和 CK_ULONG类型的ulValueLen;
具体为:
A-31:当jPValue 的类型为java/lang/Boolean时:
CK_ULONG类型的ulValueLen是通过调用pTemplate[n]. ulValueLen= sizeof(CK_BBOOL)获取的;
具体为:
a、为pTemplate[n].pValue分配缓冲区;
具体地,在本实施例中,通过调用pTemplate[n].pValue = (CK_BBOOL *) malloc(sizeof(CK_BBOOL))为pValue分配缓冲区;
b、获取java/lang/Boolean的结构;
具体地,通过调用jclass jBooleanClass = (*env)-> FindClass(env,"java/lang/Boolean")获取java/lang/Boolean结构;
c、将jPValue 转换为jboolean 类型的 jValue;
具体地,通过调用jmethodID jValueMethod = (*env)->GetMethodID(env, jBooleanClass, "booleanValue", "()Z");和jValue= (*env)->CallBoolean Method(env, jPValue , jValueMethod)实现;
d、将jValue的值存入缓冲区;
具体地,通过调用*(pTemplate[n].pValue) = (jValue == JNI_TRUE) ? TRUE : FALSE将jValue的值存入缓冲区;
A-32:当jPValue 的类型为java/lang/Byte,java/lang/ Character,java/lang/Integer, java/lang/Long时,
CK_ULONG类型的ulValueLen是通过调用pTemplate[n]. ulValueLen= sizeof(CK_ULONG)获取的;
以java/lang/Long结构为例;
a、为pTemplate[n].pValue分配缓冲区;
具体地,在本实施例中,通过调用pTemplate[n].pValue = (CK_ULONG *) malloc(sizeof(CK_ULONG));为pValue分配缓冲区;
b、获取java/lang/Long的结构;
具体地,通过调用jclass jLongClass = (*env)->FindClass(env, "java/lang/Long")获取java/lang/Long结构;
c、将jPValue 转换为jLong 类型的 jValue;
具体地,通过调用jmethodID jValueMethod = (*env)->GetMethodID(env, jLongClass, "longValue", "()J")和jValue = (*env)->CallBooleanMethod(env, jPValue , jValue   Method)实现;
d、将jValue的值存入缓冲区;
具体地,通过调用*(pTemplate[n].pValue) = (CK_ULONG) jValue将jValue的值存入缓冲区;
A-33: 当jPValue 的类型为[Z,[B,[C,[I,[J时,
以[B 为例;
CK_ULONG类型的ulValueLen是通过调用Template[n].ulValueLen =(*env)->GetArrayLength(env, jValue)获取的;
a、为pTemplate[n].pValue分配缓冲区;
具体地,在本实施例中,通过调用pTemplate[n].pValue = (CK_BYTE*) malloc(pTemplate[n].ulValueLen * sizeof(CK_BYTE))为pValue分配缓冲区;
b、将jPValue 转换为jbyte*类型的jpTemp;
具体地,通过调用jbyte* jpTemp = (jbyte*) malloc (pTemplate [n].ulValueLen * sizeof(jbyte))和(*env)->GetByteArrayRegion (env, jArray, 0, pTemplate[n].ulValueLen, jpTemp)实现;
c、将jpTemp的值存入缓冲区;
具体地,通过调用for (i=0; i<pTemplate[n].ulValueLen; i++){pTemplate[n].pValue[i] = CK_BYTE(jpTemp[i]);}将jValue的值存入缓冲区;
A-34:当jPValue 的类型为java/lang/String时
a、将jPValue 转换为const char*类型的pCharArray;
具体地,通过调用jboolean isCopy和pCharArray = (*env)-> GetStringUTFChars(env, jPValue , &isCopy)实现;
b、获取pCharArray长度,即pTemplate[n].ulValueLen的值;
具体的,通过调用pTemplate[n].ulValueLen = sizeof (pCharArray)实现;
c、为pTemplate[n].pValue分配缓冲区;
具体地,通过调用pTemplate[n].pValue = (CK_UTF8CHAR_PTR) malloc((pTemplate[n].ulValueLen + 1) * sizeof(CK_UTF8CHAR))实现;
d、将java/lang/String类型的jPValue 转存到所述缓冲区中;
具体地,通过调用 strcpy((char *) pTemplate[n].pValue, pCharArray);和(*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray)实现;
A-35:当jPValue 的类型为pkcs11/wrapper/CK_DATE时:
CK_DATE 在下层接口的结构为:
{CK_CHAR       year[4];
CK_CHAR       month[2];
CK_CHAR       day[2];}
在调用方结构为:
CK_ULONG ulValueLen是通过调用pTemplate [n].ulValueLen =sizeof(CK_DATE)实现的;
a、为pTemplate[n].pValue分配缓冲区;
具体地,通过调用pTemplate[n].pValue = (CK_ULONG *) malloc(sizeof(CK_DATE))实现;
b、获取pkcs11/wrapper/CK_DATE结构;
具体地,通过调用jclass jLongClass = (*env)->FindClass(env, "pkcs11/wrapper/CK_DATE")实现;
c、将jPValue 的值存入所述缓冲区中;
具体地,
c-1:获取预定的成员变量在类的实例中的属性编号;
具体的,通过调用jfieldID jYearID = (*env)->GetFieldID(env, jDateClass, "year", "[C");
jfieldID jMonthID = (*env)->GetFieldID(env, jDateClass,"month", "[C");
jfieldID jDayID = (*env)->GetFieldID(env, jDateClass, "day", "[C");实现;
c-2:获取预定的成员变量的值;
具体的,通过调用jobject jYear = (*env)->GetObject Field(env, jDate, jYearID );
jobject jMonth = (*env)->GetObjectField(env, jDate, jMonthID );
jobject jDay = (*env)->GetObjectField(env, jDate, jDayID )实现;
c-3:将所述成员变量的值转变为jchar*类型的数据,jYear 转换为jyearChars, jMonth转换为jmonthChars;
以jYear为例:
具体的,通过调用jchar* jyearChars = (jchar*) malloc((*env)->GetArrayLength(env, jYear) * sizeof(jchar));
 (*env)->GetCharArrayRegion(env, jYear, 0, (*env)->GetArrayLength(env, jYear), jyearChars)实现;
c-4:将获得的jchar*类型的数据存入所述缓冲区;
具体的,以jyearChars为例:
通过调用for (int i = 0; (i < (*env)->GetArrayLength(env, jYear)) && (i < 4) ; i++) {pTemplate[n].pValue->year[i] = (CK_CHAR) (jyearChars[i]);}实现;
A-36、当pTemplate[n].type为:CKA_WRAP_TEMPLATE 或者 CKA_UNWRAP_TEMPLATE,CK_VOID_PTR 的 pValue 的结构为CK_ATTRIBUTE时,再次执行步骤C-1之后的过程;
A-37、当jPValue 的类型为其他类型时:
pTemplate[n].pValue = NULL_PTR;
pTemplate[n].ulValueLen = 0;
在本实施例中,所述步骤404与所述步骤405不分先后顺序,可以先执行步骤404的内容,也可以先执行步骤405的内容;
步骤406:调用下层接口,访问智能密钥装置,得到返回结果;
具体的,
在实施例中,通过调用CK_RV rv = C_FindObjectsInit(hSession, pTemplate,ulCount);将步骤404中CK_SESSION_HANDLE类型的hSession和步骤405中的pTemplate、pTemplate的长度ulCount传给下层接口;
步骤407:判断所述返回结果是否正确,如果是,则执行步骤408,否则抛出异常,结束;
具体的,
如果下层接口的返回值不是预先预定的“成功”,则将下层接口的返回值通过抛出异常的方式返回给调用方,否则,将下层接口的返回值以及所述缓冲区中的内容返回给调用方;
具体的,抛出异常的方式为:
S1:通过JNI参数列表中的JNIEnv *env,获取调用方异常类;
具体地,以PKCS11Exception异常类为例:
通过调用jclass errClass = (*env)->FindClass(env, “pkcs11/wrapper/PKCS11Exception”)获取调用方异常类,其中" pkcs11/wrapper/PKCS11Exception "为异常类PKCS11Exception在调用方工程中的路径;
S2:通过JNI参数列表中的JNIEnv *env,实例化调用方异常;
具体地,通过调用jmethodID jConstructor = (*env)-> GetMethodID(env, errClass, "<init>", "()V")来获取预定的异常类的构造函数,其中"<init>"表示是够着函数,"()V"表示参数与返回值类型,errClass为上述S1中获取;
通过调用jthrowable jOutOfError = (jthrowable) (*env)->NewObject (env, errClass, jConstructor)将调用方异常类实例化;
具体地,errClass由S1中获取,jConstructor即上述调用GetMethodID获取得到;
S3:通过JNI参数列表中的JNIEnv *env,为调用方抛出异常;
具体地,通过调用(*env)->Throw(env, jOutOfError);将异常抛出,由调用方接收,其中jOutOfError由S2中获取;
步骤408:将所述返回结果返回给调用方;
在本实施例中,由于下层接口函数中没有需要转换的返回值,因此直接调用return方法,将结果返回给调用方。
实施例5
本发明实施例5提供一种java访问智能密钥装置的方法,包括:
本实施例以获取智能密钥装置内部对象信息的方法为例来说明;
当预定的接口public void C_GetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception被调用时:
步骤501:JNI接口获取源参数列表;
具体的,当预定的接口public void C_GetAttributeValue(longhSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception被调用时,java通过JNI技术调用JNI接口函数:JNIEXPORT void JNICALL Java_ pkcs11_wrapper_PKCS11Implemen tation_C_1GetAttributeValue(JNIEnv *env, jobject obj,jlong jSessionHandle, jlong jObjectHandle, jobjectArray jTemplate),其中接口名中的pkcs11_wrapper_PKCS11Implementation为预定的接口在调用方工程中的路径,即预定的接口在调用方在包名为pkcs11.wrapper的PKCS11Implementation类中;
获取到的参数列表为JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jObjectHandle, jobjectArray jTemplate,其中,JNIEnv *env, jobject obj是JNI接口添加的参数,用于在JNI层操作java数据,或者用于创建java数据对象以及对java数据对象赋值,真正的源参数列表是jlong jSessionHandle, jlong jObjectHandle, jobjectArray jTemplate;
步骤502:根据预设JNI接口函数与下层接口函数的对应表,确定与JNI接口函数对应的下层接口函数;
在本实施例中,所述下层接口函数是:
步骤503:根据所述下层接口函数确定目标参数列表;
在本实施例中,目标参数列表为:CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount;
步骤504:将源参数列表中预定义本地类型的参数转换为下层接口可识别的类型;
具体的,
根据所述第一预设映射表,将jlong 类型的jSessionHandle强制转换为CK_SESSION_HANDLE 类型的hSession,同时将jlong 类型的jObjectHandle强制转换为CK_OBJECT_HANDLE 类型的hObject;
步骤505:将源参数列表中预定义引用类型的参数转换为下层接口可识别的类型;
所述缓冲区的结构为:
其中,调用方的结构如下:
public class CK_ATTRIBUTE {
public long type;
public Object pValue;}
具体的,
根据所述第二预设映射表,将jobjectArray 类型的jTemplate转换为CK_ATTRIBUTE_PTR pTemplate,并得到参数jTemplate的长度CK_ULONG ulCount,根据预先约定的接口定义,上层应用的pValue的值不需要转换,只需要转换type、pTemplate中所有pValue的值为NULL_PTR、所有ulValueLen的值为0;
具体转换过程为:
A、获取所述成员变量在调用方中的结构;
在本实施例中,通过调用jclass jAttributeClass = (*env)->GetObjectClass (env, jAttribute)来获取成员变量在调用方的结构;
B、获取所述成员变量在类的实例中的属性编码;
在本实施例中,通过调用
jfieldID jFieldID1 = (*env)->GetFieldID(env, jAttributeClass, "type", "J")来获取成员变量的属性编码;
C、获取成员变量的值;
通过调用jlong jType = (*env)->GetLongField(env, jAttribute, jFieldID1)获取成员变量的值;
D、根据所述第一预设映射表,将获取的成员变量的值的JNI接口的数据类型强制转换为下层接口可识别的类型;
在本实施例中,通过调用
pTemplate[n].type = (CK_ATTRIBUTE_TYPE)jType获取type值;其中,n为一个大于等于0、小于ulCount的整数;
并且有pTemplate[n].pValue = NULL_PTR, pTemplate[n]. ulValueLen = 0;
在本实施例中,所述步骤504与所述步骤505不分先后顺序,可以先执行步骤504的内容,也可以先执行步骤505的内容;
步骤506:调用下层接口,访问智能密钥装置,得到结构体成员变量的长度;
具体的,
在实施例中,通过调用CK_RV rv = C_FindObjectsInit(hSession, hObject, pTemplate);将步骤504中CK_SESSION_ HANDLE类型的hSession、CK_OBJECT_HANDLE 类型的hObject 、和步骤505中CK_ATTRIBUTE_PTR类型的pTemplate、pTemplate的长度ulCount传给下层接口;
步骤507:判断所述返回结果是否正确,如果是,则执行步骤508,否则抛出异常,结束;
具体的,
如果下层接口的返回值不是预先预定的“成功”,则将下层接口的返回值通过抛出异常的方式返回给调用方,否则,将下层接口的返回值以及所述缓冲区中的内容返回给调用方;
具体的,抛出异常的方式为:
S1:通过JNI参数列表中的JNIEnv *env,获取调用方异常类;
具体地,以PKCS11Exception异常类为例:
通过调用jclass errClass = (*env)->FindClass(env, “pkcs11/wrapper/PKCS11Exception”)获取调用方异常类,其中" pkcs11/wrapper/PKCS11Exception "为异常类PKCS11Exception在调用方工程中的路径;
S2:通过JNI参数列表中的JNIEnv *env,实例化调用方异常;
具体地,通过调用jmethodID jConstructor = (*env)-> GetMethodID(env, errClass, "<init>", "()V")来获取预定的异常类的构造函数,其中"<init>"表示是够着函数,"()V"表示参数与返回值类型,errClass为上述S1中获取;
通过调用jthrowable jOutOfError = (jthrowable) (*env)->NewObject(env, errClass, jConstructor)将调用方异常类实例化;
具体地,errClass由S1中获取,jConstructor即上述调用GetMethodID获取得到;
S3:通过JNI参数列表中的JNIEnv *env,为调用方抛出异常;
具体地,通过调用(*env)->Throw(env, jOutOfError)将异常抛出,由调用方接收。其中jOutOfError由S2中获取;
步骤508:根据得到的结构体成员变量的长度,为结构体成员变量pValue分配缓冲区;
在本实施例中,所述结构体成员变量的长度为ulCount;
具体的,在本实施例中,通过调用for(int n = 0; n < ulCount;n++){pTemplate[n].pValue = malloc(pTemplate[n].ulCount);}为结构体成员变量分配缓冲区;
步骤509:判断pTemplate[n].pValue的值是否为NULL_PTR,如果是,则抛出异常,结束,否则调用下层接口,访问智能密钥装置,得到返回结果,如果结果正确,则执行步骤510,否则抛出异常;
步骤510:将所述返回结果转换为JNI接口类型,然后将转换后的结果返回给调用方;
具体的,转换过程如下:
步骤510-1:通过调用JNI参数列表中的JNIENV *env,获取调用方的CK_ATTRIBUTE类;
具体的,在本实施例中,通过调用jclass jAttributeClass = (*env)->FindClass(env, “pkcs11/wrapper/CK_ATTRIBUTE”)获取调用方的CK_ATTRIBUTE类,其中,“pkcs11/wrapper/
CK_ATTRIBUTE”为预定的CK_ATTRIBUTE类在调用方工程中的路径;
步骤510-2:通过JNI参数列表中的JNIENV *env,创建CK_ATTRIBUTE类的实例:
具体的,在本实施例中,通过调用jobject jAttribute = (*env)->AllocObject(env, jAttributeClass)创建类的实例;
步骤510-3: 获取预定的成员变量在类的实例中的属性编号;
在本实施例中,通过调用
jfieldID jFieldID1 = (*env)->GetFieldID(env, jAttributeClass, "type", "J");
jfieldID jFieldID2 = (*env)->GetFieldID(env, jAttributeClass, "pValue", "Ljava/lang/Object;")获取属性编号;
步骤510-4:根据下层接口返回内容的预定结构中成员变量的类型与调用方的结构的成员变量类型,将下层接口返回内容转换成为jobject类型的jAttribute ;
具体的,
一、根据所述第一预设映射表,将CK_ULONG类型强制转换为jlong类型;
在本实施例中,通过调用jlong type = (jlong)(pTemplate[n].type)得到jlong类型的type;
二、根据所述第二预设映射表,将CK_VOID_PTR,CK_ULONG类型转换为jobject类型的jValueObject;
具体包括:
根据type的类型决定具体的转换过程:
1、当type为
CKA_CLASS
CKA_KEY_TYPE
CKA_CERTIFICATE_TYPE
CKA_HW_FEATURE_TYPE
CKA_MODULUS_BITS
CKA_VALUE_BITS
CKA_VALUE_LEN
CKA_KEY_GEN_MECHANISM
CKA_PRIME_BITS
CKA_SUB_PRIME_BITS
CKA_CERTIFICATE_CATEGORY
CKA_JAVA_MIDP_SECURITY_DOMAIN
CKA_AUTH_PIN_FLAGS CKA_VENDOR_DEFINED时;
CK_VOID_PTR 是一个CK_ULONG类型数据的首地址,转换过程如下:
(1)获取long类;
在本实施例中,通过调用jclass jLongClass = (*env)-> FindClass(env, “java/lang/Long”)获取long类;
(2)获取初始化函数;
在本实施例中,通过调用jmethodID jConstructor = (*env)->GetMethodID(env, jValueObjectClass, "<init>", "(J)V");获取初始化函数;
(3)创建类的实例,并为之赋值;
在本实施例中,通过强制类型转换,将CK_VOID_PTR类型的pValue转换为jlong类型的jValue;
jlong jValue = (jlong)(*pTemplate[n].pValue);
通过调用jobject jValueObject = (*env)->NewObject(env, jValue ObjectClass, jConstructor, jValue)为jValueObject赋值;
2、当type为:
CKA_VALUE
CKA_OBJECT_ID
CKA_SUBJECT
CKA_ID
CKA_ISSUER
CKA_SERIAL_NUMBER
CKA_OWNER
CKA_AC_ISSUER
CKA_ATTR_TYPES
CKA_ECDSA_PARAMS
CKA_EC_POINT
CKA_PRIVATE_EXPONENT
CKA_PRIME_1
CKA_PRIME_2
CKA_EXPONENT_1
CKA_EXPONENT_2
CKA_COEFFICIENT
CKA_CHECK_VALUE
CKA_HASH_OF_SUBJECT_PUBLIC_KEY
CKA_HASH_OF_ISSUER_PUBLIC_KEY
CKA_MODULUS
CKA_PUBLIC_EXPONENT
CKA_PRIME
CKA_SUBPRIME
CKA_BASE时:
CK_VOID_PTR 是一个CK_BYTE数组的首地址,转换过程如下:
(1)CK_BYTE[]转换为jbyte*类型;
具体的,
通过调用jbyte* jpTemp = (jbyte*) malloc(sizeof (pTemplate[n].length) * sizeof(jbyte))和for (int i=0; i<sizeof(pTemplate[n].length); i++) {jpTemp[i] = (jbyte) ((CK_BYTE[])(pTemplate[n].pValue)[i]);}将CK_BYTE[]进行循环转换为jbyte*类型;
(2)通过JNI参数列表中的JNIEnv *env,将jbyte*类型数据转变为jbyteArray类型的数据;
具体的:
通过调用jbyteArray jArray = (*env)->NewByteArray(env, jsize(pTemplate[n].length * sizeof(jbyte)));为jArray 分配缓冲区,然后通过调用(*env)->SetCharArrayRegion(env, jArray,0, jsize(pTemplate[n].length * sizeof(jbyte)), jpTemp);将jbyte*的内容转存至jArray的缓冲区中;
所述jbyteArray 类型的jArray 即为 jValueObject;
也就是jValueObject=(jobject)jArray;
3、当type为:
CKA_RESET_ON_INIT
CKA_HAS_RESET
CKA_TOKEN
CKA_PRIVATE
CKA_MODIFIABLE
CKA_DERIVE
CKA_LOCAL
CKA_ENCRYPT
CKA_VERIFY
CKA_VERIFY_RECOVER
CKA_WRAP
CKA_SENSITIVE
CKA_SECONDARY_AUTH
CKA_DECRYPT
CKA_SIGN
CKA_SIGN_RECOVER
CKA_UNWRAP
CKA_EXTRACTABLE
CKA_ALWAYS_SENSITIVE
CKA_NEVER_EXTRACTABLE
CKA_TRUSTED
CKA_WRAP_WITH_TRUSTED
CKA_ALWAYS_AUTHENTICATE时:
(1)获取boolean类;
在本实施例中,通过调用jclass jValueObjectClass = (*env)->FindClass(env, "java/lang/Boolean")获取boolean类;
(2)获取初始化函数;
在本实施例中,通过调用jmethodID jConstructor = (*env)->GetMethodID(env, jValueObjectClass, "<init>", "(Z)V")获取初始化函数;
(3)创建类的实例,并为之赋值;
在本实施例中,通过调用
jboolean jValue = (*(CK_BBOOL)pTemplate[i].pValue == TRUE) ? JNI_TRUE : JNI_FALSE;和jobject jValueObject = (*env)-> NewObject(env, jValueObjectClass, jConstructor,jValue);创建类的实例并赋值;
4、当type为:
CKA_LABEL
CKA_APPLICATION
CKA_URL时:
CK_VOID_PTR 是一个CK_CHAR数组的首地址,转换过程如下:
(1)CK_CHAR[]转换为jbyte*类型;
具体的,
通过调用jchar* jpTemp = (jchar*) malloc(sizeof (pTemplate[n].length) * sizeof(jchar))和for (int i=0; i<sizeof(pTemplate[n].length); i++) {jpTemp[i] = (jbyte) ((CK_CHAR[])(pTemplate[n].pValue)[i]);}将CK_CHAR[]进行循环转换为jchar*类型;
(2)通过JNI参数列表中的JNIEnv *env,将jbyte*类型数据转变为jcharArray类型的数据;
具体的:
通过调用jcharArray jArray = (*env)->NewByteArray(env, jsize(pTemplate[n].length * sizeof(jchar)));为jArray 分配缓冲区,然后通过调用(*env)->SetCharArrayRegion(env, jArray,0, jsize(pTemplate[n].length * sizeof(jchar)), jpTemp);将jchar*的内容转存至jArray的缓冲区中;
所述jcharArray 类型的jArray 即为 jValueObject;
也就是jValueObject=(jobject)jArray;
5、当type为:
CKA_START_DATE
CKA_END_DATE时:
CK_VOID_PTR 为CK_DATE类型的数据,
其中,CK_DATE下层返回的结构为:
(1)通过调用JNI参数列表中的JNIENV *env,获取调用方的CK_DATE类;
在本实施例中,通过调用jclass jValueObjectClass = (*env)->FindClass(env, "pkcs11/wrapper/CK_DATE");获取CK_DATE类;
(2)通过JNI参数列表中的JNIENV *env,创建CK_DATE类的实例;
在本实施例中,通过调用jobject jValueObject = (*env)-> AllocObject(env, jValueObjectClass)创建CK_DATE类的实例;
(3)通过JNI参数列表中的JNIENV *env,将下层接口返回的内容传给所述类的实例jValueObject;
A、获取预定的成员变量在类的实例中的属性编号;
在本实施例中,通过调用:
fieldID1 = (*env)->GetFieldID(env, jValueObjectClass, "year", "[C");
fieldID2 = (*env)->GetFieldID(env, jValueObjectClass, "month", "[C");
fieldID3 = (*env)->GetFieldID(env, jValueObjectClass, "day", "[C"),获取成员变量的属性编码;
以 CK_DATE的year成员转换为例来说明:
(1) 将CK_CHAR[] 类型的year转换为jbyte*类型;
具体的,
通过调用jchar* jpTemp = (jchar*) malloc(4 * sizeof(jchar))和for (int i=0; i<4; i++) {jpTemp[i] = (jbyte) (((CK_DATE)(pTemplate[n].pValue).year[i]) );}将CK_CHAR[]进行循环转换为jchar*类型;
(2)通过JNI参数列表中的JNIEnv *env,将jbyte*类型数据转变为jcharArray类型的数据;
具体的:
通过调用jcharArray jArray = (*env)->NewByteArray(env, jsize(pTemplate[n].length * sizeof(jchar)));为jArray 分配缓冲区,然后通过调用(*env)->SetCharArrayRegion(env, jArray,0, jsize(pTemplate[n].length * sizeof(jchar)), jpTemp);将jchar*的内容转存至jArray的缓冲区中;
将jArray的数据存入缓冲区jValueObject中:
具体地,通过调用(*env)->SetObjectField(env, jValueObject,fieldID1 , jArray) 将jArray的数据存入缓冲区jValueObject中;
步骤510-5:将上述的jValueObject存入缓冲区jAttribute中;
通过调用(*env)->SetObjectField(env, jAttribute , fieldID,jValueObject);将转换后的结果jValueObject传递给jAttribute;
步骤510-6:通过调用return方法,将创建的类的实例jAttribute返回。
实施例6
本发明实施例6提供了一种java访问智能密钥装置的方法,包括:
本实施例以利用智能密钥装置内部对象生成数字签名的方法为例来说明:
当预定的接口public native byte[] C_Sign(long hSession,byte[] pData) throws PKCS11Exception; 被调用时
步骤601:JNI接口获取源参数列表;
具体的,当预定的接口public native byte[] C_Sign(long hSession, byte[] pData) throws PKCS11Exception被调用时,java通过JNI技术调用JNI接口函数:JNIEXPORT jbyteArray JNICALLJava_pkcs11_wrapper_PKCS11 Implementation _C_1Sign(JNIEnv*env, jobject obj, jlong jSessionHandle, jbyteArray jData),其中接口名中的pkcs11_wrapper_PKCS11Implementation为预定的接口在调用方工程中的路径,即预定的接口在调用方在包名为pkcs11.wrapper的PKCS11Implementation类中;获取到的参数列表为JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArrayjData,其中,JNIEnv *env, jobject obj是JNI接口添加的参数,用于在JNI层操作java数据,或者用于创建java数据对象以及对java数据对象赋值,真正的源参数列表是jlong jSessionHandle, jbyteArray jData;
步骤602:根据预设JNI接口函数与下层接口函数的对应表,确定与JNI接口函数对应的下层接口函数;
在本实施例中,所述下层接口函数是:
步骤603:根据所述下层接口函数确定目标参数列表;
在本实施例中,目标参数列表是:CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTRpSignature, CK_ULONG_PTR pulSignatureLen  ;
步骤604:将源参数列表中预定义本地类型的参数转换为下层接口可识别的类型;
具体的,
根据所述第一预设映射表,将jlong 类型的jSessionHandle强制转换为CK_SESSION_HANDLE类型的 hSession;
步骤605:将所述源参数列表中预定义引用类型的参数转换为下层接口可识别的类型;
具体的,
根据所述第二预设映射表,将jbyteArray 类型的jData转换为CK_BYTE_PTR类型的pData和参数jData的长度ulDataLen;
具体包括:
步骤605-1:获取参数jData的长度,并根据参数的长度分配存储空间;
在本实施例中,通过调用CK_ULONG ulDataLen = (*env)->Get ArrayLength(env, jData)获取参数jData长度,并通过调用CK_BYTE_PTR pData = (CK_BYTE_PTR) malloc(ulDataLen * sizeof(byte))为参数pData分配缓冲区;
步骤605-2:将jbyteArray类型转换为jbyte*类型的jpTemp;
具体的,
为jpTemp 分配缓冲区,通过调用 jpTemp = (jbyte*)malloc ((ulDataLen ) * sizeof(jbyte));
通过JNI参数列表中的JNIEnv *env,将jbyteArray数据转存到jpTemp中,通过调用 (*env)->GetByteArrayRegion(env, jArray, 0,ulDataLen , jpTemp);
步骤605-3:将jbyte*的jpTemp 转换为CK_BYTE_PTR的 pData;
具体地,
通过调用 for (int i=0; i<ulDataLen ; i++) {pData[i]= (CK_BYTE)jbyte[i];}来转换;
步骤606:根据预先约定的大小分配缓冲区;
具体的,在本实施例中,此时仅为返回长度分配缓冲区,返回值缓冲区暂不分配,即返回值首地址为NULL_PTR,也就有;
CK_BYTE_PTR pSignRet = NULL_PTR;
CK_ULONG ulSignRetLen = 0;
步骤607:调用下层接口,访问智能密钥装置,得到返回结果;
具体的,
在实施例中,通过调用CK_RV rv = C_Sign(hSession, pData,ulDataLen,pSignRet ,&ulSignRetLen)将步骤602中CK_SESSION_HANDLE hSession、CK_BYTE_PTR pData、CK_ULONG ulDataLen、和 返回值首地址pSignRet与返回长度的首地址&ulSignRetLen;
步骤608:判断所述返回结果是否正确,如果是,则执行步骤609,否则抛出异常,结束;
具体的,
如果下层接口的返回值不是预先预定的“成功”,则将下层接口的返回值通过抛出异常的方式返回给调用方,否则,将下层接口的返回值以及所述缓冲区中的内容返回给调用方;
具体的,抛出异常的方式为:
S1:通过JNI参数列表中的JNIEnv *env,获取调用方异常类;
具体地,以PKCS11Exception异常类为例:
通过调用jclass errClass = (*env)->FindClass(env, “pkcs11/wrapper/PKCS11Exception”)获取调用方异常类,其中" pkcs11/wrapper/PKCS11Exception "为异常类PKCS11Exception在调用方工程中的路径;
S2:通过JNI参数列表中的JNIEnv *env,实例化调用方异常;
具体地,通过调用jmethodID jConstructor = (*env)-> GetMethodID(env,errClass, "<init>", "()V")来获取预定的异常类的构造函数,其中"<init>"表示是够着函数,"()V"表示参数与返回值类型,errClass为上述S1中获取;
通过调用jthrowable jOutOfError = (jthrowable) (*env)->NewObject(env, errClass, jConstructor)将调用方异常类实例化;
具体地,errClass由S1中获取,jConstructor即上述调用GetMethodID获取得到;
S3:通过JNI参数列表中的JNIEnv *env,为调用方抛出异常;
具体地,通过调用(*env)->Throw(env, jOutOfError)将异常抛出,由调用方接收;其中jOutOfError由S2中获取;
步骤609:通过下层接口返回的长度,为pSignRet 分配缓冲区;
通过调用 pSignRet = (CK_BYTE_PTR)malloc (ulSignRetLen *sizeof(CK_BYTE))来分配缓冲区;
步骤610:调用下层接口,访问智能密钥装置,得到返回结果
步骤611:判断所述返回结果是否正确,如果是,则执行步骤612,否则抛出异常,结束;
其中,抛出异常与上述抛出异常的具体方式是相同的,在此不再赘述;
步骤612:将所述返回结果转换为JNI接口类型,并返回;
具体的,转换过程如下:
步骤612-1:将CK_BYTE类型转换为jbyte*类型;
具体的,
通过调用jbyte* jpTemp = (jbyte*) malloc(ulSignRetLen *sizeof (jbyte))和for (int i=0; i< ulSignRetLen ; i++){jpTemp[i] =(jbyte)pSignRet[i];}
步骤612-2:通过JNI参数列表中的JNIEnv *env,将jbyte*类型数据转变为jbyteArray类型的数据;
通过调用jbyteArray jArray = (*env)->NewbyteArray(env,jsize (ulSignRetLen*sizeof(jbyte)))为jArray 分配缓冲区,然后通过调用(*env)->SetbyteArrayRegion(env, jArray, 0, jsize(ulSignRetLen*sizeof (jbyte)), jpTemp)将jbyte*的内容转存至jArray 的缓冲区中;
步骤612-3:通过调用return 方法,将所述jbyteArray类型的jArray 返回给调用方。
以上所述,仅为本发明较佳的具体实施方式,但本发明的保护范围并不局限于此,任何熟悉本技术领域的技术人员在本发明公开的技术范围内,可轻易想到的变化或替换,都应涵盖在本发明的保护范围之内。因此,本发明的保护范围应该以权利要求的保护范围为准。

Claims (12)

1.一种java应用访问智能密钥装置的方法,其特征在于,包括:java应用调用JNI接口,所述JNI接口执行以下操作:
步骤101:JNI接口获取JNI接口函数被调用时的源参数列表;
步骤102:根据预设JNI接口函数与下层接口函数的对应表,确定与JNI接口函数对应的下层接口函数;
步骤103:根据所述下层接口函数确定目标参数列表;
步骤104:根据下层接口的目标参数列表,将所述源参数列表的值传递给相应的下层接口参数;
步骤105:调用所述下层接口,访问智能密钥装置,得到返回结果;
步骤106:将所述得到的返回结果返回给调用方或抛出异常,结束。
2.根据权利要求1所述的方法,其特征在于,
所述步骤102中,所述预设JNI接口函数与下层接口函数的对应表中包括多个一一对应的接口函数对,其中每个接口函数对中包含一个JNI接口函数与一个与所述JNI接口函数对应的下层接口函数,当JNI接口函数被调用时,根据所述预设JNI接口函数与下层接口函数的对应表查找到对应的下层接口函数。
3.根据权利要求1所述的方法,其特征在于,
所述步骤104中:
如果下层接口需要的类型是预定义简单类型,则:
根据下层接口需要的预定义简单类型,根据源参数列表中的预定义本地类型的参数,查询第一预设映射表,获取所述第一预设映射表中包含所述预定义本地类型的参数的类型对,得到与所述预定义本地类型对应的下层接口函数需要的预定义简单类型,通过强制类型转换,得到下层接口需要的参数。
4.根据权利要求1所述的方法,其特征在于,
所述步骤104中:
如果下层接口函数需要的类型是复合类型,则:
根据下层接口需要的预定义复合类型,根据源参数列表中的预定义引用类型的参数,查询第二预设映射表,获取所述第二预设映射表中包含所述预定义引用类型的参数类的型对,得到与所述预定义引用类型对应的下层接口函数需要的预定义复合类型。
5.根据权利要求4所述的方法,其特征在于,
所述步骤104具体包括:
步骤104-1:获取所述源参数列表中所述预定义引用类型的参数的长度,并根据参数长度分配第一缓冲区;
步骤104-2:将所述源参数列表中所述预定义引用类型的参数转存至所述第一缓冲区中;
步骤104-3:在所述下层接口中为转存后的数据分配第二缓冲区;
步骤104-4:将所述转存后的数据存入所述第二缓冲区中。
6.根据权利要求1所述的方法,其特征在于,
所述步骤106具体包括:
步骤106-1:判断所述返回结果是否正确,如果是,则执行步骤106-2,否则抛出异常,结束;
步骤106-2:将所述返回结果的值返回给调用方。
7.根据权利要求6所述的方法,其特征在于,
所述步骤106-1具体为:
判断下层结果的返回结果是否是预定义的“成功”,如果是,则表示返回结果正确,执行步骤106-2,否则表示返回结果错误,抛出异常,结束。
8.根据权利要求1或6或7中任意一项所述的方法,其特征在于,
所述抛出异常具体包括:
A:根据源参数列表中的参数,获取调用方异常类;
B:根据源参数列表中的参数,实例化调用方异常;
C:根据源参数列表中的参数,为调用方抛出异常。
9.根据权利要求1所述的方法,其特征在于,
所述步骤106中将所述得到的返回结果返回给调用方,具体包括:
S1:获取调用方的类;
S2:创建所述类的实例;
S3:将所述下层接口返回的内容传给所述类的实例;
S4:将所述创建的类的实例返回给调用方。
10.根据权利要求9所述的方法,其特征在于,
所述步骤S3包括:
步骤S3-1:获取预定的成员变量在存储所述类的实例的缓冲区的首地址;
步骤S3-2:根据所述下层接口返回内容的预定的成员变量的类型与调用方的结构的成员变量类型,将下层接口返回内容的类型转换成为JNI接口类型;
步骤S3-3:将转换后的内容传递给所述类的实例。
11.根据权利要求1所述的方法,其特征在于,
所述步骤106中将所述的得到的返回结果返回给调用方,具体包括:
如果所述下层接口返回内容的类型是预定义简单类型,则根据第一预设映射表,将所述预定义简单类型的参数,通过强制类型转换得到JNI接口类型,然后将得到的JNI接口类型的值返回给调用方;
如果所述下层接口返回内容的类型是预定义复合类型,则根据第二预设映射表,将所述预定义引用类型的参数转换为JNI接口类型,然后将得到的JNI接口类型的值返回给调用方。
12.根据权利要求11所述的方法,其特征在于,
如果下层接口的返回内容的类型是预定义复合类型,根据所述第二预设映射表,将所述预定义引用类型的参数转换为JNI接口类型,然后将得到的JNI接口类型的值返回给调用方,具体包括:
步骤B1:获取所述下层接口的返回内容的长度,并根据所述长度分配第三缓冲区;
步骤B2:将所述下层接口的返回内容转存至所述第三缓冲区中;
步骤B3:在JNI接口中为转存后的数据分配第四缓冲区;
步骤B4:将所述转存后的数据存入所述第四缓冲区中。
CN201210580998.8A 2012-12-27 2012-12-27 一种java应用访问智能密钥装置的方法 Active CN103093136B (zh)

Priority Applications (3)

Application Number Priority Date Filing Date Title
CN201210580998.8A CN103093136B (zh) 2012-12-27 2012-12-27 一种java应用访问智能密钥装置的方法
PCT/CN2013/087916 WO2014101610A1 (zh) 2012-12-27 2013-11-27 一种java应用访问智能密钥装置的方法
US14/394,593 US9824201B2 (en) 2012-12-27 2013-11-27 Method for java application to access intelligent key apparatus

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN201210580998.8A CN103093136B (zh) 2012-12-27 2012-12-27 一种java应用访问智能密钥装置的方法

Publications (2)

Publication Number Publication Date
CN103093136A CN103093136A (zh) 2013-05-08
CN103093136B true CN103093136B (zh) 2015-05-27

Family

ID=48205694

Family Applications (1)

Application Number Title Priority Date Filing Date
CN201210580998.8A Active CN103093136B (zh) 2012-12-27 2012-12-27 一种java应用访问智能密钥装置的方法

Country Status (3)

Country Link
US (1) US9824201B2 (zh)
CN (1) CN103093136B (zh)
WO (1) WO2014101610A1 (zh)

Families Citing this family (10)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN103093136B (zh) * 2012-12-27 2015-05-27 飞天诚信科技股份有限公司 一种java应用访问智能密钥装置的方法
CN104407864B (zh) * 2014-11-25 2018-02-02 广东欧珀移动通信有限公司 一种jni层的算法进行多实例调用的封装方法和系统
CN105446735A (zh) * 2015-11-11 2016-03-30 上海斐讯数据通信技术有限公司 一种Java与Windows消息传递方法及系统
CN105653319B (zh) * 2015-12-25 2018-11-23 飞天诚信科技股份有限公司 一种自动向应用程序加载pkcs#11模块的方法及装置
CN107317867B (zh) * 2017-07-03 2021-04-06 飞天诚信科技股份有限公司 一种通过网页脚本访问智能密钥设备的方法及系统
CN108536492B (zh) * 2018-04-08 2021-09-07 武汉斗鱼网络科技有限公司 一种直播间属性信息获取方法、装置、设备及存储介质
CN109995526A (zh) * 2019-04-10 2019-07-09 睿驰达新能源汽车科技(北京)有限公司 一种密钥的存储方法和装置、密钥的调用方法和装置
CN111049654B (zh) * 2019-11-11 2024-08-13 北京握奇智能科技有限公司 一种银行USBKey证书申请防篡改保护方法及系统
CN113835989A (zh) * 2020-06-08 2021-12-24 武汉斗鱼鱼乐网络科技有限公司 一种性能统计方法和装置
CN115080006A (zh) * 2021-03-15 2022-09-20 武汉斗鱼网络科技有限公司 一种数据调用方法及相关设备

Citations (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN1746844A (zh) * 2005-09-29 2006-03-15 浪潮电子信息产业股份有限公司 一种跨操作系统平台的机群系统监控和管理方法
CN101814124A (zh) * 2010-04-20 2010-08-25 浪潮电子信息产业股份有限公司 一种基于Java的软件安全性加强的方法
CN102043932A (zh) * 2010-12-31 2011-05-04 中国航空工业集团公司第六三一研究所 一种防止Java程序被反编译的方法
CN102708322A (zh) * 2012-05-12 2012-10-03 北京深思洛克软件技术股份有限公司 安卓系统中java应用程序的保护方法

Family Cites Families (10)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US7392937B1 (en) * 1999-12-03 2008-07-01 Diebold, Incorporated Card reading arrangement involving robotic card handling responsive to card sensing at a drive-up automated banking machine
US6901588B1 (en) * 2000-04-17 2005-05-31 Codemesh, Inc. Sharing components between programming languages by use of polymorphic proxy
US6934946B2 (en) * 2001-05-15 2005-08-23 Sun Microsystems, Inc. Lightweight native method invocation interface for java computing environments
US8995663B2 (en) * 2010-03-31 2015-03-31 Feitian Technologies Co., Ltd. Method for implementing an encryption engine by smart key device
CN101883122B (zh) * 2010-07-30 2012-12-05 迈普通信技术股份有限公司 安全连接创建方法以及用于创建安全连接的客户端设备
KR101320618B1 (ko) 2010-12-21 2013-10-23 주식회사 케이티 스마트키 관리 방법 및 장치
CN102111660B (zh) * 2011-03-28 2012-11-28 博视联(苏州)信息科技有限公司 交互式智能网络电视
CN103827880B (zh) * 2011-03-31 2017-06-16 爱迪德技术有限公司 保护非本机代码安全的方法
CN102662842B (zh) * 2012-04-11 2016-02-03 贵州航天风华精密设备有限公司 一种基于Java平台的航天器测试软件构架及其测试方法
CN103093136B (zh) * 2012-12-27 2015-05-27 飞天诚信科技股份有限公司 一种java应用访问智能密钥装置的方法

Patent Citations (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN1746844A (zh) * 2005-09-29 2006-03-15 浪潮电子信息产业股份有限公司 一种跨操作系统平台的机群系统监控和管理方法
CN101814124A (zh) * 2010-04-20 2010-08-25 浪潮电子信息产业股份有限公司 一种基于Java的软件安全性加强的方法
CN102043932A (zh) * 2010-12-31 2011-05-04 中国航空工业集团公司第六三一研究所 一种防止Java程序被反编译的方法
CN102708322A (zh) * 2012-05-12 2012-10-03 北京深思洛克软件技术股份有限公司 安卓系统中java应用程序的保护方法

Also Published As

Publication number Publication date
US20150294102A1 (en) 2015-10-15
US9824201B2 (en) 2017-11-21
CN103093136A (zh) 2013-05-08
WO2014101610A1 (zh) 2014-07-03

Similar Documents

Publication Publication Date Title
CN103093136B (zh) 一种java应用访问智能密钥装置的方法
CN104104517B (zh) 一次性密码验证的方法和系统
CN102904712B (zh) 信息加密方法
CN1889432A (zh) 基于智能卡的口令远程认证方法、智能卡、服务器和系统
CN1661961A (zh) 用于鉴权的方法、硬件标志及计算机
CN1221900C (zh) 动态电子密码设备及其资源共享系统的用户身份认证方法
CN1614924A (zh) 基于智能卡和动态密码的身份认证系统
EP3552131B1 (en) Password security
CN209803788U (zh) 一种pcie可信密码卡
CN1731723A (zh) 电子/手机令牌动态口令认证系统
CN107294710B (zh) 一种vTPM2.0的密钥迁移方法及装置
CN110620763B (zh) 一种基于移动端app的移动身份认证方法及系统
EP1673674A2 (en) Maintaining privacy for transactions performable by a user device having a security module
CN107454048A (zh) 信息的处理方法及装置、信息的认证方法、装置及系统
CN103152425A (zh) 基于云技术的移动设备的安全管理系统
CN2609069Y (zh) 指纹数字签名器
CN106790243B (zh) 一种安全u盘的密码重置方法
CN101102192A (zh) 认证设备、方法和系统
CN103259665A (zh) 电子签章方法及系统
Alzomai et al. The mobile phone as a multi OTP device using trusted computing
CN114499859A (zh) 密码验证方法、装置、设备及存储介质
CN101355424B (zh) 一种手持设备数据安全迁移的方法
CN200983153Y (zh) 具有按键的加密签名手写板
CN104333450B (zh) 一种可信自助服务系统的建立方法
CN203151519U (zh) 动态口令显示系统

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
C14 Grant of patent or utility model
GR01 Patent grant
CP03 Change of name, title or address
CP03 Change of name, title or address

Address after: 17th floor, building B, Huizhi building, No.9, Xueqing Road, Haidian District, Beijing 100085

Patentee after: Feitian Technologies Co.,Ltd.

Country or region after: China

Address before: 100085 17th floor, block B, Huizhi building, No.9 Xueqing Road, Haidian District, Beijing

Patentee before: Feitian Technologies Co.,Ltd.

Country or region before: China