I generate private keys using RustCrypto for EC/P256 and Ed25519 and serialize them to PKCS#8, I get PKCS#8v1 for the EC key and PKCS#8v2 for Ed25519. I want to display the file content using openssl pkey
.
I store them in PEM files and try to show them using openssl pkey
. It looks like PKCS#8v2 is not supported:
$ cat client-key-ec-p256.pem
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBWozCxMmxGOxC1Sk
6BJewRNZyvTPuuDNDyGgtT5amLGhRANCAATvEOIa3laR/RoVYctOysCbFljPRVj1
wjYGoiTsqXMWDZKiVo9PsPEu19s9DD5b9YSimm9yDSQYb74ue0zk292Z
-----END PRIVATE KEY-----
$ openssl pkey -text -noout -in client-key-ec-p256.pem
Private-Key: (256 bit)
priv:
05:6a:33:0b:13:26:c4:63:b1:0b:54:a4:e8:12:5e:
c1:13:59:ca:f4:cf:ba:e0:cd:0f:21:a0:b5:3e:5a:
98:b1
pub:
04:ef:10:e2:1a:de:56:91:fd:1a:15:61:cb:4e:ca:
c0:9b:16:58:cf:45:58:f5:c2:36:06:a2:24:ec:a9:
73:16:0d:92:a2:56:8f:4f:b0:f1:2e:d7:db:3d:0c:
3e:5b:f5:84:a2:9a:6f:72:0d:24:18:6f:be:2e:7b:
4c:e4:db:dd:99
ASN1 OID: prime256v1
NIST CURVE: P-256
$ cat client-key-ed25519.pem
-----BEGIN PRIVATE KEY-----
MFECAQEwBQYDK2VwBCIEIGpXp9yLxq65o3YwgYdb9TgpvkR7ii1KSlHJIs+XulMX
gSEAJRnywWdPX1F+2E/n4rP4N36tcXyZkxyVFW+m1LFaCpw=
-----END PRIVATE KEY-----
$ openssl pkey -text -noout -in client-key-ed25519.pem
Could not read key from client-key-ed25519.pem
4037E1B9007F0000:error:1608010C:STORE routines:ossl_store_handle_load_result:unsupported:../cryptostore/store_result.c:151:
Is there a reason for that or did I miss something?
Only your first (X9EC/P256) file is actually PKCS8, which doesn't really have versions; its version field is constant 0. Your second (Ed25519) file is v2 of RFC5958, the successor to PKCS8, which apparently is wanted here to include the (precomputed) publickey. Compare https://crypto.stackexchange.com/questions/59850/ed25519-pkcs8-private-key-example-from-ietf-draft-seems-malformed and https://crypto.stackexchange.com/questions/103608/will-the-value-of-the-version-fields-always-be-0-and-the-null-fields-always . And yes OpenSSL doesn't support RFC5958 v2.
You state the requirement as 'display the file content'. You can do that in OpenSSL by treating it as unknown/arbitrary ASN.1 data rather than a key:
$ openssl asn1parse -i <77472637.2
0:d=0 hl=2 l= 81 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :01
5:d=1 hl=2 l= 5 cons: SEQUENCE
7:d=2 hl=2 l= 3 prim: OBJECT :ED25519
12:d=1 hl=2 l= 34 prim: OCTET STRING [HEX DUMP]:04206A57A7DC8BC6AEB9A3763081875BF53829BE447B8A2D4A4A51C922CF97BA5317
48:d=1 hl=2 l= 33 prim: cont [ 1 ]
# the OCTET STRING at offset 12 _contains_ (wraps) the privatekey so
$ openssl asn1parse -i -strparse 12 <77472637.2
0:d=0 hl=2 l= 32 prim: OCTET STRING [HEX DUMP]:6A57A7DC8BC6AEB9A3763081875BF53829BE447B8A2D4A4A51C922CF97BA5317
# the _implicit_ BIT STRING at offset 48 contains/wraps the publickey
# but there's no way for OpenSSL to understand its type so handle manually
$ openssl base64 -d <77472637.2 | tail -c +52 | xxd -p -c32
2519f2c1674f5f517ed84fe7e2b3f8377ead717c99931c95156fa6d4b15a0a9c
# (hl=2 plus 1 byte for the 'unused' octet in a bitstring is 51,
# plus 1 because `tail` is one-origin is 52)
But this isn't really programming or development and probably offtopic.
OTOH if you want to use this key in OpenSSL, you need to remove the [1] publicKey field and set the version back to 0; OpenSSL will then regenerate the publickey when using it:
$ h=$(openssl base64 -d <77472637.2 | xxd -p -c83)
$ echo 302E020100${h:10:86} |xxd -p -r |openssl pkey -inform d -text # or other use or store or whatever
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIGpXp9yLxq65o3YwgYdb9TgpvkR7ii1KSlHJIs+XulMX
-----END PRIVATE KEY-----
ED25519 Private-Key:
priv:
6a:57:a7:dc:8b:c6:ae:b9:a3:76:30:81:87:5b:f5:
38:29:be:44:7b:8a:2d:4a:4a:51:c9:22:cf:97:ba:
53:17
pub:
25:19:f2:c1:67:4f:5f:51:7e:d8:4f:e7:e2:b3:f8:
37:7e:ad:71:7c:99:93:1c:95:15:6f:a6:d4:b1:5a:
0a:9c