PEM 格式的私钥有什么特别之处?
What is special for a private key to be PEM-formatted?
我正在尝试使用 Google API with a oAuth service account, with Python 3.4. One of the steps is to generate a JSON Web Token, for which I use PyJWT
。
我生成的代码如下:
# opening the certificate downloaded from the Google API console
# it is password protected by the standard password ('notasecret')
p12 = OpenSSL.crypto.load_pkcs12(open('certfromgoogle.p12', 'rb').read(), 'notasecret')
# extracting the private key from the certificate and dumping it to a PEM
# format (FILETYPE_PEM)
private_key = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey())
# at that stage, private_key contains the private key as
# b'-----BEGIN PRIVATE KEY-----\nMIICdg(...)FIyw==\n-----END PRIVATE KEY-----\n'
# trying to get the JWT
encoded = jwt.encode(claim, private_key, algorithm='RS256', headers={"alg": "RS256", "typ": "JWT"})
对 jwt.encode
的调用因 TypeError: Expecting a PEM-formatted key
而崩溃。完整回溯:
Traceback (most recent call last):
File "C:/Users/w_000/PycharmProjects/syncmagazines/testcrypto.py", line 20, in <module>
encoded = jwt.encode(claim, private_key, algorithm='RS256', headers={"alg": "RS256", "typ": "JWT"})
File "C:\Python34\lib\site-packages\jwt\api.py", line 118, in encode
key = alg_obj.prepare_key(key)
File "C:\Python34\lib\site-packages\jwt\algorithms.py", line 170, in prepare_key
raise TypeError('Expecting a PEM-formatted key.')
TypeError: Expecting a PEM-formatted key.
不过,似乎已正确提取私钥。
为什么这个格式不正确?
What is special for a private key to be PEM-formatted?
PEM 是一种表示编码。它有熟悉的 -----BEGIN XXX-----
和 -----END XXX-----
.
我认为 BEGIN PRIVATE KEY
是 PKCS #8 私钥。也许图书馆想要一个带有 BEGIN RSA PRIVATE KEY
的 PKCS #1 私钥。 BEGIN RSA PRIVATE KEY
也称为 传统 密钥编码(相对于 PKCS #8)。
您应该查看相关文档并以正确的格式提供密钥。
要从传统密钥转换为 PKCS #8 密钥,请参阅 pkcs(1)
. -topk8
is of interest. Also see How to convert PKCS#8-formatted PEM private key to the tranditional format?
的 OpenSSL 手册页
要将 PKCS #8 密钥转换为传统密钥,请参阅 rsa(1)
. Also see Convert PEM traditional private key to PKCS8 private key?
的 OpenSSL 手册页
在检查了 PyJWT 源代码后,很明显该库希望 PEM 数据为字符串类型,但您提供的是字节串(在您的问题中通过 b'...'
文字显而易见)。
有问题的函数是 prepare_key
, along with the definition of acceptable string types.
您必须将私钥数据解码为本机 str
类型:
private_key_bytes = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey())
private_key = private_key_bytes.decode('utf-8')
这似乎只对 Python 3 是必需的,但上面的代码也适用于 Python 2。
我正在尝试使用 Google API with a oAuth service account, with Python 3.4. One of the steps is to generate a JSON Web Token, for which I use PyJWT
。
我生成的代码如下:
# opening the certificate downloaded from the Google API console
# it is password protected by the standard password ('notasecret')
p12 = OpenSSL.crypto.load_pkcs12(open('certfromgoogle.p12', 'rb').read(), 'notasecret')
# extracting the private key from the certificate and dumping it to a PEM
# format (FILETYPE_PEM)
private_key = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey())
# at that stage, private_key contains the private key as
# b'-----BEGIN PRIVATE KEY-----\nMIICdg(...)FIyw==\n-----END PRIVATE KEY-----\n'
# trying to get the JWT
encoded = jwt.encode(claim, private_key, algorithm='RS256', headers={"alg": "RS256", "typ": "JWT"})
对 jwt.encode
的调用因 TypeError: Expecting a PEM-formatted key
而崩溃。完整回溯:
Traceback (most recent call last):
File "C:/Users/w_000/PycharmProjects/syncmagazines/testcrypto.py", line 20, in <module>
encoded = jwt.encode(claim, private_key, algorithm='RS256', headers={"alg": "RS256", "typ": "JWT"})
File "C:\Python34\lib\site-packages\jwt\api.py", line 118, in encode
key = alg_obj.prepare_key(key)
File "C:\Python34\lib\site-packages\jwt\algorithms.py", line 170, in prepare_key
raise TypeError('Expecting a PEM-formatted key.')
TypeError: Expecting a PEM-formatted key.
不过,似乎已正确提取私钥。
为什么这个格式不正确?
What is special for a private key to be PEM-formatted?
PEM 是一种表示编码。它有熟悉的 -----BEGIN XXX-----
和 -----END XXX-----
.
我认为 BEGIN PRIVATE KEY
是 PKCS #8 私钥。也许图书馆想要一个带有 BEGIN RSA PRIVATE KEY
的 PKCS #1 私钥。 BEGIN RSA PRIVATE KEY
也称为 传统 密钥编码(相对于 PKCS #8)。
您应该查看相关文档并以正确的格式提供密钥。
要从传统密钥转换为 PKCS #8 密钥,请参阅 pkcs(1)
. -topk8
is of interest. Also see How to convert PKCS#8-formatted PEM private key to the tranditional format?
要将 PKCS #8 密钥转换为传统密钥,请参阅 rsa(1)
. Also see Convert PEM traditional private key to PKCS8 private key?
在检查了 PyJWT 源代码后,很明显该库希望 PEM 数据为字符串类型,但您提供的是字节串(在您的问题中通过 b'...'
文字显而易见)。
有问题的函数是 prepare_key
, along with the definition of acceptable string types.
您必须将私钥数据解码为本机 str
类型:
private_key_bytes = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey())
private_key = private_key_bytes.decode('utf-8')
这似乎只对 Python 3 是必需的,但上面的代码也适用于 Python 2。