Closed AiNoKame closed 6 years ago
Hello!
As I can see from your steps you don't import certificate to SoftHSM. You use PKCS#8 which is private key and import it to SoftHSM
Eech SessionObject has class
property which you can use to understand what object class do you have
https://github.com/PeculiarVentures/graphene/blob/master/index.d.ts#L343
There is another npm module which allows to use PKCS#11 tokens easier node-webcrypto-p11
you can get list of allowed keys or certificates by using CryptoStorage
https://github.com/PeculiarVentures/node-webcrypto-p11#key-storage
https://github.com/PeculiarVentures/node-webcrypto-p11#certificate-storage
@microshine Thanks for the quick response! 😄 Regarding node-webcrypto-p11, I was a bit worried when I saw this https://www.npmjs.com/package/node-webcrypto-p11#warning
Question 1: Is there a way to get the certificate contents via only graphene?
Also regarding your comment:
As I can see from your steps you don't import certificate to SoftHSM. You use PKCS#8 which is private key and import it to SoftHSM
Question 2: Do you mean according to my steps, I forgot to import the certificate to SoftHSM (I thought I did in step 2 😉 )? Or do you mean, I shouldn't use SoftHSM to import the certificate?
Follow-up question (that's more about the use of SoftHSM 😅 ):
Question 3: Is there a way to import a certificate using softhsm2-util --import
so that graphene recognizes the certificate as an x509 certificate instead of a public/private key?
You can use this example. I use filter for find function. objects
contains all certificates from token
var graphene = require("graphene-pk11");
const lib = "/usr/local/lib/softhsm/libsofthsm2.so";
const mod = graphene.Module.load(lib, "LIB");
mod.initialize();
try {
const slot = mod.getSlots(0);
const session = slot.open(4);
const objects = session.find({class: graphene.ObjectClass.CERTIFICATE});
for (let i=0; i<objects.length; i++) {
const cert = objects.items(i).toType();
console.log(cert.value.toString("hex"));
}
} catch (e) {
console.error(e);
}
mod.finalize();
You use
--import /Users/AiNoKame/Documents/GitHub/SoftHSMv2/new-key.pem
As I can see it's private key. I don't see openssl certificate creation and cert.pem file importing
It looks you cannot use softhsm2-util to import certificate
--import <path> Import a key pair from the given path.
The file must be in PKCS#8-format.
Use with --slot or --token or --serial, --file-pin,
--label, --id, --no-public-key, and --pin.
You can use graphene
to do it https://github.com/PeculiarVentures/node-webcrypto-p11/blob/master/lib/cert.ts#L181
@microshine 😄 Thanks again for the quick response! I've tried several things since yesterday, but I still can't find a way to see my private certificate contents in plain text 😞
1) First, re-initialized my token and used pkcs11-tool
to generate a fresh key pair in case the issue was my imported private key:
pkcs11-tool --module=/usr/local/lib/softhsm/libsofthsm2.so -l -k \
-d abcd1234 -a new-key --key-type rsa:2048
2) I copied your code completely from Answer 1 above, and nothing was logged
3) I tried using your suggested node-webcryto-p11
module and wrote another small node app:
const p11 = require('node-webcrypto-p11')
const crypto = new p11.WebCrypto({
library: '/usr/local/lib/softhsm/libsofthsm2.so',
slot: 0,
readWrite: true
})
Promise.resolve()
.then(() => crypto.keyStorage.keys())
.then(indexes => {
console.log('\n\n========== indexes', indexes)
return crypto.keyStorage.getItem(indexes[0])
})
.then(cert => {
console.log('\n\n========== cert', cert)
console.log('\n\n========== cert.toJSON()', cert.toJSON())
})
.catch(error => {
console.error('ERROR', error)
})
Output:
========== indexes [ 'public-0200000000000000-abcd1234' ]
========== cert RsaCryptoKey {
p11Object:
PublicKey {
handle: <Buffer 02 00 00 00 00 00 00 00>,
session:
Session {
handle: <Buffer 01 00 00 00 00 00 00 00>,
slot: [Object],
state: 2,
flags: 6,
deviceError: 0 } },
usages: [ 'encrypt', 'verify', 'wrapKey' ],
type: 'public',
extractable: true,
algorithm:
{ name: 'RSASSA-PKCS1-v1_5',
hash: { name: 'SHA-256' },
modulusLength: 2048,
publicExponent: Uint8Array [ 1, 0, 1 ] },
id: 'public-0200000000000000-abcd1234' }
========== cert.toJSON() { algorithm:
{ name: 'RSASSA-PKCS1-v1_5',
hash: { name: 'SHA-256' },
modulusLength: 2048,
publicExponent: Uint8Array [ 1, 0, 1 ] },
type: 'public',
usages: [ 'encrypt', 'verify', 'wrapKey' ],
extractable: true }
...I'm not sure why indexes [ 'public-0200000000000000-abcd1234' ]
only contained the public key (and not the private key, which is what I need), and even then, there was no plain text data that I could find in the public key
Am I completely on the wrong path here? I just want to be able to securely store a private key in my HSM and use a node module to fetch the private key in plain text for use in my node app
It's not secure to put private key to HSM and then export it as plain text.
May I ask you? What are you using for exported private key? Maybe I can suggest you another way
Otherwise I can write example how to export private key from KeyStorage
Mainstream HSMs do not support clear text export of private keys. I think there must be some confusion here.
I'd love to see an example on how to export private key from KeyStorage! 😃
I have a pretty simple use case - I just want to store my private keys on an HSM and access those private keys using a node module when creating my https node server (https://nodejs.org/api/https.html#https_https_createserver_options_requestlistener)
I see. You need PKCS#8 private key
// @ts-check
const { WebCrypto } = require("node-webcrypto-p11");
const crypto = new WebCrypto({
library: '/usr/local/lib/softhsm/libsofthsm2.so',
slot: 0,
readWrite: true,
pin: "12345", // you need login to get private objects
});
async function main() {
if (crypto.isLoggedIn) {
crypto.login("12345"); // you need login to get private objects
}
const indexes = await crypto.keyStorage.keys();
let privateKey;
for(const index of indexes) {
const parts = index.split("-");
if (parts[0] === "private") {
privateKey = await crypto.keyStorage.getItem(index);
break;
}
}
if (privateKey) {
// NOTE: You can export only exportable private key
const raw = await crypto.subtle.exportKey("pkcs8", privateKey);
const bufRaw = new Buffer(raw);
console.log(bufRaw.toString("hex"));
} else {
console.log("Private key is not found");
}
}
main()
.catch((err) => {
console.error(err);
})
bufRaw
- PKCS#8 private key in DER format
If you need PEM you need to do it manually
Thanks for all the support so far, @microshine and @rmhrisk 😸 I think I'm asking for the impossible here 😆 I just opened up another ticket at nodejs (https://github.com/nodejs/help/issues/964) now that I'm a bit more knowledgeable about the actual functionality of an HSM, but I'm doubtful regarding any positive response there
Re:
I have a pretty simple use case - I just want to store my private keys on an HSM and access those private keys using a node module when creating my https node server (https://nodejs.org/api/https.html#https_https_createserver_options_requestlistener)
HSMs are used most commonly when keys live cradle to grave in the HSM.
FYI: Node crypto is a just a thin layer ontop of OpenSSL. It is possible to have node honor your OpenSSL configuration file when doing crypto, specifically with TLS. It is possible to specify a "OpenSSL engine module" in your configuration. You can usually get your HSM to be loaded in this fashion.
Thanks for the info, @rmhrisk ! I responded to your comment on the nodejs issue (https://github.com/nodejs/help/issues/964) 😄 I'm going to close this issue on the graphene repo since I think it's evolved into a generic nodejs question, so if you happen to have any further comments, please add them to the nodejs thread!
I just started using graphene, and I'm trying to read a certificate in plain text that I stored using SoftHSMv2. Here's all I've done:
0) Convert regular PEM formatted private certificate to PKCS#8 format
1) Initialize token
2) Import private certificate into token
3) Run a simple nodejs app using graphene to fetch certificate
Output:
I'm not seeing the certificate contents in my certificate object at all!
Any help would be appreciated!