I’m trying to generate an RSA key pair with my Nitrokey 3A (No NFC) on Windows using OpenSC.
According to the product page, this key have RSA 2048-4096 and support PKCS11.
However, when I use the following command to generate a key pair: pkcs11-tool --login-type user --pin 123456 -k --key-type RSA:2048 --slot 0
I get the following message: error: Generate RSA mechanism not supported Aborting.
Result of pkcs11-tool -L: Slot 0 (0x0): Nitrokey CCID/ICCD Interface 0 token label : PIV_II token manufacturer : piv_II token model : PKCS#15 emulated token flags : login required, rng, token initialized, PIN initialized hardware version : 0.0 firmware version : 0.0 serial num : b3624da64dde4d8e pin min/max : 4/8 uri : pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=b3624da64dde4d8e;token=PIV_II
Thank you, I was able to generate keys with nitropy just as you said. But how is it related to pksc#11 ?
I built a proof a concept using python-pkcs11 and a Picokey HSM. I bought a NK3 as a replacement because it is supposed to be pksc#11 compatible.
How can I retrieve de generated public key ? Is it possible with pkcs#11 ? And how can I decipher something with the private key ?
I don’t get how the different features of the Nitrokey 3 are related to each others.
Is --key 9A the key slot mentioned here Key Management - Nitrokey Documentation ?
Correct. Slot 9A is one of the PIV key slots and in the original concept each slot has a specific use (9A for authentication, 9D for key management, 9E for card authentication/attestation). However, you may use them as you please as they are treated the same way.
I also got confused as I tinkered with pkcs11-tool and various Tokens (Nitrokey Pro, NK3, HSM and also Picokey).
Tokens (on the NK3, even the different applets) often support only a subset of the functionality or require specific arguments that need to be figured out.
In practice, it always boils down to using the vendor tool for initialization and key management.
As Picokeys also got forked, I looked into the Python code and this seems to be the right level of abstraction to derive small automation tools for setting up the token. Often some raw APDUs are being used to configure the parameters.
Ok, it’s more clear now.
PIV slots are totally different from PKSC#11 slots.
Keys are accessible with PKSC#11 but because PIV objects does not have labels or IDs, they cannot be used for filtering.
It seems that PKSC#11 IDs are somehow linked to PIV slots. Something like this:
01 → 9A
02 → 9C
04 → 9E
The keys can be extracted directly without using the certificates.
But using certificate, we can access the issuer value that is set when creating the key (subject-name).
Here is an example of what can be done python-pkcs11:
from pkcs11 import ObjectClass, Attribute, lib
from OpenSSL import crypto
lib = lib(r"C:\Program Files\OpenSC Project\OpenSC\pkcs11\opensc-pkcs11.dll")
tokens = lib.get_tokens()
# Filter PKCS#11 using manufacturer id
token = None
for t in tokens:
if "Nitrokey" in t.slot.manufacturer_id:
token = t
break
assert(token is not None)
with token.open() as session:
# Get all public keys
pubkeys = session.get_objects({
Attribute.CLASS: ObjectClass.PUBLIC_KEY
})
# Get all certificates
certs = session.get_objects({
Attribute.CLASS: ObjectClass.CERTIFICATE,
})
for cert in certs:
print(cert[Attribute.ISSUER].decode("ascii")) # <- subject-name
print(cert[Attribute.ID])
# Extracting public key from certificate
pubkey = crypto.load_certificate(
crypto.FILETYPE_ASN1,
cert[Attribute.VALUE],
).get_pubkey()
print(crypto.dump_publickey(crypto.FILETYPE_PEM, pubkey))
print()
print()
for pubkey in pubkeys:
# Getting public key directly
pubkey = crypto.load_publickey(crypto.FILETYPE_ASN1, pubkey[Attribute.VALUE])
pubkey_pem = crypto.dump_publickey(crypto.FILETYPE_PEM, pubkey)
print(pubkey_pem)
print()
Yet I wasn’t able to generate a key with python-pkcs11.