If my HSM contains only an RSA private key, is it possible to derive a public key from it?
I tried using OpenSSL but it doesn’t seem to work.
openssl rsa -engine pkcs11 -in "pkcs11:id=%01;type=private" -inform engine -pubout -text
engine "pkcs11" set.
PKCS11_get_private_key returned NULL
cannot load Private Key from engine
140701804377920:error:8206F012:PKCS#11 module:pkcs11_getattr_int:Attribute type invalid:p11_attr.c:48:
140701804377920:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:crypto/engine/eng_pkey.c:78:
I’m not sure what’s happening behind the scenes in OpenSSL, but based on the syntax, it suggests that OpenSSL is trying load the private key from the HSM (which I know it won’t allow). If OpenSSL can’t do it, is there another tool that can?
Hi!
Looking at the raw commands of the Nitrokey HSM’s smart card I do not see such possibility. Please write to support@nitrokey.com
if you are interested in the detailed manual.
saper
November 4, 2020, 8:35pm
3
If you are allowed to use the key, you can request a certificate (for example using OpenSSL PKCS#11 engine https://github.com/OpenSC/OpenSC/wiki/SmartCardHSM#using-openssl-with-engine-pkcs11 ) and the X.509 (or PKCS#10) structure will contain your public key.
1 Like
saper
November 4, 2020, 8:39pm
4
By the way, the following worked for me:
openssl <<EOF
engine -t dynamic -pre SO_PATH:/usr/local/lib/engines/pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/local/lib/pkcs11/opensc-pkcs11.so
rsa -engine pkcs11 -in "pkcs11:id=%02;type=private" -inform engine -pubout -text
EOF
And the result:
OpenSSL> (dynamic) Dynamic engine loading support
[Success]: SO_PATH:/usr/local/lib/engines/pkcs11.so
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
[Success]: MODULE_PATH:/usr/local/lib/pkcs11/opensc-pkcs11.so
Loaded: (pkcs11) pkcs11 engine
[ available ]
OpenSSL> engine "pkcs11" set.
Enter PKCS#11 token PIN for DEV2 (UserPIN):
Public-Key: (4096 bit)
Modulus:
00:b9:08:58:d6:32:6e:91:44:17:77:7c:d9:1e:bc:
80:1e:54:78:da:f6:09:0a:91:3e:32:48:c8:58:53:
5d:a9:21:e1:d8:5d:61:4b:be:a7:11:7e:28:e6:27:
36:90:78:8d:fa:05:44:26:7f:4c:a2:b7:8d:69:21:
fb:b6:c4:3c:4a:82:a5:e0:f4:ea:49:9f:5f:f9:13:
7f:ba:79:c3:6b:bf:a8:79:fc:13:0c:b7:d9:ab:95:
e4:3f:78:ac:99:eb:25:c1:3f:fa:f4:16:24:38:b5:
1c:ed:12:e6:18:2f:96:e7:d7:c4:05:95:4b:f6:bf:
46:f2:07:e0:5a:69:a9:97:85:9f:c2:b9:cf:57:c3:
f4:50:1e:b4:20:e0:71:db:38:64:df:83:6b:7d:ca:
5a:81:69:ce:d8:30:81:28:38:6c:37:fd:21:0b:89:
2f:18:78:f0:6e:5d:a0:3f:81:1d:09:bf:95:92:e6:
0a:ce:e9:ee:3f:f2:70:bc:c3:08:ca:57:ec:d5:ba:
12:6d:2e:1a:60:e6:51:5e:63:bb:18:c7:89:a9:f9:
62:ad:35:3a:27:46:c3:b2:b1:5a:24:9d:00:96:cc:
1b:7b:5a:81:89:af:54:f3:3f:1b:9d:2d:51:e8:4b:
e0:71:b3:bf:18:24:1d:5f:f5:41:a0:f0:57:ec:d0:
08:ce:f4:1c:04:39:03:e4:f8:f0:b5:f6:9f:f5:fc:
ef:f1:ec:f9:5b:3f:76:66:15:d8:fa:2f:75:e9:4d:
41:1f:79:e7:25:f7:69:60:d6:bb:ad:23:ec:6d:b1:
61:3e:dd:d8:73:b8:0b:14:7a:48:51:4f:7a:5b:86:
16:be:cf:de:bb:e2:02:f4:7a:ee:41:56:4c:95:0d:
c8:af:1d:68:f0:6d:32:ed:e6:61:ae:f2:72:81:d2:
c8:a3:dc:ce:a2:db:26:8f:e7:7e:22:97:5c:2f:09:
f3:c3:d0:90:bf:63:6b:e1:af:e5:4a:08:9d:13:d4:
3c:d7:0e:bc:9b:59:95:57:36:f7:12:f0:8d:a1:81:
1c:fa:cf:12:2c:a9:44:df:34:fe:65:28:6e:bb:90:
b3:9f:fa:7e:43:44:4a:ee:a4:c6:fd:b3:18:ee:cc:
ad:0c:aa:f1:c5:c7:cb:05:2d:0b:85:c6:6f:c2:1f:
50:51:d0:f7:6c:7a:78:46:29:de:2e:2c:1e:39:0d:
8d:5a:90:ab:01:6c:53:a2:25:11:90:c2:cf:9d:71:
f6:0b:65:a0:9d:b4:20:f3:89:2a:d2:ce:23:b5:89:
28:fd:8f:45:7c:b2:9d:97:ff:af:68:fd:aa:81:3a:
d2:eb:06:70:4d:77:32:c5:82:3c:c8:79:e1:8f:88:
78:76:e1
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuQhY1jJukUQXd3zZHryA
HlR42vYJCpE+MkjIWFNdqSHh2F1hS76nEX4o5ic2kHiN+gVEJn9MoreNaSH7tsQ8
SoKl4PTqSZ9f+RN/unnDa7+oefwTDLfZq5XkP3ismeslwT/69BYkOLUc7RLmGC+W
59fEBZVL9r9G8gfgWmmpl4WfwrnPV8P0UB60IOBx2zhk34NrfcpagWnO2DCBKDhs
N/0hC4kvGHjwbl2gP4EdCb+VkuYKzunuP/JwvMMIylfs1boSbS4aYOZRXmO7GMeJ
qflirTU6J0bDsrFaJJ0Alswbe1qBia9U8z8bnS1R6EvgcbO/GCQdX/VBoPBX7NAI
zvQcBDkD5Pjwtfaf9fzv8ez5Wz92ZhXY+i916U1BH3nnJfdpYNa7rSPsbbFhPt3Y
c7gLFHpIUU96W4YWvs/eu+IC9HruQVZMlQ3Irx1o8G0y7eZhrvJygdLIo9zOotsm
j+d+IpdcLwnzw9CQv2Nr4a/lSgidE9Q81w68m1mVVzb3EvCNoYEc+s8SLKlE3zT+
ZShuu5Czn/p+Q0RK7qTG/bMY7sytDKrxxcfLBS0LhcZvwh9QUdD3bHp4RineLiwe
OQ2NWpCrAWxToiURkMLPnXH2C2WgnbQg84kq0s4jtYko/Y9FfLKdl/+vaP2qgTrS
6wZwTXcyxYI8yHnhj4h4duECAwEAAQ==
-----END PUBLIC KEY-----
1 Like
hmmmm…still can’t get it to work. Maybe it’ll be helpful if I post the steps I’m using…
pkcs11-tool --keypairgen --key-type rsa:2048 --id 01 --login
openssl req -config openssl.cnf -engine pkcs11 -keyform engine -new -x509 -key 01 -sha512 -days 10 -out test.crt
pkcs11-tool --write-object test.crt --type cert --id 01 --login
pkcs11-tool --list-object --login
Using slot 0 with a present token (0x0)
Logging in to "UserPIN (TEST)".
Please enter User PIN:
Private Key Object; RSA
label: Certificate
ID: 01
Usage: decrypt, sign, unwrap
Certificate Object; type = X.509 cert
label: Certificate
subject: DN: CN=test
ID: 01
Public Key Object; RSA 2048 bits
label: Certificate
ID: 01
Usage: encrypt, verify
pkcs11-tool --delete-object --id 01 --type cert --login
pkcs11-tool --list-object --login
Using slot 0 with a present token (0x0)
Logging in to "UserPIN (TEST)".
Please enter User PIN:
Private Key Object; RSA
label: Certificate
ID: 01
Usage: decrypt, sign, unwrap
My engine configuration is in the openssl.cnf but I did try it all on the CLI. Also, I’m using CentOS 8 so my library paths are a little different.
openssl <<EOF
engine -t dynamic -pre SO_PATH:/usr/lib64/engines-1.1/pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/lib64/opensc-pkcs11.so
rsa -engine pkcs11 -in "pkcs11:id=%01;type=private" -inform engine -pubout -text
EOF
PKCS11_get_private_key returned NULL
cannot load Private Key from engine
140154751170368:error:8206F012:PKCS#11 module:pkcs11_getattr_int:Attribute type invalid:p11_attr.c:48:
140154751170368:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:crypto/engine/eng_pkey.c:78:
unable to load Private Key
error in rsa
Curiously, I did discover that if I create a keypair (and don’t bind a cert to it), then I can successfully derive the public key. I’m wondering if the private key attributes are changed during the --write-object step?
BHR
November 6, 2020, 12:46pm
6
With a siging request it worked for me.
Create a certificate with the private key, stored within the Nitrokey at ID 11:
$ openssl req -engine pkcs11 -keyform engine -new -key 11 -nodes -days 35600 -x509 -sha256 -out "id11-cert.pem" -subj "/CN=Test Cert 1" -key "pkcs11:pin-value=648219" engine "pkcs11" set.
The certificate contains the RSA public key (Modulus, Exponent):
$ cat id11-cert.pem |openssl x509 -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
70:fe:41:f8:1f:a1:36:bd:b1:65:15:cf:41:ca:2f:c9:82:b8:0d:68
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = Test Cert 1
Validity
Not Before: Nov 6 12:13:33 2020 GMT
Not After : Apr 27 12:13:33 2118 GMT
Subject: CN = Test Cert 1
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (1024 bit)
Modulus:
00:b3:88:f1:d6:9d:87:50:94:d3:52:9d:8a:97:e6:
3b:35:01:a4:ee:3b:65:4b:e6:14:b7:6d:74:57:ee:
29:dc:c8:7f:5d:a7:b5:c8:ea:54:75:97:ea:31:d6:
2e:38:07:23:5e:de:04:5a:59:05:03:af:01:67:a6:
74:9a:8b:ef:5c:6a:95:13:f9:7a:08:fe:91:5d:f8:
95:ca:96:40:14:0f:84:7a:b8:89:e8:a6:4e:3c:a9:
e4:24:7b:9e:a3:1a:0b:5f:6b:2a:8e:fe:c5:ac:e4:
01:79:00:4a:f9:e0:14:3f:2b:39:31:b2:1b:c5:c7:
d8:d9:f7:e9:1d:65:4b:a3:41
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
97:D2:F0:EF:25:44:D2:CE:D6:B8:9D:A5:7C:5C:ED:39:A0:34:C0:61
X509v3 Authority Key Identifier:
keyid:97:D2:F0:EF:25:44:D2:CE:D6:B8:9D:A5:7C:5C:ED:39:A0:34:C0:61
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
98:1e:e3:7e:14:f8:b8:4f:0f:4f:b9:57:b3:be:2e:3a:09:d7:
04:0c:df:bd:53:28:03:39:1c:b1:35:bc:b7:cc:1f:a2:78:e9:
c9:ac:c3:e9:4b:ef:82:bd:f3:c2:ff:59:d8:37:82:7b:64:be:
f4:c8:6d:37:43:c6:a3:a6:62:0b:05:89:8d:eb:4a:6b:ac:80:
fa:8f:5b:4f:59:83:b2:57:15:d8:44:6b:f5:9f:48:11:52:03:
9f:48:fe:c0:70:a1:71:59:b9:30:50:fe:c5:bf:80:9c:27:06:
51:40:87:25:04:ea:28:44:cc:19:01:9b:c8:3f:37:b6:52:f5:
cd:82
Now you can extract the public key from the certificate:
$ openssl x509 -pubkey -noout -in id11-cert.pem > id11-pubkey.pem
$ cat id11-pubkey.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCziPHWnYdQlNNSnYqX5js1AaTu
O2VL5hS3bXRX7incyH9dp7XI6lR1l+ox1i44ByNe3gRaWQUDrwFnpnSai+9capUT
+XoI/pFd+JXKlkAUD4R6uInopk48qeQke56jGgtfayqO/sWs5AF5AEr54BQ/Kzkx
shvFx9jZ9+kdZUujQQIDAQAB
-----END PUBLIC KEY-----
I appreciate the help you all have been giving!!
Unfortunately, I still end up with the error “pkcs11_getattr_int:Attribute type invalid:p11_attr.c:48:
”
This could be inherit to HSM1 so I will test again as soon as my HSM2 arrives.
The easiest way to reproduce the error:
Generate a keypair on the HSM
Generate a certificate from OpenSSL which is signed by the HSM
Copy the certificate to the HSM
Delete the certificate from the HSM (which removes the public key)
Try to generate another certificate with OpenSSL which is signed by the HSM
saper
November 16, 2020, 12:01am
8
Well, you didn’t say it is HSM1, I tried HSM2 (I have only access to these).
You can also try building https://github.com/CardContact/sc-hsm-embedded and then make sure you are using --module option to PKCS#11 tools pkcs11-tool --module /usr/local/lib/libsc-hsm-pkcs11.so -L
and change the PKCS#11 module path for OpenSSL