Closed mohiniyadav closed 3 years ago
Try node-webcrypto-p11. It uses pkcs11js and creates correct signatures.
There is one more our module which helps to generate CSR in 10 lines of code. See @peculiar/x509
I already have public and private key stored in hsm, I want to use those keys to sign certificate, I can see in @peculiar/x509, a new set of keypair is generated. const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"]);
How can I sign a CSR using pre-existing keys in HSM? @microshine
Thanks for replying.
I'll review your code and share my example in 2 hours
CSR generation using node-webcrypto-p11
and @peculiar/x509
import { Crypto } from "node-webcrypto-p11";
import * as x509 from "@peculiar/x509";
async function main() {
// Init Crypto provider
const crypto = new Crypto({
library: "/usr/local/lib/softhsm/libsofthsm2.so",
slot: 0,
pin: "12345",
readWrite: true,
});
// Generate RSA keys
const alg = {
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
publicExponent: new Uint8Array([1, 0, 1]),
modulusLength: 2048,
}
const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"]);
// Add keys to the token
await crypto.keyStorage.setItem(keys.privateKey);
await crypto.keyStorage.setItem(keys.publicKey);
// Generate CSR
const csr = await x509.Pkcs10CertificateRequestGenerator.create({
name: "CN=example.org, C=US, ST=Virginia, L=Blacksburg, O=Test, OU=Test",
keys,
signingAlgorithm: alg,
attributes: [
new x509.ChallengePasswordAttribute("12345"),
],
extensions: [
new x509.SubjectAlternativeNameExtension({
dns: [
"test.domain.com",
"other.domain.com",
"www.domain.net",
],
})
]
}, crypto);
console.log(csr.toString("pem"));
}
main().catch(e => console.error(e));
-----BEGIN CERTIFICATE REQUEST-----
MIIDEzCCAfsCAQAwaTEUMBIGA1UEAxMLZXhhbXBsZS5vcmcxCzAJBgNVBAYTAlVT
MREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzENMAsGA1UE
ChMEVGVzdDENMAsGA1UECxMEVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAMuubNLj6Zmekos3oOhfyxrq8i1wrKs1/pNT0oC7BFwb9RkBRrNeSO8Y
Hw5nlIkX7NJ3ChquctKfLbjvC5BYtGsjltR9uyLy8LRVsuPnSsx6Ggrs7U8SxpGw
5TStTm4vBKcFn5/ttYQdKlx6pJyqrTN7/0IRnuCp729jgeoj7CZ6D2Zdaqn8MEKU
Jx/RJGsN7vcffJcjWcxQ/vu7HUk4bouEbNA+H4aX/XmNmcs1fF6Gl77Kp4uhX889
MEhEeQTDjWf3K5dPlX1pQnGyG8uDbpQxMiFoigGYpbf0xVTxlOlAto5brsQa5Ipk
Gq9RHv5HLAPwJFqDkJustpbbiNhpppkCAwEAAaBlMBQGCSqGSIb3DQEJBzEHEwUx
MjM0NTBNBgkqhkiG9w0BCQ4xQDA+MDwGA1UdEQQ1MDOCD3Rlc3QuZG9tYWluLmNv
bYIQb3RoZXIuZG9tYWluLmNvbYIOd3d3LmRvbWFpbi5uZXQwDQYJKoZIhvcNAQEL
BQADggEBAKmndZsbFFKZIyTInVoNxNdFPAqDqLdVMRATfF9x4dkVqkYdQEwqa9Ru
xHHlMCD9Z08Aszpw/q1LjRoCDvxM8GJcCtoI8NhnF75EKfaHF561TTuebVoxPnR1
6qk2R/NAAHJ8jZi/5upLaqswEGEmJ8Zbam/vFNf1fbMozNLs9JX2oc8XRkbttS+6
ARcG7lanp5SzyabCuTNB93kkhjG4Oy7eSuwUmFxDpoOeOskvp3SuMI9u73I7zQr5
+7K1DLqmdKqEHKrAUbADB94sooIAcaFBow79DYc6MLR9y0nmwQSOBOoBYdg4r06G
cxZa5+FG8blvovjT8QML+kTwjL4mdyA=
-----END CERTIFICATE REQUEST-----
SEQUENCE (3 elem)
SEQUENCE (4 elem)
INTEGER 0
SEQUENCE (6 elem)
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
PrintableString example.org
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.6 countryName (X.520 DN component)
PrintableString US
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.8 stateOrProvinceName (X.520 DN component)
PrintableString Virginia
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.7 localityName (X.520 DN component)
PrintableString Blacksburg
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.10 organizationName (X.520 DN component)
PrintableString Test
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.11 organizationalUnitName (X.520 DN component)
PrintableString Test
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
NULL
BIT STRING (2160 bit) 001100001000001000000001000010100000001010000010000000010000000100000…
SEQUENCE (2 elem)
INTEGER (2048 bit) 257123881271531590243586916281357399888535460018445819024090528777625…
INTEGER 65537
[0] (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.9.7 challengePassword (PKCS #9)
SET (1 elem)
PrintableString 12345
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.9.14 extensionRequest (PKCS #9 via CRMF)
SET (1 elem)
SEQUENCE (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.29.17 subjectAltName (X.509 extension)
OCTET STRING (53 byte) 3033820F746573742E646F6D61696E2E636F6D82106F746865722E646F6D61696E2E63…
SEQUENCE (3 elem)
[2] (15 byte) test.domain.com
[2] (16 byte) other.domain.com
[2] (14 byte) www.domain.net
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.1.11 sha256WithRSAEncryption (PKCS #1)
NULL
BIT STRING (2048 bit) 101010011010011101110101100110110001101100010100010100101001100100100…
If you need to use keys from the token use KeyStorage API
If you need to add a request or certificate to the token use CertificateStorage API
I tried this example but i get this error.
[Pkcs11Error: CKR_FUNCTION_NOT_SUPPORTED] { method: 'C_CopyObject', nativeStack: ' at Error (native) C_CopyObject:584', code: 84 }
Could you please help me with it
Looks like your PKCS11 provider doesn't support C_CopyObject function. You should create your objects directly on the token. node-webcrypto-p11
allows doing it via the algorithm
argument.
Try this
const alg = {
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
publicExponent: new Uint8Array([1, 0, 1]),
modulusLength: 2048,
token: true,
sensitive: true,
}
It works just fine. Thank you so much
When i remove the token and plug it in again I found that the key pairs were removed from the token @microshine
Do i have to use crypto.subtle.importKey to save key pairs in token ? @microshine
When i remove the token and plug it in again I found that the key pairs were removed from the token
If you pass the token: true
property into the algorithm (generateKey
or improtKey
) it should save the key into the token
Do i have to use crypto.subtle.importKey to save key pairs in token ?
Are you importing or generating the key?
@MhmodTayel What PKCS#11 library do you use?
I'm using epass2003auto token with it's libcastle module also I'm using the example you provide above. but when I generate key pairs and list all objects in the token I saw them but when I unplug the token and plug it again I didn't see them and after few tries i got anther error CryptoError: Rsa: Can not generate new key CKR_DEVICE_MEMORY:49
in spite of there is no key pairs in the token
Here are some examples
Remove all objects from the token
await crypto.keyStorage.clear();
await crypto.certStorage.clear();
List all keys and certs
const keys = await crypto.keyStorage.keys();
for (const index of keys) {
console.log(index);
}
const certs = await crypto.certStorage.keys();
for (const index of certs) {
console.log(index);
}
I'm confused that it throws the CKR_DEVICE_MEMORY error, but you don't see these objects on the token.
Please try to generate the keys using the token: true
property and list all keys by the script I've shared.
Could you try to create the self-signed certificate or request via https://tools.fortifyapp.com. It requires the Fortify app which you can download from https://fortifyapp.com. This app uses node-webcrypto-p11 and supports epass2003 token
I don't have ePass2003 token but this script works fine with SoftHSM
import { Crypto } from "node-webcrypto-p11";
const crypto = new Crypto({
library: "/usr/local/lib/softhsm/libsofthsm2.so",
slot: 0,
pin: "12345",
readWrite: true,
});
// await crypto.keyStorage.clear();
const alg = {
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
publicExponent: new Uint8Array([1, 0, 1]),
modulusLength: 2048,
token: true,
sensitive: true,
};
await crypto.subtle.generateKey(alg, false, ["sign", "verify"]);
const keys = await crypto.keyStorage.keys();
for (const index of keys) {
console.log(index);
}
crypto.keyStorage.keys
receives keys with token: true
only
I removed all objects from the token and I was able to generate key pairs but The issue of keeping key pairs in the token after unplug it and plug it again still exist
Does node-webcrypto-p11 show an empty list too after token replugin?
yes
it's really strange
Try to get access to PKCS#11 object. Each key keeps it in p11Object
field.
console.log("Token:", rsaKeys.privateKey.p11Object.token);
If it returns true
and disappears after token removing, I guess the problem is on PKCS#11 library
The issue of CKR_DEVICE_MEMORY still exist in spite of there is no object in the token
Could we have a chat via Skype or Hangouts?
Skype: microshine82 Hangouts: microshine82@gmail.com
@MhmodTayel Please try one more script.
graphene-p11
is a wrapper over the PKCS#11 interface. This script allows printing all PKCS#11 objects from the token
import * as graphene from "graphene-p11";
async function main() {
const softhsm = graphene.Module.load("/usr/local/lib/softhsm/libsofthsm2.so");
softhsm.initialize();
try {
const slot = softhsm.getSlots(0);
const session = slot.open(graphene.SessionFlag.SERIAL_SESSION);
session.login("12345");
const objects = session.find();
for (const obj of objects) {
console.log(graphene.ObjectClass[obj.class]);
}
} finally {
softhsm.finalize();
}
}
main().catch(e => console.error(e));
Log
PUBLIC_KEY
PRIVATE_KEY
PRIVATE_KEY
PRIVATE_KEY
PUBLIC_KEY
PUBLIC_KEY
Still the same
It works fine with softhsm
Do you use the latest version of libcastle
?
yes
Hello @microshine, I hope you and your lovely ones feel great. Can you please tell me that what is the problem here?
Providing code to review:
let keySize = 2048; var publicKeyTemplate = [ { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PUBLIC_KEY }, { type: pkcs11js.CKA_TOKEN, value: true }, { type: pkcs11js.CKA_LABEL, value: "My RSA Public Key" }, { type: pkcs11js.CKA_DERIVE, value: true }, { type: pkcs11js.CKA_PUBLIC_EXPONENT, value: new Buffer([1, 0, 1]) }, { type: pkcs11js.CKA_MODULUS_BITS, value: keySize }, { type: pkcs11js.CKA_VERIFY, value: true } ]; var privateKeyTemplate = [ { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY }, { type: pkcs11js.CKA_TOKEN, value: true }, { type: pkcs11js.CKA_LABEL, value: "My RSA Private Key" }, { type: pkcs11js.CKA_SIGN, value: true }, { type: pkcs11js.CKA_DERIVE, value: true }, { type: pkcs11js.CKA_EXTRACTABLE, value: true }, { type: pkcs11js.CKA_SENSITIVE, value: true } ];