java - 在 JNA 中创建对象 C_CreateObject 时会发生奇怪的事情 [PKCS11]

标签 java swing jna pkcs#11

我正在制作 JNA PKCS11 包装器,在 token 中创建对象时发生了奇怪的事情(使用 CKO_DATA 和 CKO_CERTIFICATE 进行测试)。大多数情况下结果是CKR_TEMPLATE_INCONSISTENT,多次尝试后即可创建对象。也许你知道会发生什么。

JNA 接口(interface)和结构,

NativeLong C_CreateObject(final NativeLong hSession, final CK_ATTRIBUTE[] pTemplate, final NativeLong ulCount, final IntByReference phObject);

public class CK_ATTRIBUTE extends Structure {
    public NativeLong type;
    public Pointer pValue;
    public NativeLong ulValueLen;

    public static class ByReference extends CK_ATTRIBUTE implements Structure.ByReference {
    }

    public static class ByValue extends CK_ATTRIBUTE implements Structure.ByValue {
    }

    public CK_ATTRIBUTE() {
        setAlignType(ALIGN_NONE);
    }

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList(new String[] { "type", "pValue", "ulValueLen" });
    }
}

包装器,

public class Attribute {
    private final CKA cka;
    private final byte[] data;

    public Attribute(final CKA cka, final byte[] data) {
        this.cka = cka;
        this.data = data.clone();
    }

    public CKA getCKA() {
        return cka;
    }

    public byte[] getData() {
        return data;
    }
}

public static CK_ATTRIBUTE[] createNativeAttributes(final List<Attribute> attributes) {
    final CK_ATTRIBUTE[] nativeAttributes = (CK_ATTRIBUTE[]) new CK_ATTRIBUTE().toArray(attributes.size());
    for (int i = 0; i < attributes.size(); i++) {
        final Attribute attribute = attributes.get(i);
        nativeAttributes[i].type = attribute.getCKA().getValue();
        final int len = attribute.getData().length;
        final Pointer pointer = new Memory(len);
        nativeAttributes[i].pValue = pointer;
        pointer.write(0, attribute.getData(), 0, len);
        nativeAttributes[i].ulValueLen = new NativeLong(len);
    }
    return nativeAttributes;
}

public NativeLong createObject(final NativeLong hSession, final CK_ATRIBUTE[] pTemplate) throws CryptokiException {
    if (hSession == null) {
        throw new IllegalArgumentException("hSession cannot be null");
    }
    if (pTemplate == null || pTemplate.length == 0) {
       throw new IllegalArgumentException("pTemplate cannot be empty");
    }
    final IntByReference phObject = new IntByReference(0);
    generateException(cryptoki.C_CreateObject(hSession, pTemplate, new NativeLong(pTemplate.length), phObject));
    return new NativeLong(phObject.getValue());
}

测试片段,

// create CKO_DATA
final List<Attribute> attributes = new ArrayList<>();
attributes.add(new Attribute(CKA.CLASS, new byte[] { CKO.DATA.getValue().byteValue() }));
attributes.add(new Attribute(CKA.TOKEN, new byte[] { Cryptoki.CK_TRUE }));
attributes.add(new Attribute(CKA.APPLICATION, "My Application".getBytes()));
attributes.add(new Attribute(CKA.VALUE, new byte[] { 0x01, 0x02, 0x03, 0x04 }));
attributes.add(new Attribute(CKA.LABEL, "Test Label".getBytes()));
final CK_ATTRIBUTE[] pTemplate = CryptokiWrapper.createNativeAttributes(attributes);
final NativeLong hObject = wrapper.createObject(hSessionRW, pTemplate);

// create CKO_CERTIFICATE
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
try (final InputStream inputStream = new FileInputStream("src/main/resources/test.cer")) {
    final X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream);
    final List<Attribute> attributes = new ArrayList<>();
    attributes.add(new Attribute(CKA.CLASS, new byte[] { CKO.CERTIFICATE.getValue().byteValue() }));
    attributes.add(new Attribute(CKA.CERTIFICATE_TYPE, new byte[] { CKC.X_509.getValue().byteValue() }));
    attributes.add(new Attribute(CKA.TOKEN, new byte[] { Cryptoki.CK_TRUE }));
    attributes.add(new Attribute(CKA.LABEL, "Test Cert".getBytes()));
    attributes.add(new Attribute(CKA.SUBJECT, x509Certificate.getSubjectDN().getName().getBytes()));
    attributes.add(new Attribute(CKA.ID, new byte[] { 0x01, 0x02 }));
            attributes.add(new Attribute(CKA.VALUE, x509Certificate.getEncoded()));
    final CK_ATTRIBUTE[] pTemplate = CryptokiWrapper.createNativeAttributes(attributes);
    final NativeLong hObject = wrapper.createObject(hSessionRW, pTemplate);
}

如果在 Debug模式下运行应用程序并设置一些断点,成功的可能性会更高。

注意,所有代码都在单个线程下运行。

最佳答案

终于找到这个问题的原因了,

 attributes.add(new Attribute(CKA.CLASS, new byte[] {  CKO.DATA.getValue().byteValue() }));

这行是错误的,CKO_DATA的值为0x00000000,这意味着它是一个32位整数,所以它的长度是4,并且该值是一个字节数组;经过一些测试,该值是一个小端序列。

有时方法执行成功的原因是,有时内存中的序列是00 00 00 00,符合方法的要求,尤其是在 Debug模式下。

关于java - 在 JNA 中创建对象 C_CreateObject 时会发生奇怪的事情 [PKCS11],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35933258/

相关文章:

struct - 在 JNA 中映射联合内的结构

java - Web应用程序中的配置参数(Java+Spring+Hibernate+Tapestry)

java - 调整大小后 JLabel 文本在 JPanel 中消失

Java JPanel getGraphics() 函数

java - JNA 库和 native 库未找到错误

c# - 什么等同于 Java 中的 IntPtr (C#)?

java - 计算 Frog 到达河对岸所需的最少跳跃次数

java - java如何处理整数上溢和下溢?

java - 没有同时监视文件夹

java - 使用 GridBagLayout() 将按钮与右中对齐