如何在python中创建JWKS公钥/私钥对?

问题描述 投票:0回答:3

如何创建 JWKS 公钥/私钥对,类似于可以在 https://mkjwk.org/ 手动创建的密钥对,其中包括 密钥 ID (

kid
) 和 密钥使用
use
)?我使用
cryptography
模块生成 RSA 密钥对,并使用
python-jose
将密钥提取为 JWK,但创建的密钥不包括
kid
use
(毫不奇怪,因为它们尚未在任何地方指定) .

代码:

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
​
from jose import jwk, constants
import json
​
key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)
public_key = key.public_key().public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)
private_key = key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.TraditionalOpenSSL,
    encryption_algorithm=serialization.NoEncryption()
)
​
print(json.dumps(jwk.RSAKey(algorithm=constants.Algorithms.RS256, key=public_key.decode('utf-8')).to_dict()))
print(json.dumps(jwk.RSAKey(algorithm=constants.Algorithms.RS256, key=private_key.decode('utf-8')).to_dict()))

通过上述代码片段生成公钥(无

kid
use
属性):

{
    "alg": "RS256",
    "kty": "RSA",
    "n": "tqbcR_6JC....OKQ",
    "e": "AQAB"
}
python python-3.x cryptography public-key-encryption
3个回答
7
投票

使用

jwcrypto
库生成 JWKS 公钥/私钥对的另一种方法:

from jwcrypto import jwk

key = jwk.JWK.generate(kty='RSA', size=2048, alg='RSA-OAEP-256', use='enc', kid='12345')
public_key = key.export_public()
private_key = key.export_private()

通过上面的代码片段生成公钥:

{
    "kty": "RSA",
    "alg": "RSA-OAEP-256",
    "kid": "12345",
    "use": "enc",
    "e": "AQAB",
    "n": "0YclBn...vV7y7w"
}

1
投票

我相信

kid
只是一段元数据(任何字符串),在生成密钥的过程中没有使用。

对于

use
来说,它可能有点相似,但根据您想要不同的非对称加密方案的用途(您可以参考最知名的非对称加密系统 RSA 的加密和签名方案)描述)。

总而言之,您很可能可以根据上述信息向 JSON 字典添加适当的键来重新创建 JSON 的精确结构。


0
投票

您可以使用以下代码生成 JWKS,其中包括有关证书的信息(例如 x5t、x5c)。 由于证书中已经包含了公钥的信息,所以不需要单独传递公钥。

要了解有关如何为 JWT 生成数字签名 RSA 对的更多信息,请参阅此处

import base64
import json

from cryptography.hazmat.primitives.hashes import SHA1
from jose import constants, jwk
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization


class JWKSGenerator:
    def __init__(
        self,
        *,
        file_path: str,
        kid: str,
        use: str = 'sig',
    ) -> None:
        with open(file_path, 'rb') as f:
            self._cert_pem_raw_data: bytes = f.read().strip()

        self._cert = x509.load_pem_x509_certificate(self._cert_pem_raw_data, default_backend())
        self._kid = kid
        self._use = use

    def _create_x5t(self, ):
        digest = self._cert.fingerprint(algorithm=SHA1())
        return base64.b64encode(digest).decode('utf-8')

    def _create_x5c(self, ):
        cert_val = self._cert.public_bytes(serialization.Encoding.DER)
        return base64.b64encode(cert_val).decode('utf-8')

    def process(self):
        jwks = jwk.RSAKey(algorithm=constants.Algorithms.RS256, key=self._cert_pem_raw_data).to_dict()

        jwks.update({
            "x5t": self._create_x5t(),
            "x5c": [
                self._create_x5c()
            ],
            "kid": self._kid,
            "use": self._use,
        })
        print(json.dumps(jwks, indent=4))
        return jwks


JWKSGenerator(
    file_path='<complete path to certificate pem file>',
    kid="key_id_123",
).process()

如果您尚未进行数字签名,您可以使用@Anand Jayabalan 提供的

© www.soinside.com 2019 - 2024. All rights reserved.