PeculiarVentures / node-webcrypto-p11

A WebCrypto Polyfill for Node in typescript built on PKCS#11.
MIT License
44 stars 15 forks source link

Unable to get certificate from HSM device #43

Closed ENDaZONELT closed 5 years ago

ENDaZONELT commented 6 years ago

Certificate is stored on HSM device and I need to get it for signing. But when I try to do that an error message occurs.

import * as xadesjs from 'xadesjs';
import { WebCrypto } from 'node-webcrypto-p11';

async function test() {

    const cryptoConfig = {
        library: "/home/app/src/lib/pkcs11.so",
        name: "Ultimaco HSM",
        slot: 2,
        readWrite: false,
        pin: "xxxxxxxxxxxx"
    };

    const crypto = new WebCrypto(cryptoConfig);
    xadesjs.Application.setEngine("pkcs11", crypto);

    const certificateList = await crypto.certStorage.keys();
    console.log(certificateList);

    try {
        const certificate = await crypto.certStorage.getItem('x509-0500000000000000-6365727469666963617465');
    } catch (e) {
        console.log(e.toString());
    }
}
export default { test };

console log:

[ 'x509-0500000000000000-6365727469666963617465' ]

Error: CKR_GENERAL_ERROR:5
    at Error (native) C_GetAttributeValue:444
Error: CKR_GENERAL_ERROR:5
    at Error (native) C_GetAttributeValue:444
    at SessionObject.getAttribute (/home/app/src/node_modules/graphene-pk11/build/object.js:59:25)
    at SessionObject.get (/home/app/src/node_modules/graphene-pk11/build/object.js:77:21)
    at SessionObject.get [as class] (/home/app/src/node_modules/graphene-pk11/build/object.js:86:25)
    at SessionObject.toType (/home/app/src/node_modules/graphene-pk11/build/object.js:95:22)
    at Promise (/home/app/src/node_modules/node-webcrypto-p11/built/crypto/rsa.js:219:53)
    at new Promise (<anonymous>)
    at Function.importJwkPublicKey (/home/app/src/node_modules/node-webcrypto-p11/built/crypto/rsa.js:215:16)
    at importKey.apply.then (/home/app/src/node_modules/node-webcrypto-p11/built/crypto/rsa.js:132:37)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)`

But there were no problems to get a certificate using session.find()

import { WebCrypto } from 'node-webcrypto-p11';
import * as graphene from 'graphene-pk11';

async function test() {

    const Module = graphene.Module;

    const mod = Module.load("/home/app/src/libcs_pkcs11_R2.so", "Ultimaco");

    mod.initialize();

    const session = mod.getSlots(2).open();
    session.login("xxxxxxxxxx");

    const fetchedCertificates = session.find({class: graphene.ObjectClass.CERTIFICATE});
    const certificate = fetchedCertificates.items(0).toType();

    console.log(`======= certificate: `, certificate);
    console.log(`======= Object.getOwnPropertyNames(certificate): `, Object.getOwnPropertyNames(certificate));
    console.log(`======= certificate.lib: `, certificate.lib);
    console.log(`======= certificate.handle: `, certificate.handle);
    console.log(`======= certificate.handle.toString('hex'): `, certificate.handle.toString('hex'));
    console.log(`======= certificate.id.toString('hex'): `, certificate.id.toString('hex'));
    console.log(`======= certificate.label: `, certificate.label);
    console.log(`======= certificate.subject: `, certificate.subject);
    console.log(`======= certificate.value: `, certificate.value);

    session.logout();
    mod.finalize();        
}

export default { test };
======= certificate:  X509Certificate {
  handle: <Buffer 05 00 00 00 00 00 00 00>,
  session: 
   Session {
     handle: <Buffer 9e 16 4f 01 00 00 00 00>,
     slot: 
      Slot {
        handle: <Buffer 02 00 00 00 00 00 00 00>,
        module: [Object],
        slotDescription: 'XXXX - SLOT_0002',
        manufacturerID: 'Utimaco IS GmbH',
        flags: 5,
        hardwareVersion: [Object],
        firmwareVersion: [Object] },
     state: 0,
     flags: 4,
     deviceError: 0 } }
======= Object.getOwnPropertyNames(certificate):  [ 'lib', 'handle', 'session' ]
======= certificate.lib:  PKCS11 { libPath: '/home/app/src/libcs_pkcs11_R2.so' }
======= certificate.handle:  <Buffer 05 00 00 00 00 00 00 00>
======= certificate.handle.toString('hex'):  0500000000000000
======= certificate.id.toString('hex'):  6365727469666963617465
======= certificate.label:  X509 Certificate
======= certificate.subject:  <Buffer 30 81 99 31 30 30 2e 06 37 30 36 ... >
======= certificate.value:  <Buffer 30 82 05 72 30 82 04 5a a0 31 0b 30 09 06 03 55 04 ... >
microshine commented 6 years ago

@ENDaZONELT Thank you for your information

As I can see from log this can be HSM error. You've got CKR_GENERAL_ERROR on public key importing. I cannot reproduce this error with my PKCS11 providers.

Can you try to create RSA public key in your HSM via Session.create function and get class attribute from created object?

const object = session.create({
    token: false,
    class: graphene.ObjectClass.PUBLIC_KEY,
    keyType: graphene.KeyType.RSA,
    private: false,
    label: "RSA-Test-key",
    id: Buffer.from("rsa-test-public-key"),
    verify: true,
    encrypt: true,
    wrap: true,
    publicExponent: Buffer.from("j2MS4Q5yM8bODfWWdwg9aHo3vBtuBeOkArnMKfgP0vPUGoi2Xe+vrHfSFKlb3kBjJVJcIYoEtU1POTtWlj1TnPfJl8vT/poumWAk+W8q20spuRfFA5X6sJvcgsr8XXeKG7IlSqvlE8ETRdPjH8QtOA2qYbzigqx1q0rQKJ5yZ60yivP8fxstb0tFQLJspfYh+tMi02zHPEksZZUjwZe1EkLJED9yZBvlORT6jHubnRkCiQ85rGHx1ADXY7wNa4pPJ8TXH5EUAoBdXW4ommjpXQBW2e7kTxTBmfQRHo22iKwB8CvAepW5zMYgBnKl7UuqpI3BPUaPD76gghybKeahPQ==", "base64")
    modulus: Buffer.from([1,0,1]),
});
console.log(object.class);
ENDaZONELT commented 6 years ago

Thank you for you response @microshine . What I try to do is to get a certificate (not to import public key) from HSM device. I have private key, public key and certificate on my device. And I need to retrieve a certificate from HSM device to sign a document. I know, that I can store a certificate in my application, but I want to have everything on my device.

microshine commented 6 years ago

node-webcrypto-p11 module returns Certificate with PublicKey

interface ICryptoCertificate {
  type: CryptoCertificateFormat;
  publicKey: NativeCryptoKey;
}

https://github.com/PeculiarVentures/node-webcrypto-p11/blob/master/lib/cert_storage.ts#L59

ENDaZONELT commented 5 years ago

Found other way

rmhrisk commented 5 years ago

@ENDaZONELT please share your solution for others.