将PEM文件转换为DER格式

5

我目前正在尝试编写一个脚本,使我能够从隐藏服务的私钥文件计算Tor HS地址。为了做到这一点,文件需要转换成DER格式。

使用OpenSSL可以通过以下方式完成:

openssl rsa -in private_key -pubout -outform DER

将以下内容输入python:

base64.b32encode(hashlib.sha1(sys.stdin.read()[22:]).digest()[:10]).lower()'

这段代码将正确返回地址。

然而,我想仅使用Python实现相同的功能。我的问题是,使用pycrypto模块时DER输出不同,因此地址不正确。

key = RSA.importKey(keyfile.read()).publickey()
print(key.exportKey(format='DER'))

会产生不同于openssl调用的输出结果。

这只是允许不同结果的实现问题吗?还是我在某个地方犯了错误?

任何帮助将不胜感激。


在最近的一个项目中,我注意到exportKey方法在某些格式上并不是非常可靠。我不得不重新实现它的一些部分。在使用时要小心。 - Klaus D.
你能在问题中给出DER输出的十六进制示例吗?PEM输入也可能很有用。我猜想两个不同的答案之间。 - Maarten Bodewes
4个回答

10

使用Python将证书转换为DER格式

首先,我们需要加载文件

cert_file = keyfile.read()

然后我们将其转换为pem格式

from OpenSSL import crypto
cert_pem = crypto.load_certificate(crypto.FILETYPE_PEM, cert_file)

现在我们正在生成der格式的输出
即: 输出等于openssl x509 -outform der -in certificate.pem -out certificate.der.


即: 输出等于openssl x509 -outform der -in certificate.pem -out certificate.der.

cert_der = crypto.dump_certificate(crypto.FILETYPE_ASN1, cert_pem)

6
我在寻找类似的内容,截至2019年3月,OpenSSL建议使用pyca/cryptography而不是crypto模块。(来源
接下来您需要做的是将PEM转换为DER格式。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

with open("id_rsa", "rb") as keyfile:
    # Load the PEM format key
    pemkey = serialization.load_pem_private_key(
        keyfile.read(),
        None,
        default_backend()
    )
    # Serialize it to DER format
    derkey = pemkey.private_bytes(
        serialization.Encoding.DER,
        serialization.PrivateFormat.TraditionalOpenSSL,
        serialization.NoEncryption()
    )
    # And write the DER format to a file
    with open("key.der", "wb") as outfile:
        outfile.write(derkey)


这是非常有帮助的回复。我实现了相同的功能,但使用公钥代替私钥。对于公钥,这就是亚马逊EC2计算MD5的方法。 - Brian

4
我想将证书文件从DER格式转换为PEM格式,而不是密钥文件,但谷歌把我带到了这里。感谢@alleen1的答案,我可以将证书或密钥从DER格式转换为PEM格式,反之亦然。
第一步,加载文件。
第二步,保存为所需格式。
我省略了获取"pem_data"和"der_data"的过程,您可以从文件或其他地方获取它们。它们应该是字节而不是字符串,在需要时使用.encode()方法。
from cryptography import x509
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

# Step one, load the file. 

# Load key file
# PEM 
key = serialization.load_pem_private_key(pem_data, None, default_backend())
# DER
key = serialization.load_der_private_key(der_data, None, default_backend())

# Load cert file
# PEM
cert = x509.load_pem_x509_certificate(pem_data, default_backend())
# DER
cert = x509.load_der_x509_certificate(der_data, default_backend())

# Step two,save it to the format you want.
# PEM key
key_val = key.private_bytes(
              serialization.Encoding.PEM,
              serialization.PrivateFormat.TraditionalOpenSSL,
              serialization.NoEncryption()
          )
# DER key
key_val = key.private_bytes(
              serialization.Encoding.DER,
              serialization.PrivateFormat.TraditionalOpenSSL,
              serialization.NoEncryption()
          )

# PEM cert
cert_val = cert.public_bytes(serialization.Encoding.PEM)
# DER cert
cert_val = cert.public_bytes(serialization.Encoding.DER)

0
最初的问题是:“从私钥中提取公钥”,这是因为openSSL命令在初始问题中指定了“pubout”。
使用OpenSSL可以通过以下方式完成:(请注意,“pubout”将输出定义为仅公钥)
openssl ALGORITHM_USED -in private_key -pubout -outform DER

但是使用Python加密模块,您可以从私钥中提取公钥(请注意,这似乎适用于RSA和基于EC的加密)。

使用Python:

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.backends import default_backend

    # Create private key (example uses elliptic curve encryption)

    priv_key = ec.generate_private_key(ec.SECP256K1, default_backend())

    pub_key = priv_key.public_key()

    pub_key_pem = pub_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
        )

    with open('public_key.pem', 'wb') as outfile:
        outfile.write(public_key_pem)

有关密码学文档的更多信息:https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/#cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接