无法通过private key.pem加密JSON:Passbase元数据加密故障排查
Passbase元数据加密问题排查与修复
背景
我正在使用KYC提供商Passbase,需采用4096位PEM证书加密元数据。已生成公私钥对并将公钥提供给对方,密钥生成命令:
openssl genrsa -out ~/passbase-test-private-key.pem 4096 openssl rsa -in ~/passbase-test-private-key.pem -out ~/passbase-test-public-key.pub -pubout
官方加密示例
官方给出的参考代码:
import base64 import subprocess import tempfile metadata = bytearray('{"foo": "bar"}', 'utf-8') with open("~/passbase-test-private-key.pem", "rb") as f: p = subprocess.Popen( "openssl rsautl -sign -inkey " + f.name, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate(input=metadata) encrypted_metadata = base64.b64encode(stdout)
自定义修改(问题代码)
因私钥存储在Google Secret Manager,测试阶段先将私钥放入.env文件,修改后的加密函数:
def encrypt_metadata(data): metadata = bytearray(str(data), 'utf-8') ENCRYPTION_KEY = os.environ.get('private_rsa_passbase_key') #encrypt metadata p = subprocess.Popen(ENCRYPTION_KEY, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate(input=metadata) encrypted_metadata = base64.b64encode(stdout) print (p,stdout,stderr,encrypted_metadata) return encrypted_metadata
错误输出
运行后无法生成加密元数据,错误信息:
<Popen: returncode: 2 args: ['-', '-', '-', '-', '-', 'B', 'E', 'G', 'I', 'N...> b'' b'/bin/sh: --: invalid option\nUsage:\t/bin/sh [GNU long option] [option] ...\n\t/bin/sh [GNU long option] [option] script-file ...\nGNU long options:\n\t--debug\n\t--debugger\n\t--dump-po-strings\n\t--dump-strings\n\t--help\n\t--init-file\n\t--login\n\t--noediting\n\t--noprofile\n\t--norc\n\t--posix\n\t--protected\n\t--rcfile\n\t--restricted\n\t--verbose\n\t--version\n\t--wordexp\nShell options:\n\t-irsD or -c command or -O shopt_option\t\t(invocation only)\n\t-abefhkmnptuvxBCHP or -o option\n' b''
问题根源
你直接把私钥文本传给了subprocess.Popen的命令参数,Shell将私钥开头的-----BEGIN RSA PRIVATE KEY-----识别为非法命令选项--,导致报错。
修复方案
方案1:临时文件存储私钥(兼容openssl命令)
通过临时文件存储从环境变量读取的私钥,再传入openssl命令,避免直接暴露私钥内容:
import base64 import subprocess import tempfile import os def encrypt_metadata(data): metadata = bytearray(str(data), 'utf-8') private_key = os.environ.get('private_rsa_passbase_key') # 创建自动清理的临时私钥文件 with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_key: tmp_key.write(private_key) try: # 构造正确的openssl签名命令 cmd = f"openssl rsautl -sign -inkey {tmp_key.name}" p = subprocess.Popen( cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, stderr = p.communicate(input=metadata) if p.returncode != 0: raise Exception(f"加密失败:{stderr.decode('utf-8')}") return base64.b64encode(stdout) finally: # 强制删除临时文件,避免私钥泄露 os.unlink(tmp_key.name)
方案2:使用PyCryptodome库(更安全高效)
避免调用外部openssl进程,直接用Python加密库实现,无Shell注入风险:
import base64 import os from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 def encrypt_metadata(data): metadata = bytearray(str(data), 'utf-8') private_key_bytes = os.environ.get('private_rsa_passbase_key').encode('utf-8') # 导入私钥并执行签名加密 rsa_key = RSA.import_key(private_key_bytes) hash_obj = SHA256.new(metadata) signature = pkcs1_15.new(rsa_key).sign(hash_obj) return base64.b64encode(signature)
注意:需要先安装依赖库:
pip install pycryptodome
内容的提问来源于stack exchange,提问作者Alexander Thomsen
相关产品推荐
相关产品推荐

