Gen*_*erd 6 cryptography rsa pseudocode pem jwk
这个问题更通用,而不是针对特定语言,因此我将解释我的问题以及我在伪代码中尝试过的内容。
我正在尝试从 JWK 集中生成 PEM 公钥。JWK 包括“e”(指数)和“n”(模)变量。我的问题是,在不使用任何库和 OpenSSL 命令行工具的情况下将此 JWK 转换为 PEM 的确切步骤是什么。
这是JWK供参考:
{
"kty": "RSA",
"alg": "RS512",
"kid": "26887d3ee3293c526c0e6dd05f122df53aa3f13d7dad06d25e266fa6f51db79fb52422aaf79f121476237e98dcd6640350fee47fec70e783544ec9a36e4605bc",
"use": "sig",
"n": "14m79mVwIE0JxQdKrgXVf7dVcBS90U0TvG7Yf7dG4NJocz1PNUrKrzGhe_FryOe0JahL_sjA2_rKw7NBCpuVx_zSPFRw6kqjewGicjXGus5Fmlf3zDuqwV4BWIFHyQexMPOly0agFfcM0M0MgBULXjINgBs9MwnRv7JVfRoGqXHsNM45djFDd3o4liu4LPlge_DquZUFLNu-BYAyAlWkz0H2TepZhGrN9VEPmxzQkNzXc1R4MpZvbxrRRgaAA2z094ik3hk86JhfyFq-LDcueZhtshmrYZ95LWgMlQ7PixkeK1HkeEYMt20lmNzR8B8KabimYmibxA4Ay9gpRwfp-Q",
"e": "AQAB"
}
Run Code Online (Sandbox Code Playgroud)
我的大部分研究源自node-jwk-to-pem库(可以在这里找到: https: //github.com/Brightspace/node-jwk-to-pem)和一个使用JOSE库的StackOverflow问题在 PHP 中(可以在这里找到:How to conversion a public key from a JWK into PEM for OpenSSL?)
根据我通过阅读上述库(加上一些其他文章和问题,但没有完全提到逐步过程)所发现的,我发现第一步是将模数和指数转换为整数(特别是 BigInt)。这通常会导致以下结果:
n = 27209154847141595039206198313134388207882403216639061643382959557246344691110642716248339592972939239825436848454712213431917464875221502188500634554426063986720722251339335488215426908010590565758292169712942346285217861588132983738839891250753593240057639347814778952277719613395670962156961452389927728643840215833830614315091417876959205843957512422401240879135352731575182574836052718961865690645602829768565458494497550672252951063585023601307115444743487394113997186698238507983094748342588645472362960665610355698438390751920697759620235642103374737421940385132232531739910444003185620313592808726865629407737
e = 65537
Run Code Online (Sandbox Code Playgroud)
使用此信息,我将如何从指数和模数生成 PEM 公钥?任何伪代码或建议都将是令人难以置信的!
RSA公钥n
由模数和指数定义e
。
您可以使用和字段直接从JWK 类型RSA
获取该信息:n
e
“n”(模数)参数包含 RSA 公钥的模值。它表示为 Base64urlUInt 编码值。
“e”(指数)参数包含 RSA 公钥的指数值。它表示为 Base64urlUInt 编码值。
要创建表示此公钥信息的 PEM 文件,您基本上需要构建其等效的 ASN.1 DER 编码表示形式,可能还需要一些前导码。在其原始形式中,它在RFC3447中是这样定义的:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
Run Code Online (Sandbox Code Playgroud)
ASN.1
定义用于表示任意数据结构的规则和类型,并且为此目的在密码学中广泛使用。
ASN.1 仅提供语法,但该信息的实际编码是使用不同的编码格式(尤其是 DER)执行的。
执行编码的方式并不简单:Let's Encrypt 提供了一篇关于该主题的优秀文章。出色的lapo.it/asn1js 站点还提供了一个用于检查 ASN.1 DER 编码信息的出色工具。
例如,考虑从下面提到的 SO 问题中提取的以下模数和指数:
SEQUENCE (2 elements)
INTEGER (2048 bit): EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
INTEGER (24 bit): 010001
Run Code Online (Sandbox Code Playgroud)
对应的ASN.1 DER编码如下:
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
Run Code Online (Sandbox Code Playgroud)
在 ASN.1 DER 中,每个元素都被编码为类型-长度-值三元组。
类型由标签标识,通常用一个字节进行编码。
例如,30
表示一个SEQUENCE
,而02
对应于一种INTEGER
类型。
上述文章提供了 ASN.1 定义的不同类型的列表以及相应的标签。
长度有点棘手:如果关联值的长度达到( ) 个字节,则由单个字节指示。如果字节数大于,则第一个长度字节指定实际定义长度的字节数。请考虑阅读本文的这一部分,我认为这是非常有解释性的。127
0x7F
127
Length
然后,您包括实际值。
在提供的示例中,30 82 01 0A
意味着:
30
: A 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
字节长,以第一个字节0x00填充的2048位模(参见前述文章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-----
) 。考虑阅读这个精彩的SO 问题和相关答案,它不仅详细解释了 RSA 公钥基础知识,还解释了这些不同表示形式的注意事项。
我创建了一个网站来实现将 PEM 资产转换为 JWK 并返回的特定目的: https: //jwkset.com/generate
您可以在下面看到相关页面的屏幕截图。如果您使用私钥,它是开源的并且易于自行托管。
docker run --rm -p 8080:8080 micahparks/jwksetcom
Run Code Online (Sandbox Code Playgroud)
该网站是https://github.com/MicahParks/jwkset开源项目的一部分,该项目是一个 Golang 包。它还发布了一个 CLI 工具来完成此任务。更多信息请参见网站屏幕截图。
CLI 工具jwksetinfer
可用于将一个或多个 PEM 编码资产转换为单个 JWK 集。
通过 Golang 工具链安装:
go install github.com/MicahParks/jwkset/cmd/jwksetinfer@latest
Run Code Online (Sandbox Code Playgroud)
用法:
jwksetinfer mykey.pem mycert.crt
Run Code Online (Sandbox Code Playgroud)
如果您正在寻找 Golang 代码示例,您可以观察此测试,其中涵盖以下 PEM 编码的 X.509 证书、SEC 1、PKCS #1、PKCS #8 和 PKIX。
归档时间: |
|
查看次数: |
11589 次 |
最近记录: |