NK3 PKCS11 Generate RSA mechanism not supported

Hello

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

Am I doing something wrong ?

Keypairs need to be generated using nitropy

c:\Program Files\Nitrokey\Nitropy>nitropy.exe nk3 piv --experimental generate-key --key 9A --algo rsa2048 --subject-name "CN=My Name" --subject-alt-name-upn "my.name@example.com" --path my.csr
Command line tool to interact with Nitrokey devices 0.12.2
Enter the PIN:
Nitrokey CCID/ICCD Interface 0

c:\Program Files\Nitrokey\Nitropy>nitropy.exe nk3 piv --experimental list-certificates
Command line tool to interact with Nitrokey devices 0.12.2
Nitrokey CCID/ICCD Interface 0
Slot    Algorithm               Subject                 Serial Number                                   Issuer          
----    ----------------------- ------------------      ----------------------------------------        ------------------
9A      sha256WithRSAEncryption CN=My Name      3ddcde5da3454533d6011e6fdf82f41b60c45344        CN=My Name
1 Like

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 ?

Thanks in advance for your help

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.

nitropy nk3 piv --experimental read-certificate --key 9A
Command line tool to interact with Nitrokey devices 0.12.2
Nitrokey CCID/ICCD Interface 0
-----BEGIN CERTIFICATE-----
MIID2DCCAsCgAwIBAgIUPdzeXaNFRTPWAR5v34L0G2DEU0QwDQYJKoZIhvcNAQEL
BQAwGjEYMBYGA1UEAwwPUmVpbmVyIFJvdHRtYW5uMCAXDTAwMDEwMTAwMDAwMFoY
DzIwOTkwMTAxMDAwMDAwWjAaMRgwFgYDVQQDDA9SZWluZXIgUm90dG1hbm4wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7varbwH+6+fTc8ogOH911wPhC
8HJw8t01SretwIqZSwjplD1gtg4WIULqkd5gBLyltZ5bPAzL6J9h0/YrRU0mznDq
+RwNMhr6zIwW8fDBdwDxCO9UsXLrl0ADYD0ApYVd0i+3klBoVoy9I0XjvAYwAN0u
8MOjWWBEtm21JcDCOoRfChRzQ45x5l67PiZkAaz6TMXwk3XFin/v6mpReV+nzgfQ
fheOCB4ChknhDiFgegDQ3H90U+VZ24qpoGSleRJ78gx0b2Vxbs6Ip6XvE0N9Lat7
7fHX/fTlb88kCxTthhEvFuXcUT3iZ8Ciy1Hxz0kb5/3Iy+1VXIIL4qbvTtuRAgMB
AAGjggESMIIBDjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSUE
GDAWBggrBgEFBQcDAgYKKwYBBAGCNxQCAjCBlAYJKoZIhvcNAQkPBIGGMIGDMAsG
CWCGSAFlAwQBKjALBglghkgBZQMEAS0wCwYJYIZIAWUDBAEWMAsGCWCGSAFlAwQB
GTALBglghkgBZQMEAQIwCwYJYIZIAWUDBAEFMAoGCCqGSIb3DQMHMAcGBSsOAwIH
MA4GCCqGSIb3DQMCAgIAgDAOBggqhkiG9w0DBAICAgAwNgYDVR0RBC8wLaArBgor
BgEEAYI3FAIDoB0MG3JlaW5lci5yb3R0bWFubkBleGFtcGxlLmNvbTANBgkqhkiG
9w0BAQsFAAOCAQEASa0gi9oiKcWKDae8Zk+jsCuKicauoFZRgF1ltQWCofAGCqyZ
tXk7hentzWSJHA4G9ZtfB0CcRlij8lg+8xDXbUm9sn18J6dDJl1SU2yK6PtlOQHP
J+jnJG8H6+XoADKnSVjcE744iEJN068Vdi5rRHonQ/6JJ70a0ox9AmIaG7JSSzXB
b4aX1QgMLnZMN1HEyrw5aTC0Fbgl3c9NknW6ubx6b2iIGrGtEG6+iQhkPQZjc+m/
v95LnsN/2JaKosCVrVjphCF96rgdW/O5enLB7ialov3ePRj0oplb8S9/WSC7NOyG
6ZkUizya9+fd0edOvJK+1MubGEZQKu1Ojq/d3Q==
-----END CERTIFICATE-----

openssl x509 -in cert.pem -pubkey -noout > public.pem

cat public.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu72q28B/uvn03PKIDh/d
dcD4QvBycPLdNUq3rcCKmUsI6ZQ9YLYOFiFC6pHeYAS8pbWeWzwMy+ifYdP2K0VN
Js5w6vkcDTIa+syMFvHwwXcA8QjvVLFy65dAA2A9AKWFXdIvt5JQaFaMvSNF47wG
MADdLvDDo1lgRLZttSXAwjqEXwoUc0OOceZeuz4mZAGs+kzF8JN1xYp/7+pqUXlf
p84H0H4XjggeAoZJ4Q4hYHoA0Nx/dFPlWduKqaBkpXkSe/IMdG9lcW7OiKel7xND
fS2re+3x1/305W/PJAsU7YYRLxbl3FE94mfAostR8c9JG+f9yMvtVVyCC+Km707b
kQIDAQAB
-----END PUBLIC KEY-----

I used pkcs#11 Python module as I tinkered with PIV.

1 Like

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.

Anyway, thank you @nku !