如何通过JNA接口从SoftHSM提取对象?模板匹配异常排查
问题:SoftHSM中JNA调用C_FindObjects返回空对象句柄
我在开发Java应用提取SoftHSM中的对象,已成功打开令牌会话,且存在标签为"MY_DATA"的Data对象。调用C_FindObjects后objectHandles始终为空(ulObjectCount=0),无错误返回码;使用空模板能正常获取句柄列表,推测问题出在搜索模板的类型定义上。
我的Java/JNA实现代码
String dataLabel = "MY_DATA"; CK_ATTRIBUTE[] searchTemplate = (CK_ATTRIBUTE[]) new CK_ATTRIBUTE().toArray(2); searchTemplate[0].type = new NativeLong(Pkcs11Library.CKA_LABEL); // long CKA_LABEL = 0x00000003 byte[] labelBytes = dataLabel.getBytes(); searchTemplate[0].pValue = new Memory(labelBytes.length); searchTemplate[0].pValue.write(0, labelBytes, 0, labelBytes.length); searchTemplate[0].ulValueLen = new NativeLong(labelBytes.length); searchTemplate[1].type = new NativeLong(Pkcs11Library.CKA_CLASS); // long CKA_CLASS = 0x00000000 searchTemplate[1].pValue = new Memory(NativeLong.SIZE); searchTemplate[1].pValue.setNativeLong(0, new NativeLong(Pkcs11Library.CKO_DATA)); // long CKO_DATA = 0x00000000 searchTemplate[1].ulValueLen = new NativeLong(NativeLong.SIZE); int rv = Pkcs11Library.INSTANCE.C_FindObjectsInit(hSession, searchTemplate, searchTemplate.length); if (rv != Pkcs11Library.CKR_OK) { //TODO } int[] objectHandles = new int[MAX_OBJECT_COUNT]; // MAX_OBJECT_COUNT = 10 NativeLongByReference pulObjectCount = new NativeLongByReference(); rv = Pkcs11Library.INSTANCE.C_FindObjects(hSession, objectHandles, objectHandles.length, pulObjectCount); int ulObjectCount = pulObjectCount.getValue().intValue();
JNA接口定义
// CK_ATTRIBUTE public class CK_ATTRIBUTE extends Structure { public NativeLong type; public Pointer pValue; public NativeLong ulValueLen; public CK_ATTRIBUTE() { super(); } @Override protected List<String> getFieldOrder() { return Arrays.asList("type", "pValue", "ulValueLen"); } } int C_FindObjectsInit(int hSession, CK_ATTRIBUTE[] searchTemplate, int length); int C_FindObjects(int hSession, int[] phObject, int ulMaxObjectCount, NativeLongByReference pulObjectCount);
SoftHSM原生C定义
struct ck_attribute { ck_attribute_type_t type; void *value; unsigned long value_len; }; CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount);
运行环境
- Windows x64
- OpenJDK17
- SoftHSMv2 x64 DLL
解决方案
- 统一字符串编码
SoftHSM中对象标签默认以UTF-8存储,而dataLabel.getBytes()会使用平台默认编码(Windows下为GBK),导致匹配失败。修改为显式指定UTF-8:
byte[] labelBytes = dataLabel.getBytes(StandardCharsets.UTF_8);
- 修正对象句柄类型
Windows x64平台下,CK_OBJECT_HANDLE是64位无符号整数,原代码用int[]存储会造成截断。需改为NativeLong[]存储句柄,并更新JNA接口:
// 调用代码修改 NativeLong[] objectHandles = new NativeLong[MAX_OBJECT_COUNT]; for (int i = 0; i < MAX_OBJECT_COUNT; i++) { objectHandles[i] = new NativeLong(0); } // JNA接口定义修改 int C_FindObjects(int hSession, NativeLong[] phObject, NativeLong ulMaxObjectCount, NativeLongByReference pulObjectCount);
- 验证属性值的字节长度
CKA_CLASS对应的CKO_DATA是32位枚举值,原代码用NativeLong.SIZE(x64下为8)作为长度,与SoftHSM的32位存储不匹配。改为固定4字节:
searchTemplate[1].pValue = new Memory(4); searchTemplate[1].pValue.setInt(0, (int)Pkcs11Library.CKO_DATA); searchTemplate[1].ulValueLen = new NativeLong(4);
- 检查会话权限
确认打开会话时是否指定了CKF_RW_SESSION,部分HSM要求读写会话才能完整访问对象属性。
内容的提问来源于stack exchange,提问作者tamar_a_roulettes
相关产品推荐
相关产品推荐

