在本地,我有一个 .env 文件,其中包含单行 RSA 密钥,如下所示:
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\ncontentsofkey\n-----END RSA PRIVATE KEY-----\n"
每 64 个字符包含一个
\n
以转义新行。
此密钥格式在本地工作并允许我的 Python 应用程序按预期运行,私钥能够加载。
问题始于生产。我将私钥一行格式复制并粘贴到 GitHub Secret 中,但是完全相同的密钥和格式会引发此错误:
ValueError: ('无法反序列化密钥数据。数据可能格式不正确,可能使用不支持的算法加密,或者可能是不支持的密钥类型(例如具有显式参数的 EC 曲线)。', [
])
在处理上述异常的过程中,又发生了一个异常:
ValueError: ('无法反序列化密钥数据。数据可能格式不正确,可能使用不支持的算法加密,或者可能是不支持的密钥类型(例如具有显式参数的 EC 曲线)。', [
])
正如reason_text中所述,似乎不支持密钥格式并且没有状态行?这让我非常困惑,因为这是在本地工作的,但在生产中却不起作用。在生产中,当我测试本地时,我使用完全相同的requirements.txt和python版本运行venv。
我在 load_pem_private_key() 函数之前添加了一条打印语句来查看密钥的格式,它的打印格式与我的 .env 文件完全相同......在本地工作得很好:
"-----BEGIN RSA PRIVATE KEY-----\ncontentsofkey\n-----END RSA PRIVATE KEY-----\n"
我没有看到本地打印语句和生产中的打印语句之间有任何区别,以查看按键是否在某处被操作。
有人遇到过这种情况吗?我需要将私钥存储在一行中,否则 GitHub Actions 工作流程会返回 YAML 语法错误。
这是我正在使用的代码,它在本地运行得很好,但在生产中却不起作用:
now = int(time.time())
payload = {"iat": now, "exp": now + expiration, "iss": self.id}
print(self.key)
# This line below is throwing the error showed above
encrypted = jwt.encode(payload, key=self.key, algorithm="RS256")
if isinstance(encrypted, bytes):
encrypted = encrypted.decode("utf-8")
return encrypted
上面代码中的打印语句用于调试目的。
有什么想法吗?加密包抛出
_handle_key_loading_error
为 load_pem_public_key
这是 GitHub 工作流程:
- name: Deploy secrets
if: ${{ github.event_name == 'release' || github.event_name == 'workflow_dispatch' }}
run: |
eval "echo \"$(cat .deployment/secret.yaml)\"" | kubectl apply -f -
env:
GITHUBAPP_KEY: '${{ secrets.PRIVATE_KEY }}'
下面是k8的secret的部署文件
apiVersion: v1
kind: Secret
metadata:
name: xxx
namespace: xxx
type: Opaque
stringData:
GITHUBAPP_KEY: '${GITHUBAPP_KEY}'
我试图模仿你的场景。直接使用单行键创建变量效果很好。但是,当通过
yaml
模块从 YAML 文件读取时,它包含 \\n
而不是 \n
。我遇到了与 \\n
相同的反序列化失败错误。将它们替换为 \n
解决了问题,之后 jwt.encode()
开始正常工作。
在下面的示例中,
key
是直接赋值的变量,key1
是从YAML文件中读取的(观察转义字符和大小差异):
>>> key
'-----BEGIN RSA PRIVATE KEY-----\nKEY\n-----END RSA PRIVATE KEY-----'
>>> key1
'-----BEGIN RSA PRIVATE KEY-----\\nKEY\\n-----END RSA PRIVATE KEY-----'
>>> len(key)
1650
>>> len(key1)
1652
这是测试流程(
TEST_PRIVATE_KEY
是单行私钥):
name: python_jwt
on: workflow_dispatch
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Create secret.yaml
env:
GITHUBAPP_KEY: '${{ secrets.TEST_PRIVATE_KEY }}'
shell: bash
run: |
cat > secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: xxx
namespace: xxx
type: Opaque
stringData:
GITHUBAPP_KEY: '${GITHUBAPP_KEY}'
EOF
eval "echo \"$(cat secret.yaml)\"" > secret-new.yaml
ls -l secret*
- name: JWT
shell: python
run: |
import yaml, time, jwt
with open('secret.yaml') as f:
secret = yaml.safe_load(f)
key = secret['stringData']['GITHUBAPP_KEY'].encode().replace(b'\\n', b'\n')
print(f'{len(key)} | {key}')
now = int(time.time())
payload = {"iat": now, "exp": now, "iss": "123456"}
encrypted = jwt.encode(payload, key=key, algorithm="RS256")
print(f'encrypted: {encrypted}')
输出:
您需要在您这边验证这一点,并找出传递给
jwt.encode()
的实际密钥。