Encryption 如何通过openssl将jwk转换为公钥

Encryption 如何通过openssl将jwk转换为公钥,encryption,openssl,public-key-encryption,elliptic-curve,jwk,Encryption,Openssl,Public Key Encryption,Elliptic Curve,Jwk,我有一个JWE和一个临时公钥。 所以我有坐标X和Y 我在shell模式下的问题是如何将JWK转换为pem格式的ECC公钥 例如,这里有一个jwk {"epk":{"kty":"EC","crv":"P-256","x":"GCl--lQHb7NKYU3jXpKVI_BYaTlALT5JFPdl3sbB9mY","y":"ADRX25PBSlZJE79drET0ARtRqZAkUIMNt9aa2bbjBYY"}} 在我这样做之后 > # I convert the x coordonate

我有一个JWE和一个临时公钥。 所以我有坐标X和Y

我在shell模式下的问题是如何将JWK转换为pem格式的ECC公钥

例如,这里有一个jwk

{"epk":{"kty":"EC","crv":"P-256","x":"GCl--lQHb7NKYU3jXpKVI_BYaTlALT5JFPdl3sbB9mY","y":"ADRX25PBSlZJE79drET0ARtRqZAkUIMNt9aa2bbjBYY"}}
在我这样做之后

> # I convert the x coordonate from base64url to base64
> echo -n -e "GCl++lQHb7NKYU3jXpKVI/BYaTlALT5JFPdl3sbB9mY" | base64 -d | hexdump

0000000 2918 fa7e 0754 b36f 614a e34d 925e 2395
0000010 58f0 3969 2d40 493e f714 de65 c1c6 66f6
0000020

> echo -n -e "ADRX25PBSlZJE79drET0ARtRqZAkUIMNt9aa2bbjBYY" | base64 -d | hexdump

0000000 3400 db57 c193 564a 1349 5dbf 44ac 01f4
0000010 511b 90a9 5024 0d83 d6b7 d99a e3b6 8605
0000020
所以公钥是 04 2918 fa7e 0754 b36f 614a e34d 925e 2395 58f0 3969 2d40 493e f714 de65 c1c6 66f6 3400 db57 c193 564a 1349 5dbf 44ac 01f4 511b 90a9 5024 0d83 d6b7 d99a e3b6 8605

但我有曲线,公钥,我想知道如何生成pem

换句话说,

我有一个文件mykey.pub,其中包含以下内容:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETGUwowNEfqQ0LtHiMXJPY+Os5pXc
lsYCRPOi3F6K0n4k1RjJ7PGp/9RhZy3XS1yn1Qlu4hoCClHcc9rPXPn4fQ==
-----END PUBLIC KEY-----
我执行此命令以显示公钥:

> openssl ec -in mykey.pub -pubin -text -noout
read EC key
Public-Key: (256 bit)
pub:
    04:4c:65:30:a3:03:44:7e:a4:34:2e:d1:e2:31:72:
    4f:63:e3:ac:e6:95:dc:96:c6:02:44:f3:a2:dc:5e:
    8a:d2:7e:24:d5:18:c9:ec:f1:a9:ff:d4:61:67:2d:
    d7:4b:5c:a7:d5:09:6e:e2:1a:02:0a:51:dc:73:da:
    cf:5c:f9:f8:7d
ASN1 OID: prime256v1
NIST CURVE: P-256

所以我的问题是我是否有这些数据

> openssl ec -in mykey.pub -pubin -text -noout
read EC key
Public-Key: (256 bit)
pub:
    04:4c:65:30:a3:03:44:7e:a4:34:2e:d1:e2:31:72:
    4f:63:e3:ac:e6:95:dc:96:c6:02:44:f3:a2:dc:5e:
    8a:d2:7e:24:d5:18:c9:ec:f1:a9:ff:d4:61:67:2d:
    d7:4b:5c:a7:d5:09:6e:e2:1a:02:0a:51:dc:73:da:
    cf:5c:f9:f8:7d
ASN1 OID: prime256v1
NIST CURVE: P-256

如何在shell模式下检索此文件

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETGUwowNEfqQ0LtHiMXJPY+Os5pXc
lsYCRPOi3F6K0n4k1RjJ7PGp/9RhZy3XS1yn1Qlu4hoCClHcc9rPXPn4fQ==
-----END PUBLIC KEY-----

首先让我简要描述一下您的目标格式。您想要获得的是PEM编码的SubjectPublicKeyInfo(SPKI)文件。PEM编码本质上是DER编码(二进制格式),然后使用页眉和页脚对base64进行编码。SPKI结构在RFC5280中定义(见第4.1节):

因此,二进制DER编码中的第一个字节块由一个标头组成,该标头标识正在使用的算法(其中一部分包括曲线)。最后一个字节是原始公钥(曲线上编码的x和y坐标)

由于示例关键点与要创建的关键点对应的曲线相同,因此它将具有相同的算法标识符头字节。使用mykey.pub文件,我们可以将其转换为二进制DER格式:

$ openssl ec -in mykey.pub -pubin -outform DER -out key.der
让我们看一下内容:

$ hexdump -C key.der
00000000  30 59 30 13 06 07 2a 86  48 ce 3d 02 01 06 08 2a  |0Y0...*.H.=....*|
00000010  86 48 ce 3d 03 01 07 03  42 00 04 4c 65 30 a3 03  |.H.=....B..Le0..|
00000020  44 7e a4 34 2e d1 e2 31  72 4f 63 e3 ac e6 95 dc  |D~.4...1rOc.....|
00000030  96 c6 02 44 f3 a2 dc 5e  8a d2 7e 24 d5 18 c9 ec  |...D...^..~$....|
00000040  f1 a9 ff d4 61 67 2d d7  4b 5c a7 d5 09 6e e2 1a  |....ag-.K\...n..|
00000050  02 0a 51 dc 73 da cf 5c  f9 f8 7d                 |..Q.s..\..}|
0000005b
您可以看到上面打印出来的公钥的第一个字节,从偏移量0x1a开始(即26个字节):
04 4c 65 30…
。原始公钥数据一直延伸到文件末尾,长度为65字节。这包括一个前导0x04字节,后跟32字节的x坐标和32字节的y坐标。前导0x04告诉我们坐标是如何表示的。0x04表示“未压缩”-这很方便,因为这是我们最容易处理的。我们还将对目标密钥使用未压缩格式。因此,我们需要从示例密钥中获取头的前26个字节加上0x04字节(总共27个字节):

$ head -c 27 key.der >key.head
为了验证我们得到了我们期望的结果:

$ hexdump -C key.head
00000000  30 59 30 13 06 07 2a 86  48 ce 3d 02 01 06 08 2a  |0Y0...*.H.=....*|
00000010  86 48 ce 3d 03 01 07 03  42 00 04                 |.H.=....B..|
0000001b
现在我们创建坐标的x和y元素,您已经这样做了:

$ echo -n "GCl++lQHb7NKYU3jXpKVI/BYaTlALT5JFPdl3sbB9mY=" | base64 -d >key.x
$ echo -n "ADRX25PBSlZJE79drET0ARtRqZAkUIMNt9aa2bbjBYY=" | base64 -d >key.y
然后将所有元素放在一起:

cat key.head key.x key.y >keynew.der
我们可以将DER格式的新密钥转换为PEM格式:

$ openssl ec -in keynew.der -inform DER -pubin -out keynew.pem
这给了我们:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGCl++lQHb7NKYU3jXpKVI/BYaTlA
LT5JFPdl3sbB9mYANFfbk8FKVkkTv12sRPQBG1GpkCRQgw231prZtuMFhg==
-----END PUBLIC KEY-----
为了检查它是否正常:

$ openssl ec -in keynew.pem -pubin -noout -text
read EC key
Public-Key: (256 bit)
pub:
    04:18:29:7e:fa:54:07:6f:b3:4a:61:4d:e3:5e:92:
    95:23:f0:58:69:39:40:2d:3e:49:14:f7:65:de:c6:
    c1:f6:66:00:34:57:db:93:c1:4a:56:49:13:bf:5d:
    ac:44:f4:01:1b:51:a9:90:24:50:83:0d:b7:d6:9a:
    d9:b6:e3:05:86
ASN1 OID: prime256v1
NIST CURVE: P-256

我还有一个问题,我有临时公钥和私钥。使用openssl,我生成派生密钥
openssl pkeyutl-deriver-inkey../mykey.key-peerkey-keynew.pem-out secret_key.bin
。但字节是由两个字节组成的组反转的。我不知道为什么:密钥必须是
e6030796243ce743acc266e18122bf411e90538dec4c67d7c5b4033e180ad10c
,但使用openssl我获得
03e6 9607 3c24 43e7 c2ac e166 2281 41bf 901e 8d53 4cec d767 b4c5 3e03 a18 0cd1
。你知道为什么吗?我猜你正在使用没有格式字符串的“hextump”来显示键。默认情况下,它以2字节块的形式解释和显示值。整个2字节值被解释为单个整数值并显示。这将在little endian系统上给出奇怪的结果。请尝试“hextump-C”以获得更可读的输出
$ openssl ec -in keynew.pem -pubin -noout -text
read EC key
Public-Key: (256 bit)
pub:
    04:18:29:7e:fa:54:07:6f:b3:4a:61:4d:e3:5e:92:
    95:23:f0:58:69:39:40:2d:3e:49:14:f7:65:de:c6:
    c1:f6:66:00:34:57:db:93:c1:4a:56:49:13:bf:5d:
    ac:44:f4:01:1b:51:a9:90:24:50:83:0d:b7:d6:9a:
    d9:b6:e3:05:86
ASN1 OID: prime256v1
NIST CURVE: P-256