You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

解决方案

  1. 统一字符串编码
    SoftHSM中对象标签默认以UTF-8存储,而dataLabel.getBytes()会使用平台默认编码(Windows下为GBK),导致匹配失败。修改为显式指定UTF-8:
byte[] labelBytes = dataLabel.getBytes(StandardCharsets.UTF_8);
  1. 修正对象句柄类型
    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);
  1. 验证属性值的字节长度
    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);
  1. 检查会话权限
    确认打开会话时是否指定了CKF_RW_SESSION,部分HSM要求读写会话才能完整访问对象属性。

内容的提问来源于stack exchange,提问作者tamar_a_roulettes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 07:14:54