X9.62 密钥的格式是什么?

信息安全 电子抄送 尼斯特 文件类型
2021-09-01 20:51:59

RFC8292包含这个 gem:

The "k" parameter includes an ECDSA public key [FIPS186] in
uncompressed form [X9.62] that is encoded using base64url encoding
[RFC7515].

在下面有一个使用这种键的例子:

Authorization: vapid
   t=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL3
     B1c2guZXhhbXBsZS5uZXQiLCJleHAiOjE0NTM1MjM3NjgsInN1YiI6Im1ha
     Wx0bzpwdXNoQGV4YW1wbGUuY29tIn0.i3CYb7t4xfxCDquptFOepC9GAu_H
     LGkMlMuCGSK2rpiUfnK9ojFwDXb1JrErtmysazNjjvW2L9OkSSHzvoD1oA,
   k=BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dR
     uU_RCPCfA5aq9ojSwk5Y2EmClBPs

关键是k=示例中的字段。

这似乎不是 ASN.1 格式:

$ cat vapidkey
-----BEGIN PUBLIC KEY-----
BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dRuU_RCPCfA5aq9ojSwk5Y2EmClBPs
-----END PUBLIC KEY-----
$ openssl asn1parse -in vapidkey -i
    0:d=0  hl=2 l=  13 prim: OCTET STRING      [HEX DUMP]:47C73CA2D5150CD5BE708F1B27
Error in encoding
139686682194112:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:91:

如何解析这种格式?

不幸的是,X9.62 标准似乎在付费墙后面。没关系,我不需要完整的标准,我只需要读取一个密钥并将其相关位传递给一个知道如何处理它的库。但这似乎比看起来更难;我尝试过的库不能立即理解这种格式,所以我必须自己做一些转换。但是,如果我不知道密钥的格式,那将非常困难。

2个回答

它确实不是 ASN.1。

(AFAIK 全部)X9.62 的格式在 SEC1 中复制,不受2.3.3 和 2.3.4 的曲线点(这是实际的公钥值,不包括元数据)的影响。

您拥有的未压缩点格式只是一个八位字节 04,后跟 X 和 Y 坐标,每个坐标都是一个大小由曲线下的字段确定的无符号 bigendian 整数,您需要已经知道 - 通常公钥是嵌入在 X.509 SPKI(见下文)中,用于识别曲线并因此提供其字段大小。压缩格式也很常见,它是一个八位字节 02 或 03,指定 Y 是偶数还是奇数(对于素数特征曲线,通常缩写为素数并表示为 Fp),仅后跟 X。

我从来没有见过任何实现 ECC 的库根本没有实现(X9.62)未压缩点格式,而且很少有没有实现压缩的库。对 ECDSA签名的格式存在分歧更为常见,但这不是您的情况。

另请注意,8292 和 7515 中使用的 base64url-unpadded 方案与 OpenSSL 使用的(传统)PEM/SMIME base64 不兼容。这两个“额外”字符是不同的,OpenSSL需要填充(如果不是 3 的精确倍数),并且在大多数情况下需要换行符。此外,'PUBLIC KEY' PEM 类型应该是 X.509 SubjectPublicKeyInfo 结构,在 OpenSSL API(和代码)中称为 PUBKEY,包括 SEQUENCE 和 AlgorithmIdentifier 以及 BIT STRING 包装,尽管这并不重要,因为你没有'不要试图将其作为任意 ASN.1 的密钥来读取。

对@dave_thompson_085 提供的答案略有补充。X9.62 中指定了第三种编码格式,在 SEC1 中没有复制:混合。

它基本上是未压缩的编码,但第一个字节编码 y 的均匀性,就像压缩格式一样。它由第一个字节中的 06 和 07 指定,它们与压缩后的 02 和 03 含义相同。