如何在python中验证签名文件 [英] How to verify a signed file in python

查看:215
本文介绍了如何在python中验证签名文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用openssl SHA256和私钥对文件进行了签名,如下所示:

I have signed a file using openssl SHA256 and a private key as follows:

with subprocess.Popen(
        # Pipe the signature to openssl to convert it from raw binary encoding to base64 encoding.
        # This will prevent any potential corruption due to line ending conversions, and also allows 
        # a human to read and copy the signature (e.g. for manual verification).
        'openssl dgst -sha256 -sign private.key sign_me.zip | openssl base64 > signature.sha256',
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        shell=True,
) as proc:
    out, _ = proc.communicate()

要求

  1. 我需要使用signature.sha256public_key.crt来验证sign_me.zip未被修改.
  2. 与Python 3.2-3.4兼容
  3. 需要同时在Windows和Redhat上运行,并且不能保证OpenSSL将位于路径或已知位置.理想情况下,我想使用一个核心的Python模块,但是如果降低复杂性,我将考虑使用第三方模块.
  1. I need to use signature.sha256 and public_key.crt to verify that sign_me.zip has not been modified.
  2. Compatible with Python 3.2 - 3.4
  3. Needs to work on both Windows and Redhat, and there is no guarantee that OpenSSL will be on the path or in a known location. Ideally I'd like to use a core Python module, but I will consider a 3rd party module if it reduces complexity.

我尝试过的东西

我已经做了很多搜索,试图弄清楚该怎么做,但是我一直没有找到满意的答案.这是我尝试和/或研究过的事情的列表:

What I've Tried

I've done a lot of searching trying to figure out how to do this, but I haven't been able to find a satisfactory answer. Here is a list of things I've tried and/or researched:

  • 我能够通过以下shell命令手动验证签名.由于要求3,这不能作为永久解决方案.

  • I am able to manually verify the signature via the following shell command. This won't work as a permanent solution due to requirement 3.

openssl dgst -sha256 -verify <(openssl x509 -in public_key.crt -pubkey -noout) -signature signature.sha256 sign_me.zip

我发现了这个问题,几乎正是我想做的.近两年没有得到答复,甚至没有发表评论.它提到了 ssl python库,该库主要处理客户端/服务器证书和套接字.

I found this question, which is almost exactly what I want to do. It hasn't been answered or even commented on in nearly 2 years. It mentions the ssl python library, which deals mostly with client/server certificates and sockets.

也许我缺少明显的东西?我在安全性/加密/散列方面还没有做很多工作,因此欢迎您提供反馈.

Perhaps I'm missing something obvious? I haven't done much work with security/encryption/hashing, so feedback is welcome.

推荐答案

感谢Patrick Mevzek向我指出了正确的方向.最终,我使用密码学模块找到了以下解决方案.我最终改变了我对文件签名的方式,以匹配以后将对其进行验证的方式.

Thanks to Patrick Mevzek for pointing me in the right direction. I eventually found the following solution to my problem using the Cryptography module. I ended up changing how I'm signing the file to match how I will later verify it.

密钥生成:

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

# Generate the public/private key pair.
private_key = rsa.generate_private_key(
    public_exponent = 65537,
    key_size = 4096,
    backend = default_backend(),
)

# Save the private key to a file.
with open('private.key', 'wb') as f:
    f.write(
        private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.NoEncryption(),
        )
    )

# Save the public key to a file.
with open('public.pem', 'wb') as f:
    f.write(
        private_key.public_key().public_bytes(
            encoding = serialization.Encoding.PEM,
            format = serialization.PublicFormat.SubjectPublicKeyInfo,
        )
    )

签名:

import base64
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding

# Load the private key. 
with open('private.key', 'rb') as key_file: 
    private_key = serialization.load_pem_private_key(
        key_file.read(),
        password = None,
        backend = default_backend(),
    )

# Load the contents of the file to be signed.
with open('payload.dat', 'rb') as f:
    payload = f.read()

# Sign the payload file.
signature = base64.b64encode(
    private_key.sign(
        payload,
        padding.PSS(
            mgf = padding.MGF1(hashes.SHA256()),
            salt_length = padding.PSS.MAX_LENGTH,
        ),
        hashes.SHA256(),
    )
)
with open('signature.sig', 'wb') as f:
    f.write(signature)

验证:

import base64
import cryptography.exceptions
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.serialization import load_pem_public_key

# Load the public key.
with open('public.pem', 'rb') as f:
    public_key = load_pem_public_key(f.read(), default_backend())

# Load the payload contents and the signature.
with open('payload.dat', 'rb') as f:
    payload_contents = f.read()
with open('signature.sig', 'rb') as f:
    signature = base64.b64decode(f.read())

# Perform the verification.
try:
    public_key.verify(
        signature,
        payload_contents,
        padding.PSS(
            mgf = padding.MGF1(hashes.SHA256()),
            salt_length = padding.PSS.MAX_LENGTH,
        ),
        hashes.SHA256(),
    )
except cryptography.exceptions.InvalidSignature as e:
    print('ERROR: Payload and/or signature files failed verification!')

这篇关于如何在python中验证签名文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆