首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将JWK转换为PEM

如何将JWK转换为PEM
EN

Stack Overflow用户
提问于 2022-02-03 15:32:42
回答 1查看 2.5K关注 0票数 3

这个问题是更通用的,而不是特定的语言,所以我将解释我的问题和我用伪代码尝试了什么。

我正在尝试从JWK集生成一个PEM公钥。JWK包含"e“(指数)和"n”(模量)变量。我的问题是,在不使用任何库和不使用OpenSSL命令行工具的情况下,将JWK转换为PEM的确切步骤是什么。

以下是可供参考的JWK:

代码语言:javascript
复制
{
  "kty": "RSA",
  "alg": "RS512",
  "kid": "26887d3ee3293c526c0e6dd05f122df53aa3f13d7dad06d25e266fa6f51db79fb52422aaf79f121476237e98dcd6640350fee47fec70e783544ec9a36e4605bc",
  "use": "sig",
  "n": "14m79mVwIE0JxQdKrgXVf7dVcBS90U0TvG7Yf7dG4NJocz1PNUrKrzGhe_FryOe0JahL_sjA2_rKw7NBCpuVx_zSPFRw6kqjewGicjXGus5Fmlf3zDuqwV4BWIFHyQexMPOly0agFfcM0M0MgBULXjINgBs9MwnRv7JVfRoGqXHsNM45djFDd3o4liu4LPlge_DquZUFLNu-BYAyAlWkz0H2TepZhGrN9VEPmxzQkNzXc1R4MpZvbxrRRgaAA2z094ik3hk86JhfyFq-LDcueZhtshmrYZ95LWgMlQ7PixkeK1HkeEYMt20lmNzR8B8KabimYmibxA4Ay9gpRwfp-Q",
  "e": "AQAB"
}

我的大部分研究来源于节点-jwk到-pem库(在这里可以找到:https://github.com/Brightspace/node-jwk-to-pem)和StackOverflow问题(在PHP中使用JOSE库(在这里可以找到:如何将OpenSSL的公钥从JWK转换为PEM?) )。

通过阅读上面提到的库(再加上其他几篇文章和问题,没有提到逐步的过程),我发现第一步是将模数和指数转换为整数(特别是BigInt)。这通常导致以下情况:

代码语言:javascript
复制
n = 27209154847141595039206198313134388207882403216639061643382959557246344691110642716248339592972939239825436848454712213431917464875221502188500634554426063986720722251339335488215426908010590565758292169712942346285217861588132983738839891250753593240057639347814778952277719613395670962156961452389927728643840215833830614315091417876959205843957512422401240879135352731575182574836052718961865690645602829768565458494497550672252951063585023601307115444743487394113997186698238507983094748342588645472362960665610355698438390751920697759620235642103374737421940385132232531739910444003185620313592808726865629407737
e = 65537

利用这些信息,我将如何从指数和模数生成PEM公钥?任何伪代码或建议都会令人难以置信!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-12 22:34:03

RSA公钥是由模n和指数e定义的。

您可以使用RSAe字段直接从e获取该信息:

"n“(模数)参数包含RSA公钥的模值。它表示为Base64urlUInt编码的值。"e“(指数)参数包含RSA公钥的指数值。它表示为Base64urlUInt编码的值。

要创建一个表示此公钥信息的PEM文件,您基本上需要构建其等效的ASN.1 DER编码表示形式,可能需要有一些前导。在其原始形式中,它在RFC3447中的定义如下

代码语言:javascript
复制
RSAPublicKey ::= SEQUENCE {
  modulus           INTEGER,  -- n
  publicExponent    INTEGER   -- e
}

ASN.1定义了用于表示任意数据结构的规则和类型,并在密码学中被广泛用于此目的。

ASN.1只给出一个语法,但是实际的信息编码是使用不同的编码格式执行的,特别是DER。

编码的执行方式是非常重要的:让我们加密提供有关主题的一篇优秀文章。伟大的Apo.it/asn1js站点也为检查ASN.1编码信息提供了一个极好的工具。

例如,从下面提到的SO问题中提取以下模数和指数:

代码语言:javascript
复制
SEQUENCE (2 elements)
   INTEGER (2048 bit): EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
   INTEGER (24 bit): 010001

对应的ASN.1 DER编码如下:

代码语言:javascript
复制
30 82 01 0A      ;sequence (0x10A bytes long)
   02 82 01 01   ;integer (0x101 bytes long)
      00 EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
   02 03         ;integer (3 bytes long)
      010001

在ASN.1 DER中,每个元素都被编码为类型长度值三重奏.

类型由标记标识,通常用一个字节编码。

例如,30的意思是SEQUENCE,而02则对应于INTEGER类型。

上述文章提供了ASN.1定义的带有相应标记的不同类型的列表。

长度有点棘手:如果关联的值高达127 (0x7F)字节长,则由单个字节表示。如果字节数大于127,则第一个长度字节指定实际定义长度的字节数。请考虑阅读Length一节的这篇文章,我认为它是非常解释性的。

然后,将实际值包括在内。

在提供的示例中,30 82 01 0A意味着:

  • 30:一个SEQUENCE
  • 82:长度字节。0x82 & 0x7F -> 0x02实际值长度以2字节表示。
  • 01 0A:实际值长度,266字节长。

现在,值02 82 01 01 00 EB506399F5C612F5A67A09C119...

  • 02:一个INTEGER
  • 82:长度字节。再说一遍,0x82 & 0x7F -> 0x02。实际值长度以2字节表示。
  • 01 01:实际值长度,257字节长,模数2048位,加上第一个字节0x00 (参见上述条款中的Integer padding部分)。
  • 00 EB506399F5C612F5A67A09C119:填充模量值。

最后,02 03 010001

  • 02:一个INTEGER
  • 03:指数值是3字节长。
  • 010001:指数值。

然后,应该将结果编码为base64,并将其封装在特殊的文本分隔符中,例如,-----BEGIN RSA PUBLIC KEY----------END RSA PUBLIC KEY-----

请注意,您有几个选项可以表示PEM格式的键,上面描述的选项是PKCS#1,以及更通用的X.509,它们适合于以不同格式表示键(表单-----BEGIN PUBLIC KEY-----之一)。考虑阅读这个精彩的所以问题和相关的答案,它不仅非常详细地解释了RSA公钥的基本原理,而且还解释了这些不同表示的注意事项。

考虑阅读,,特别是另一个,所以问题,我认为它们也会有帮助。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70974044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档