opensslpublic-keysecret-keypkcs#8

How can I show the content of a PKCS#8v2 files using openssl?


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?


Solution

  • 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