繁体   English   中英

验证使用python签名的文件时遇到的问题

[英]Problems to verify a file signed with python

我正在尝试使用OpenSSL和Python创建一个签名文件,但是没有收到任何错误消息,但是该过程无法正常工作,我找不到原因。

以下是我逐步签名文件并检查签名的步骤:

  1. 首先,我在命令行中创建crt

    openssl req -nodes -x509 -sha256 -newkey rsa:4096 -keyout "cert.key" -out "cert.crt" -subj "/C=BR/ST=SP/L=SP/O=Company/OU=IT Dept/CN=cert"

此时,我有两个文件: cert.keycert.crt

  1. 使用如下所示的Python脚本对文件进行签名:

     import os.path from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from base64 import b64encode, b64decode def __init__(self): folder = os.path.dirname(os.path.realpath(__file__)) file_path = os.path.join(folder, '../static/cert.key') self.key = open(file_path, "r").read() def sign_data(self, my_file): rsakey = RSA.importKey(self.key) # I opened the cert.key in __init__ signer = PKCS1_v1_5.new(rsakey) digest = SHA256.new() digest.update(my_file) sign = signer.sign(digest) return sign, b64encode(sign) 

一切正常,保存文件后,我还有另外三个文件: my_file.csv (原始文件), my_file.txt.sha256my_file.txt.sha256.base64 此时,我可以解码base64文件并与已签名的文件进行比较,两者都很好。

问题是当我尝试使用以下命令来验证签名时

`openssl dgst -sha256 -verify  <(openssl x509 -in "cert.crt"  -pubkey -noout) -signature my_file.txt.sha256 my_file.csv`

在这一点上,我总是收到“验证失败”,并且不明白为什么。

也许问题出在我缺乏Python的知识,因为当我使用以下命令(在步骤1之后和使用2中描述的Python脚本之前)对文件签名时,相同的验证工作正常。

openssl dgst -sha256 -sign "cert.key" -out my_file.txt.sha256 my_file.csv

我做错什么了吗?

更新

根据评论,我在python 2.7的本地virtualnv中尝试了该脚本,并且该脚本可以正常工作,因此问题必须出在读/写操作中。

我正在使用完整的脚本(包括读/写操作)更新此问题,因为我可以在本地运行它,但在GAE环境中仍然没有收到任何错误,也无法理解原因。

第一步是使用以下脚本在CSV存储(桶)中创建和存储CSV文件

import logging
import string
import cloudstorage as gcs
from google.appengine.api import app_identity

def create_csv_file(self, filename, cursor=None):    
    filename = '/' + self.bucket_name + filename
    try:
        write_retry_params = gcs.RetryParams(backoff_factor=1.1)
        # the cursor stores a MySQL result set
        if cursor is not None:
            gcs_file = gcs.open(filename,
                                'w',
                                content_type='text/csv',
                                retry_params=write_retry_params)
            for row in cursor:
                gcs_file.write(','.join(map(str, row)) + '\n')
            gcs_file.close()
    except Exception as ex:
        logging.critical("Problem to write in th GC Storage with the exception:{}".format(ex))
        raise ex

它可以正常工作,并将CSV存储在Google存储设备中的正确路径中。 在那部分之后,下一个读/写操作是文件的签名。

def cert_file(self, original_filename):
    filename = '/' + self.bucket_name + original_filename
    cert = Cert() # This class just has one method, that is that described in my original question and is used to sign the file.

    with gcs.open(filename) as cloudstorage_file:
        cloudstorage_file.seek(-1024, os.SEEK_END)
        signed_file, encoded_signed_file = cert.sign_data(cloudstorage_file.read()) #the method to sign the file
    signature_content = encoded_signed_file

    signed_file_name = string.replace(original_filename, '.csv', '.txt.sha256')
    encoded_signed_file_name = string.replace(signed_file_name, '.txt.sha256', '.txt.sha256.base64')

    self.inner_upload_file(signed_file, signed_file_name)
    self.inner_upload_file(encoded_signed_file, encoded_signed_file_name)

    return signed_file_name, encoded_signed_file_name, signature_content

inner_upload_file ,只需将新文件保存在同一存储桶中:

def inner_upload_file(self, file_data, filename):
    filename = '/' + self.bucket_name + filename
    try:
        write_retry_params = gcs.RetryParams(backoff_factor=1.1)
        gcs_file = gcs.open(filename,
                            'w',
                            content_type='application/octet-stream',
                            retry_params=write_retry_params)
        gcs_file.write(file_data)
        gcs_file.close()
    except Exception as ex:
        logging.critical("Problem to write in th GC Storage with the exception:{}".format(ex))
        raise ex

这是app.yaml供参考。 命令行生成的cert.key和cert.crt存储在app文件夹内的静态文件夹中(我的app.yaml位于同一目录中)。

更新2

按照注释,我尝试在本地运行签名过程,然后比较文件。 以下是逐步设置和结果。

首先,我修改了签名过程,使其以python sign.py file_name身份运行。

#!/usr/bin/python

import sys
import os
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64encode, b64decode

file_path = 'static/cert.key'
key = open(file_path, "rb").read()

rsakey = RSA.importKey(key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
file_object  = open(sys.argv[1], "r")
digest.update(file_object.read())
sign = signer.sign(digest)
signed_path = "signed"
f = open(signed_path + '.txt.sha256', 'w')
f.write(sign)
f.close()
f2 = open(signed_path + '.txt.sha256.base64', 'w')
f2.write(b64encode(sign))
f2.close()

我运行了自动流程,该流程将签名文件保存在GCS的存储桶中(连同原始CSV文件一起)。 之后,我通过Google网页面板下载了GCS的两个文件。

我使用刚下载的CSV文件在带有python 2.7.10的virtualenv中运行了python sign.py gcs_file_original.csv命令。

之后,我将两个签名文件与cmp -b gcs_signed.txt.sha256 locally_signed.txt.sha256结果为:

gcs_signed.txt.sha256 local_signed.txt.sha256不同:字节1,第1行为24 ^ T 164 t

使用VisualBinaryDiff ,结果看起来像两个完全不同的文件。

签名之间的差异

现在,我知道了问题,但是对如何解决它一无所知。 这个问题非常棘手。

我终于找到了问题。 我非常专注于在openssl签名过程中发现问题,而没有注意旧的Ctrl + C / Ctrl + V问题。

为了进行测试,我复制了本教程中“从GCS读取”示例

当我将测试移至实际应用程序时,我没有再阅读该页面,也没有注意到gcs_file.seek(-1024, os.SEEK_END)

正如我在原始问题中所说的那样,我不是Python专家,但是此行仅读取GCS文件的一部分,因此签名确实与原始文件不同。

只需减少我的阅读方法的范围即可,现在一切正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM