JSON Web Key (JWK) for public key requires x and y coordinates.

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

JSON Web Key (JWK) for public key requires x and y coordinates.

OpenSSL - User mailing list
Hello,

Not a genius with openssl or encryption at all. Thanks for reading.

Background:

* Generate a private key (really key set) with named curve:
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -pkeyopt ec_param_enc:named_curve -outform PEM -out account-privkey-prime256v1.pem
* Look at named curves representation:
openssl pkey -in account-privkey-prime256v1.pem -noout -text
* Look at explicit encoding ( I want x and y coordinates ):
openssl ec -in  account-privkey-prime256v1.pem -param_enc explicit -text -noout

Example output:
read EC key
Private-Key: (256 bit)
priv:
    ae:b7:b9:30:ed:3d:2f:03:b9:0c:bd:b8:39:b9:5c:
    39:33:c0:48:f1:45:a2:b4:8a:1b:4c:8c:86:f0:86:
    2a:5a
pub:
    04:68:1f:bc:7f:2b:c8:c3:c1:4d:5e:b1:2c:b5:29:
    62:d7:01:21:51:70:bc:e5:30:ab:10:96:c8:23:0a:
    7b:df:85:00:7b:fb:bb:58:4d:e6:4a:80:a6:ef:a1:
    be:df:72:08:48:e0:3c:13:d4:7d:f8:62:75:d0:d8:
    b5:aa:c2:b3:c1
Field Type: prime-field
Prime:
    00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
    00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff
A:   
    00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
    00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:fc
B:   
    5a:c6:35:d8:aa:3a:93:e7:b3:eb:bd:55:76:98:86:
    bc:65:1d:06:b0:cc:53:b0:f6:3b:ce:3c:3e:27:d2:
    60:4b
Generator (uncompressed):
    04:6b:17:d1:f2:e1:2c:42:47:f8:bc:e6:e5:63:a4:
    40:f2:77:03:7d:81:2d:eb:33:a0:f4:a1:39:45:d8:
    98:c2:96:4f:e3:42:e2:fe:1a:7f:9b:8e:e7:eb:4a:
    7c:0f:9e:16:2b:ce:33:57:6b:31:5e:ce:cb:b6:40:
    68:37:bf:51:f5
Order:
    00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff:
    ff:ff:bc:e6:fa:ad:a7:17:9e:84:f3:b9:ca:c2:fc:
    63:25:51
Cofactor:  1 (0x1)
Seed:
    c4:9d:36:08:86:e7:04:93:6a:66:78:e1:13:9d:26:
    b7:81:9f:7e:90

* RFC7518, sec. 6.2.1 requires for public key representation key-value pairs for keys 'crv', 'x', and 'y'.
The 'crv' value is easy. It's the line NIST CURVE: P-256 from the -text for named curve format, not shown above.
The 'x' and the 'y' are not shown. My guess from looking online is that x and y are in the value for openssl -text
value 'pub'. In output above, pub value (abbreviated) is 04:68...b3:c1. I have not been successful in unpacking
the pub value to show anything coherent. I think the colons can be dropped and what's left can be decoded
base64 or base64url. My openssl (Debian linux) has no 'base64' subcommand.

I have found nothing online about this. I figure this should be important. Typically, lack of relevant documentation online means I am making a very original mistake. I am not subscribed to the [hidden email] mailing list. I can of course check
the archives and see if this went into it.

What am I doing wrong? I think it's a conceptual thing. I am not a C programmer and don't exactly want to figure out how to use the C functions. Even so, I am interested in what's a reasonable  approach, even if not so reasonable for me. I must be doing something unreasonable. Thanks. Happy Holidays if that applies to you.

Bonus Question: Do I or should I worry about seeding for the Pseudorandom Number Generator (PRNG). It seems to me that it would be nice to get a pseudo-random number and just mess it up a bit in a text editor and use that as the seed for making a new key. Just a guess. If you have an informed thought on that, I'd be interested.

Thanks for openssl and everything! It's indispensible free software.

Douglas Morris
Reply | Threaded
Open this post in threaded view
|

Re: JSON Web Key (JWK) for public key requires x and y coordinates.

Nicola Tuveri-2
Hi Douglas,

I don't think OpenSSL supports the encoding of keys specified in
RFC7518: you are right in believing that the x and y values can be
retrieved from the 'pub:' field of the `-text` output for the key, but
that field conforms to Sec 2.3.4 of the SEC1 standard (which is
referenced also by RFC7518, although they preferred to use a custom
representation for the curve point).

If I am reading RFC7518 correctly, you would need a piece of software
that would take the affine x and y coordinate for the public EC point
encoded as the base64 encoding of the octet representation of a field
element (zero padded to the byte length of the field order).

It is possible to achieve this writing a C/C++ program using the
OpenSSL API, but as far as I know, no OpenSSL CLI tool currently
supports that format.

With a quick glance at Google results though, it seems that many
modules supporting JOSE for NodeJS/Ruby/Erlang/Elixir/Python also have
methods to parse a public key PEM file and transform into an RFC7518
key.
So depending on what language you are using to develop your
application you should be able to call something like
`JOSE::JWK::from_pem_file('pubkey.pem')` and obtain an object
representing the public key that can be exported to the RFC7518
encoding.

In Ruby, for example, using the 'jose' gem, you could:

```sh
$ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1
-pkeyopt ec_param_enc:named_curve -outform PEM -out
account-privkey-prime256v1.pem
$ openssl pkey -in account-privkey-prime256v1.pem -pubout -out
account-pubkey-prime256v1.pem
$ ruby -e 'require "jose"; puts
JOSE::JWK::from_pem_file("account-pubkey-prime256v1.pem").to_map.to_h'
{"y"=>"vUFxfD2pBMjv-iaX8zKnNeXe2GaZcspLdnyoPzEK89w", "kty"=>"EC",
"crv"=>"P-256", "x"=>"-3zPuCvv1VTw1hs5X4pCLkj3QQjocw9lYEKxqKG27W8"}
```

Bonus answer: I am not an expert on the RAND module of OpenSSL, but
the short answer should be that if you are using the latest release of
OpenSSL, most likely you don't need to worry about seeding manually
the PRNG, as the RAND module should be doing everything it can to
gather the required entropy from the facilities provided by your
platform and feeding it through a state-of-the-art cryptographic PRNG
implementation to obtain the cryptographically secure randomness
needed, e.g. for the key generation above.
Of course I cannot say anything about the functionality provided by
whatever framework you are going to use for the rest of your RFC7518
operations, as what they use depends on their cryptographic backend
(which could be OpenSSL or some other software).



Best regards (and Happy Holidays to you as well)

Nicola Tuveri