python os.system:意外标记“(”附近的语法错误 - 嵌套括号

python os.system:意外标记“(”附近的语法错误 - 嵌套括号

我读过,当从 python 提交命令时,我可以将 bash 括号放在引号中。在本例中,我尝试使用在 shell 上运行的命令为 openssl 创建密钥和 csr,但从 python 执行时则不然。我尝试了几种组合,但不断遇到其他问题。

以下 python 命令失败:

import os

os.system('openssl req -nodes -newkey rsa:2048 -sha256 -keyout mynode.key -out mynode.csr -subj "/C=US/ST=Florida/L=St Petersburg/O=MyCompany/OU=MyOU/CN=mynode/[email protected]" -reqexts OPTS -config <(cat /etc/pki/tls/openssl.cnf <(printf "[OPTS]\  basicConstraints = CA:FALSE  subjectAltName = DNS:mynode,DNS:myf5  keyUsage = digitalSignature, keyEncipherment  extendedKeyUsage = serverAuth, clientAuth"))')

底层 openssl 命令成功:

openssl req -nodes -newkey rsa:2048 -sha256 -keyout mynode.key -out mynode.csr -subj "/C=US/ST=Florida/L=St Petersburg/O=MyCompany/OU=MyOU/CN=mynode/[email protected]" -reqexts OPTS -config <(cat /etc/pki/tls/openssl.cnf <(printf "[OPTS]\  basicConstraints = CA:FALSE  subjectAltName = DNS:mynode,DNS:myf5  keyUsage = digitalSignature, keyEncipherment  extendedKeyUsage = serverAuth, clientAuth"))

这一定很简单,但我却找不到答案。

答案1

<(…)是进程替换,它存在于 bash(以及 ksh 和 zsh)中,但不存在于普通 sh 中。该system函数调用 sh,而不是 bash。

您可以使用管道代替 上的进程替换openssl,并将嵌套进程替换简化为简单的命令序列。

{ cat /etc/pki/tls/openssl.cnf;
  printf "[OPTS]\  basicConstraints = CA:FALSE  subjectAltName = DNS:mynode,DNS:myf5  keyUsage = digitalSignature, keyEncipherment  extendedKeyUsage = serverAuth, clientAuth";
} | openssl req -nodes -newkey rsa:2048 -sha256 -keyout mynode.key -out mynode.csr -subj "/C=US/ST=Florida/L=St Petersburg/O=MyCompany/OU=MyOU/CN=mynode/[email protected]" -reqexts OPTS -config -

(换行符可选)

答案2

感谢您的回复。我想了一下,决定寻找一种 python 原生的方法来做到这一点。有足够的信息python 密码学备忘单网站以及其他人,我能够将 python 代码放在一起来生成 CSR。

requires pyOpenSSL


from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend())

with open('mycert.key', 'wb') as f:
     f.write(key.private_bytes(
     encoding=serialization.Encoding.PEM,
     format=serialization.PrivateFormat.TraditionalOpenSSL,
     encryption_algorithm=serialization.NoEncryption()))

from OpenSSL import crypto

# load private key
ftype = crypto.FILETYPE_PEM
with open('mycert.key', 'rb') as f: key = f.read()
key = crypto.load_privatekey(ftype, key)
req    = crypto.X509Req()

alt_name  = [ b"DNS:mynode",
              b"DNS:myF5",
              b"email:[email protected]" ]
key_usage = [ b"Digital Signature",
              b"Key Encipherment" ]
key_usage = [ b"digitalSignature",
              b"keyEncipherment" ]
ext_key_usage = [ b"serverAuth",
                  b"clientAuth" ]

# country (countryName, C)
# state or province name (stateOrProvinceName, ST)
# locality (locality, L)
# organization (organizationName, O)
# organizational unit (organizationalUnitName, OU)
# common name (commonName, CN)

req.get_subject().C  = "US"
req.get_subject().ST = "Florida"
req.get_subject().L  = "St Petersburg"
req.get_subject().O  = "myCompany"
req.get_subject().OU = "MyOU"
req.get_subject().CN = "mynode"
req.add_extensions([
    crypto.X509Extension( b"basicConstraints",
                          False,
                          b"CA:FALSE"),
    crypto.X509Extension( b"keyUsage",
                          False,
                          b",".join(key_usage)),
    crypto.X509Extension( b"subjectAltName",
                          False,
                          b",".join(alt_name))
])

req.set_pubkey(key)
req.sign(key, "sha256")

csr = crypto.dump_certificate_request(ftype, req)
with open("mycert.csr", 'wb') as f: f.write(csr)

相关内容