我尝试使用OpenSSL和Python创建一个签名文件,但我没有收到任何错误消息,但是过程无法正常工作,我无法找到原因。< / p>
以下是我一步一步签署文件并检查签名:
首先我在命令行中创建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.key
和cert.crt
使用如下所示的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.sha256
和my_file.txt.sha256.base64
。此时,我可以解码base64文件并与签名文件进行比较,两者都很好。
问题是当我尝试使用以下命令verify the signature时:
`openssl dgst -sha256 -verify <(openssl x509 -in "cert.crt" -pubkey -noout) -signature my_file.txt.sha256 my_file.csv`
此时我总是收到&#34;验证失败&#34;并且不明白为什么。
也许问题是我缺乏Python的知识,因为当我使用以下命令签署文件时(在步骤1之后和使用2中描述的Python脚本之前),相同的验证工作正常。
openssl dgst -sha256 -sign "cert.key" -out my_file.txt.sha256 my_file.csv
我做错了吗?
更新
基于这些评论,我在python 2.7的本地virtualnv中尝试了这个脚本并且它工作正常,所以问题必须在读/写操作中。
我使用完整的脚本更新此队列,包括读/写操作,因为我可以在本地运行它,但我仍然没有在GAE环境中出现任何错误,并且可以& #39;了解原因。
第一步是使用以下脚本在Google存储(存储桶)中创建和存储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
Here is the 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文件)。之后,我通过谷歌网页面板为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,结果看起来像两个完全不同的文件。
现在,我知道这个问题,但不知道如何解决它。这个问题非常棘手。
答案 0 :(得分:2)
我终于找到了问题。我非常专注于在openssl签名过程中发现问题并且没有注意旧的Ctrl + C / Ctrl + V问题。
出于测试目的,我复制了'Read from GCS' example from this tutorial。
当我将测试移到真实世界的应用程序时,我没有再次阅读该页面,也没有注意到gcs_file.seek(-1024, os.SEEK_END)
。
正如我在原始问题中所说,我不是Python专家,但这行只是阅读GCS文件的一部分,因此签名确实与原始签名不同。
只需缩短我的阅读方法,现在一切正常。